Kubectl Commands
Common kubectl commands for inspecting, triggering, and managing site recovery resources
Use kubectl to inspect, create, update, and delete Site Recovery custom resources directly on your primary, DR, or quorum clusters. Because Site Recovery implements the Kubernetes operator pattern, kubectl is the authoritative interface for declaring protection intent and observing operator-driven reconciliation — every resource you create or patch triggers a controller response without requiring any additional tooling.
kubectl [--kubeconfig <path>] [--context <context>] <verb> <resource> [name] [-n <namespace>] [flags]
All Site Recovery custom resources live under the API group siterecovery.trilio.io. The examples on this page use explicit --kubeconfig flags to make cluster targeting clear; substitute your own kubeconfig paths or contexts as appropriate.
The flags below are standard kubectl flags that are particularly relevant when working across the three clusters that make up a Site Recovery deployment.
| Flag | Short | Default | Description |
|---|---|---|---|
--kubeconfig | ~/.kube/config | Path to the kubeconfig file. Specify different files to target the quorum, primary, or DR cluster. | |
--context | Current context | Override the active kubeconfig context without switching files. | |
-n, --namespace | -n | default | Namespace in which the resource lives. DR deployments use the dr-<name> namespace on the quorum cluster. |
-o, --output | -o | (table) | Output format. Use yaml to see full resource specs, json for piping to jq, or jsonpath for targeted field extraction. |
--watch | -w | false | Stream resource updates. Useful for monitoring failover or protection progress in real time. |
--for | Used with kubectl wait to block until a specific condition is met, such as a field reaching a target value. | ||
--timeout | 30s | Maximum time to wait when used with kubectl wait. | |
--type | strategic | Patch strategy for kubectl patch. Use merge for simple field updates on Site Recovery resources. | |
-p | Inline patch body for kubectl patch. | ||
-f | Path to a manifest file or - for stdin, used with apply, create, and delete. | ||
-l, --selector | -l | Label selector for filtering resource lists. | |
--all-namespaces | -A | false | List resources across all namespaces. Useful when auditing protection state cluster-wide. |
The table below maps common kubectl verbs to their Site Recovery use cases.
| Verb | Description |
|---|---|
get | List or describe Site Recovery resources. Add -o yaml for full spec and status. |
apply | Create or update a resource from a manifest file. The preferred way to declare ProtectionGroups, ProtectionRequests, FailoverRequests, TestFailovers, and DRBDReplicationPolicies. |
patch | Modify a specific field of an existing resource. Use --type merge when updating fields such as spec.virtualMachines or spec.desiredState. |
delete | Remove a Site Recovery resource. Deleting a FailoverRequest or TestFailover after completion is safe; deleting a ProtectionGroup or ProtectionRequest removes protection intent and may trigger controller cleanup. |
describe | Show events and a human-readable summary for a resource. The Events section reveals controller reconciliation activity and error messages. |
wait | Block until a resource reaches a target condition. Use this in scripts to synchronize between steps, for example waiting for a FailoverRequest to complete. |
logs | Stream controller logs. Target controller pods by label to observe reconciliation decisions. |
rollout restart | Restart a controller deployment. Use this after updating CRDs or credentials to force controllers to reload. |
| Variable | Default | Description |
|---|---|---|
KUBECONFIG | ~/.kube/config | Colon-separated list of kubeconfig files. Set this to load multiple cluster configs simultaneously and reference them by context name. |
KUBECTL_EXTERNAL_DIFF | Path to a diff tool used by kubectl diff. Useful for previewing manifest changes before applying them to protection resources. |
| Code | Meaning |
|---|---|
0 | Command succeeded. The resource was found, applied, patched, or deleted as requested. |
1 | General error. Includes authentication failures, API server unreachable, or invalid manifest syntax. Check stderr for the error message. |
1 | Resource not found when using get, describe, or delete with a specific name. |
1 | Timeout expired when using kubectl wait --timeout. The resource did not reach the expected condition within the allowed time. |
The examples below are organized by workflow stage. Each example shows the command, the cluster it targets, and representative output. Replace <name>, <namespace>, and kubeconfig paths with values from your environment.
List all Site Recovery custom resource types
Confirm that the Site Recovery CRDs are installed on the target cluster.
kubectl --kubeconfig ~/.kube/config-quorum \
get crds | grep siterecovery.trilio.io
Expected output:
drbdreplicationpolicies.siterecovery.trilio.io 2025-01-15T10:00:00Z
drbdvolumes.siterecovery.trilio.io 2025-01-15T10:00:00Z
failoverrequests.siterecovery.trilio.io 2025-01-15T10:00:00Z
protectiongroups.siterecovery.trilio.io 2025-01-15T10:00:00Z
protectionrequests.siterecovery.trilio.io 2025-01-15T10:00:00Z
replicationgroupstatuses.siterecovery.trilio.io 2025-01-15T10:00:00Z
rpoevents.siterecovery.trilio.io 2025-01-15T10:00:00Z
testfailovers.siterecovery.trilio.io 2025-01-15T10:00:00Z
Create a ProtectionGroup
A ProtectionGroup declares which VMs should fail over together as a unit on your primary cluster. Apply the manifest from the primary cluster context.
kubectl --kubeconfig ~/.kube/config-primary apply -f - <<EOF
apiVersion: siterecovery.trilio.io/v1alpha1
kind: ProtectionGroup
metadata:
name: production-pg
namespace: default
spec:
desiredState: running
virtualMachines:
- name: prod-vm-1
- name: prod-vm-2
EOF
Expected output:
protectiongroup.siterecovery.trilio.io/production-pg created
Inspect ProtectionGroup status
After the protection-group-controller reconciles, check the aggregated replication state. Run this on whichever cluster hosts the ProtectionGroup resource.
kubectl --kubeconfig ~/.kube/config-primary \
get protectiongroup production-pg -n default
Expected output:
NAME STATE VMS REPLICATION HEALTH AGE
production-pg Active 2 synchronous Healthy 5m
For the full spec and status including per-VM replication state:
kubectl --kubeconfig ~/.kube/config-primary \
get protectiongroup production-pg -n default -o yaml
Expected output (abbreviated):
apiVersion: siterecovery.trilio.io/v1alpha1
kind: ProtectionGroup
metadata:
name: production-pg
namespace: default
status:
state: Active
replicationHealth: Healthy
currentState: running
protectedVMs:
- name: prod-vm-1
namespace: default
replicationStatus: Protected
- name: prod-vm-2
namespace: default
replicationStatus: Protected
Add a VM to an existing ProtectionGroup
Use a merge patch to append a VM to the spec.virtualMachines list. You must supply the full list because the merge patch replaces the array.
kubectl --kubeconfig ~/.kube/config-primary \
patch protectiongroup production-pg -n default \
--type merge \
-p '{
"spec": {
"virtualMachines": [
{"name": "prod-vm-1"},
{"name": "prod-vm-2"},
{"name": "prod-vm-3"}
]
}
}'
Expected output:
protectiongroup.siterecovery.trilio.io/production-pg patched
Verify the update was accepted:
kubectl --kubeconfig ~/.kube/config-primary \
get protectiongroup production-pg -n default \
-o jsonpath='{.spec.virtualMachines}' | jq .
Expected output:
[
{"name": "prod-vm-1"},
{"name": "prod-vm-2"},
{"name": "prod-vm-3"}
]
Create a ProtectionRequest (DRBD Operator deployments)
In the DRBD Operator deployment model, request protection for a single VM. The protection-controller on the quorum cluster validates the VM, creates DRBDVolume resources, and switches the VM to a DRBD-backed frontend PVC.
kubectl --kubeconfig ~/.kube/config-quorum apply -f - <<EOF
apiVersion: siterecovery.trilio.io/v1alpha1
kind: ProtectionRequest
metadata:
name: protect-web-vm-1
namespace: dr-production
spec:
virtualMachine:
name: web-vm-1
namespace: default
replicationPolicy: drbd-sync-policy
EOF
Expected output:
protectionrequest.siterecovery.trilio.io/protect-web-vm-1 created
Watch the lifecycle progress:
kubectl --kubeconfig ~/.kube/config-quorum \
get protectionrequest protect-web-vm-1 -n dr-production -w
Expected output:
NAME STATUS AGE
protect-web-vm-1 Validating 5s
protect-web-vm-1 Protecting 18s
protect-web-vm-1 Protected 2m10s
Inspect a DRBDVolume
After a ProtectionRequest is processed, the controller creates DRBDVolume resources. Check sync progress on the primary cluster.
kubectl --kubeconfig ~/.kube/config-primary \
get drbdvolumes -n default
Expected output:
NAME SYNC FRONTEND-PVC AGE
pvc-a1b2c3d4-e5f6-7890-abcd-ef1234567890 100% web-vm-1-frontend-pvc 8m
For detailed sync state and frontend PVC reference:
kubectl --kubeconfig ~/.kube/config-primary \
get drbdvolume pvc-a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-n default -o yaml
Inspect a DRBDReplicationPolicy
A DRBDReplicationPolicy defines how volumes replicate between clusters. Inspect its storage class mappings and protocol selection.
kubectl --kubeconfig ~/.kube/config-primary \
get drbdreplicationpolicy drbd-sync-policy -n default -o yaml
Expected output (abbreviated):
apiVersion: siterecovery.trilio.io/v1alpha1
kind: DRBDReplicationPolicy
metadata:
name: drbd-sync-policy
namespace: default
spec:
protocol: C
storageClassMappings:
- primary: fast-ssd
dr: fast-ssd-dr
replicationEndpoints:
primary: 192.168.10.10:7000
dr: 192.168.20.10:7000
Check replication health with ReplicationGroupStatus
The replication-monitor writes ReplicationGroupStatus resources that provide an aggregated health view. Check this on the quorum cluster for operator-level visibility.
kubectl --kubeconfig ~/.kube/config-quorum \
get replicationgroupstatus -n dr-production
Expected output:
NAME HEALTH LAST-SYNC AGE
production-pg Healthy 2025-01-15T14:23:00Z 2d
For per-volume sync state:
kubectl --kubeconfig ~/.kube/config-quorum \
describe replicationgroupstatus production-pg -n dr-production
List RPOEvents to audit replication lag violations
RPOEvent resources are written by the replication-monitor when lag thresholds are exceeded. Review them to audit data loss risk.
kubectl --kubeconfig ~/.kube/config-quorum \
get rpoevents -n dr-production
Expected output:
NAME PROTECTION-GROUP LAG SEVERITY AGE
rpoevent-20250115-142300 production-pg 45s Warning 2h
rpoevent-20250114-091500 production-pg 120s Critical 1d
Inspect a specific event for full context:
kubectl --kubeconfig ~/.kube/config-quorum \
get rpoevent rpoevent-20250115-142300 -n dr-production -o yaml
Trigger a planned failover
A planned (graceful) failover stops VMs on the primary cluster before promoting volumes on the DR cluster, ensuring zero data loss. Apply a FailoverRequest to the quorum cluster; the failover-controller watches for it and orchestrates the sequence.
kubectl --kubeconfig ~/.kube/config-quorum apply -f - <<EOF
apiVersion: siterecovery.trilio.io/v1alpha1
kind: FailoverRequest
metadata:
name: planned-failover-production
namespace: dr-production
spec:
protectionGroup: production-pg
failoverType: planned
targetCluster: dr-cluster
EOF
Expected output:
failoverrequest.siterecovery.trilio.io/planned-failover-production created
Monitor progress in real time:
kubectl --kubeconfig ~/.kube/config-quorum \
get failoverrequest planned-failover-production \
-n dr-production -w
Expected output:
NAME TYPE PHASE STATUS AGE
planned-failover-production planned StoppingOnSource InProgress 15s
planned-failover-production planned WaitingForDRBD InProgress 45s
planned-failover-production planned StartingOnTarget InProgress 1m10s
planned-failover-production planned Completed Succeeded 3m42s
Wait for completion in a script:
kubectl --kubeconfig ~/.kube/config-quorum \
wait failoverrequest planned-failover-production \
-n dr-production \
--for=jsonpath='{.status.state}'=Completed \
--timeout=600s
Trigger an unplanned failover
An unplanned (emergency) failover promotes DR volumes and starts VMs without waiting for a graceful shutdown on the primary cluster. Use this when the primary cluster is unavailable.
kubectl --kubeconfig ~/.kube/config-quorum apply -f - <<EOF
apiVersion: siterecovery.trilio.io/v1alpha1
kind: FailoverRequest
metadata:
name: emergency-failover-production
namespace: dr-production
spec:
protectionGroup: production-pg
failoverType: unplanned
targetCluster: dr-cluster
EOF
Expected output:
failoverrequest.siterecovery.trilio.io/emergency-failover-production created
Inspect a FailoverRequest after completion
After a failover completes, review the full status to confirm which phase each step reached and whether any errors were recorded.
kubectl --kubeconfig ~/.kube/config-quorum \
describe failoverrequest planned-failover-production \
-n dr-production
The Events section of the output shows the controller's step-by-step reconciliation decisions and any warnings encountered during the operation.
Initiate a test failover (DRBD Operator deployments only)
A TestFailover performs a non-disruptive DR validation by snapshotting production volumes, booting test VMs on the DR cluster, running verification checks, and cleaning up — without affecting production workloads. Test failover is only supported in DRBD Operator deployment models.
kubectl --kubeconfig ~/.kube/config-primary apply -f - <<EOF
apiVersion: siterecovery.trilio.io/v1alpha1
kind: TestFailover
metadata:
name: tf-production-pg-jan15
namespace: default
spec:
protectionGroup: production-pg
EOF
Expected output:
testfailover.siterecovery.trilio.io/tf-production-pg-jan15 created
Watch the test failover lifecycle:
kubectl --kubeconfig ~/.kube/config-primary \
get testfailover tf-production-pg-jan15 -n default -w
Expected output:
NAME PHASE STATUS AGE
tf-production-pg-jan15 Snapshotting InProgress 10s
tf-production-pg-jan15 ProvisioningTestVMs InProgress 40s
tf-production-pg-jan15 Verifying InProgress 2m
tf-production-pg-jan15 CleaningUp InProgress 4m
tf-production-pg-jan15 Completed Succeeded 5m30s
Watch controller logs during a failover
To observe what the failover-controller is doing during an active FailoverRequest, stream its logs from the quorum cluster. Controllers run in the dr-<deployment-name> namespace.
kubectl --kubeconfig ~/.kube/config-quorum \
logs -n dr-production \
-l app=failover-controller \
--follow
For the protection-group-controller running on the primary cluster:
kubectl --kubeconfig ~/.kube/config-primary \
logs -n default \
-l app=protection-group-controller \
--follow
Watch controller logs for the test-failover-controller
The test-failover-controller runs on the primary and DR clusters. Stream its logs to observe snapshot creation and test VM provisioning.
kubectl --kubeconfig ~/.kube/config-dr \
logs -n default \
-l app=test-failover-controller \
--follow
List all Protection Groups across namespaces
When managing a multi-tenant quorum with multiple DR deployments, use --all-namespaces to audit protection state across every deployment namespace.
kubectl --kubeconfig ~/.kube/config-quorum \
get protectiongroups --all-namespaces
Expected output:
NAMESSPACE NAME STATE VMS HEALTH AGE
dr-production production-pg Active 3 Healthy 5d
dr-staging staging-pg Active 1 Healthy 2d
dr-analytics analytics-pg Active 2 Degraded 12h
Describe a ProtectionGroup to view controller events
The Events section reveals why a ProtectionGroup entered a Degraded state and what the controller attempted.
kubectl --kubeconfig ~/.kube/config-primary \
describe protectiongroup production-pg -n default
Look for lines beginning with Warning in the Events section to identify replication or validation errors.
Delete a completed FailoverRequest
Completed FailoverRequest resources persist in the cluster as an audit record. Delete them when they are no longer needed.
kubectl --kubeconfig ~/.kube/config-quorum \
delete failoverrequest planned-failover-production \
-n dr-production
Expected output:
failoverrequest.siterecovery.trilio.io/planned-failover-production deleted
Restart a controller after a credential or CRD update
If you update cluster credentials or apply CRD schema changes, restart the affected controller deployment so it reloads its configuration.
# Restart the failover-controller on the quorum cluster
kubectl --kubeconfig ~/.kube/config-quorum \
rollout restart deployment/failover-controller \
-n dr-production
# Confirm rollout completes
kubectl --kubeconfig ~/.kube/config-quorum \
rollout status deployment/failover-controller \
-n dr-production
Expected output:
deployment.apps/failover-controller successfully rolled out