Trilio Site Recovery for Kubernetes/OpenShift Virtualization
CLI reference

Kubectl Commands

Common kubectl commands for inspecting, triggering, and managing site recovery resources


Description

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.


Synopsis

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.


Flags

The flags below are standard kubectl flags that are particularly relevant when working across the three clusters that make up a Site Recovery deployment.

FlagShortDefaultDescription
--kubeconfig~/.kube/configPath to the kubeconfig file. Specify different files to target the quorum, primary, or DR cluster.
--contextCurrent contextOverride the active kubeconfig context without switching files.
-n, --namespace-ndefaultNamespace 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-wfalseStream resource updates. Useful for monitoring failover or protection progress in real time.
--forUsed with kubectl wait to block until a specific condition is met, such as a field reaching a target value.
--timeout30sMaximum time to wait when used with kubectl wait.
--typestrategicPatch strategy for kubectl patch. Use merge for simple field updates on Site Recovery resources.
-pInline patch body for kubectl patch.
-fPath to a manifest file or - for stdin, used with apply, create, and delete.
-l, --selector-lLabel selector for filtering resource lists.
--all-namespaces-AfalseList resources across all namespaces. Useful when auditing protection state cluster-wide.

Subcommands

The table below maps common kubectl verbs to their Site Recovery use cases.

VerbDescription
getList or describe Site Recovery resources. Add -o yaml for full spec and status.
applyCreate or update a resource from a manifest file. The preferred way to declare ProtectionGroups, ProtectionRequests, FailoverRequests, TestFailovers, and DRBDReplicationPolicies.
patchModify a specific field of an existing resource. Use --type merge when updating fields such as spec.virtualMachines or spec.desiredState.
deleteRemove 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.
describeShow events and a human-readable summary for a resource. The Events section reveals controller reconciliation activity and error messages.
waitBlock until a resource reaches a target condition. Use this in scripts to synchronize between steps, for example waiting for a FailoverRequest to complete.
logsStream controller logs. Target controller pods by label to observe reconciliation decisions.
rollout restartRestart a controller deployment. Use this after updating CRDs or credentials to force controllers to reload.

Environment variables
VariableDefaultDescription
KUBECONFIG~/.kube/configColon-separated list of kubeconfig files. Set this to load multiple cluster configs simultaneously and reference them by context name.
KUBECTL_EXTERNAL_DIFFPath to a diff tool used by kubectl diff. Useful for previewing manifest changes before applying them to protection resources.

Exit codes
CodeMeaning
0Command succeeded. The resource was found, applied, patched, or deleted as requested.
1General error. Includes authentication failures, API server unreachable, or invalid manifest syntax. Check stderr for the error message.
1Resource not found when using get, describe, or delete with a specific name.
1Timeout expired when using kubectl wait --timeout. The resource did not reach the expected condition within the allowed time.

Examples

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