DRPlacementControl CRD
DRPlacementControl CRD
Overview
The DRPlacementControl (DRPC) custom resource is the primary interface for protecting and managing applications with disaster recovery capabilities. Created by users in the application namespace on the OCM hub cluster, it orchestrates:
- Initial DR protection of applications deployed on the preferred cluster
- Failover operations to peer clusters during disasters
- Planned relocation between clusters
The DRPC is the control plane for application DR - it creates and manages VolumeReplicationGroup (VRG) resources on managed clusters via ManifestWork, coordinates with OCM Placement, and tracks DR state.
Lifecycle: One DRPC per application. Created when enabling DR protection, modified to trigger DR operations, deleted when removing DR protection.
API Group and Version
- API Group:
ramendr.openshift.io - API Version:
v1alpha1 - Kind:
DRPlacementControl - Short Name:
drpc - Scope: Namespaced
Spec Fields
Required Fields
placementRef (v1.ObjectReference)
Reference to the OCM Placement resource that selects where the application runs.
Requirements:
- Must exist in the same namespace as DRPC
- Immutable after creation
- Supported kinds:
Placement,PlacementRule(deprecated)
Example:
placementRef:
kind: Placement
name: my-app-placement
How it works: DRPC modifies the Placement decisions to control which cluster runs the application during DR operations.
drPolicyRef (v1.ObjectReference)
Reference to the DRPolicy that defines the DR topology and replication configuration.
Requirements:
- DRPolicy must exist (cluster-scoped resource)
- Immutable after creation
- DRPolicy must have exactly 2 clusters
Example:
drPolicyRef:
name: dr-policy
pvcSelector (metav1.LabelSelector)
Label selector to identify which PVCs in the application namespace need DR protection.
Requirements:
- Immutable after creation
- Must match labels on PVCs you want to protect
Example:
pvcSelector:
matchLabels:
app: my-app
protect: "true"
Best practice: Use specific labels to avoid protecting unwanted PVCs (e.g., cache volumes).
Optional Fields
preferredCluster (string)
The cluster name where the application should run and return to after relocate.
Behavior:
- If set, application deploys to this cluster, if not already deployed or deployed elsewhere
- During relocate, application returns to this cluster
- Can be changed to relocate application
Example:
preferredCluster: east-cluster
failoverCluster (string)
The target cluster for failover operations.
When to use: Set this along with action: Failover to trigger a failover.
Example:
failoverCluster: west-cluster
action: Failover
Note: For relocate operations, change preferredCluster instead and
action to Relocate
action (DRAction)
The DR action to perform: Failover or Relocate.
Valid values:
Failover- Recover application onfailoverCluster(assumes source is down)Relocate- Migrate/Relocate application to target cluster (planned operation)
Example:
# Trigger failover
action: Failover
failoverCluster: west-cluster
# Trigger relocate
action: Relocate
preferredCluster: east-cluster
protectedNamespaces ([]string)
List of namespaces to protect when DRPC is created in the RamenOpsNamespace namespace.
Requirements:
- DRPC and PlacementRef must be in RamenOpsNamespace (from RamenConfig)
- Resources in these namespaces are treated as unmanaged
- Typically used with Recipes to control capture order
Example:
protectedNamespaces:
- app-namespace-1
- app-namespace-2
- app-config-namespace
Use case: Multi-namespace applications or shared configuration namespaces.
kubeObjectProtection (KubeObjectProtectionSpec)
Configuration for protecting Kubernetes resources (not just PVCs).
Fields:
captureInterval(metav1.Duration) - How often to capture Kubernetes objects (default: 5m)recipeRef(RecipeRef) - Reference to Recipe for custom workflowsrecipeParameters(map[string][]string) - Parameters for RecipekubeObjectSelector(metav1.LabelSelector) - Selector for objects to protect
Example:
kubeObjectProtection:
captureInterval: 5m
recipeRef:
name: mysql-recipe
namespace: my-app
When to use:
- Discovered applications (no GitOps)
- Recipe-based protection for stateful apps
- Not needed for GitOps (Git is source of truth)
volSyncSpec (VolSyncSpec)
Configuration for VolSync-based replication (sync DR).
Example:
volSyncSpec:
disabled: false
Status Fields
The DRPC status provides detailed information about the DR state and progress.
phase (DRState)
Current state of the DRPC.
States:
WaitForUser- Waiting for user action after hub recoveryInitiating- Action (Deploy/Failover/Relocate) preparing for executionDeploying- Initial deployment in progressDeployed- Application running normally with DR protectionFailingOver- Failover operation in progressFailedOver- Application has been failed overRelocating- Relocation operation in progressRelocated- Application has been relocatedDeleting- DRPC deletion in progress
observedGeneration (int64)
The generation of the DRPC spec that was last processed.
Use: Compare with metadata.generation to see if changes are processed.
actionStartTime (metav1.Time)
When the current DR action started.
actionDuration (metav1.Duration)
How long the current action has been running.
progression (ProgressionStatus)
Detailed progress indicator for the current operation.
Deploy progressions (during initial deployment):
CreatingMW- Creating ManifestWork for VRGUpdatingPlRule- Updating Placement RuleEnsuringVolSyncSetup- Setting up VolSync (if enabled)SettingUpVolSyncDest- Setting up VolSync destinationCompleted- Operation finished successfully
Failover progressions (during failover operation):
Pre-failover (before creating VRG on failover cluster):
CheckingFailoverPrerequisites- Verifying failover prerequisitesWaitForFencing- Waiting for storage fencing to completeWaitForStorageMaintenanceActivation- Waiting for storage maintenance mode
Post-failover (after creating VRG on failover cluster):
FailingOverToCluster- Executing failover to target clusterWaitingForResourceRestore- Waiting for resources to restoreWaitForReadiness- Waiting for application to become readyUpdatedPlacement- Placement has been updatedCompleted- Operation finished successfullyCleaningUp- Cleaning up resources on source clusterWaitOnUserToCleanUp- Waiting for user intervention
Relocate progressions (during relocate operation):
Pre-relocate (before creating VRG on preferred cluster):
PreparingFinalSync- Preparing for final data syncClearingPlacement- Clearing placement decisionsRunningFinalSync- Running final data syncFinalSyncComplete- Final sync completedEnsuringVolumesAreSecondary- Setting volumes to secondary stateWaitOnUserToCleanUp- Waiting for user intervention (if needed)
Post-relocate (after creating VRG on preferred cluster):
WaitingForResourceRestore- Waiting for resources to restoreWaitForReadiness- Waiting for application to become readyUpdatedPlacement- Placement has been updatedCompleted- Operation finished successfullyCleaningUp- Cleaning up resources on source cluster
Special progressions (any operation):
Deleting- DRPC deletion in progressDeleted- DRPC has been deletedPaused- Action is paused, user intervention required
preferredDecision (PlacementDecision)
The cluster where the application is currently running or should run.
Fields:
clusterName- Name of the clusterclusterNamespace- Namespace of the ManagedCluster
conditions ([]metav1.Condition)
Standard Kubernetes conditions.
Condition types:
Available- Cluster is ready for workloadPeerReady- Peer cluster is ready for DR operationsProtected- Application is properly protected
lastGroupSyncTime (metav1.Time)
Time of the most recent successful synchronization of all PVCs.
lastGroupSyncDuration (metav1.Duration)
Duration of the most recent sync operation.
lastGroupSyncBytes (int64)
Total bytes transferred in the most recent sync.
lastKubeObjectProtectionTime (metav1.Time)
Time of the most recent successful Kubernetes object protection.
Examples
Example 1: Basic Application Protection
Enable DR for a simple stateless application with persistent data:
apiVersion: ramendr.openshift.io/v1alpha1
kind: DRPlacementControl
metadata:
name: webapp-drpc
namespace: webapp
spec:
# Deploy to east cluster initially
preferredCluster: east-cluster
# Use regional DR policy
drPolicyRef:
name: dr-policy
# Reference OCM Placement
placementRef:
kind: Placement
name: webapp-placement
# Protect PVCs with app=webapp label
pvcSelector:
matchLabels:
app: webapp
Example 2: Triggering a Failover
Fail over application to west cluster due to east cluster failure:
apiVersion: ramendr.openshift.io/v1alpha1
kind: DRPlacementControl
metadata:
name: webapp-drpc
namespace: webapp
spec:
preferredCluster: east-cluster
failoverCluster: west-cluster # Target cluster
drPolicyRef:
name: dr-policy
placementRef:
kind: Placement
name: webapp-placement
pvcSelector:
matchLabels:
app: webapp
action: Failover # Trigger failover
Example 3: Triggering a Relocate
Move application back to east cluster:
apiVersion: ramendr.openshift.io/v1alpha1
kind: DRPlacementControl
metadata:
name: webapp-drpc
namespace: webapp
spec:
preferredCluster: east-cluster # Target cluster
drPolicyRef:
name: dr-policy
placementRef:
kind: Placement
name: webapp-placement
pvcSelector:
matchLabels:
app: webapp
action: Relocate # Trigger relocate
Example 4: Recipe-Based Protection
Protect a database application with custom capture/recovery workflows:
apiVersion: ramendr.openshift.io/v1alpha1
kind: DRPlacementControl
metadata:
name: mysql-drpc
namespace: mysql-app
spec:
preferredCluster: east-cluster
drPolicyRef:
name: dr-policy
placementRef:
kind: Placement
name: mysql-placement
pvcSelector:
matchLabels:
app: mysql
kubeObjectProtection:
captureInterval: 5m
recipeRef:
name: mysql-recipe
namespace: mysql-app
Example 5: Multi-Namespace Protection
Protect application spanning multiple namespaces:
apiVersion: ramendr.openshift.io/v1alpha1
kind: DRPlacementControl
metadata:
name: multi-ns-app-drpc
namespace: ramen-ops # Must be in RamenOpsNamespace
spec:
preferredCluster: east-cluster
drPolicyRef:
name: dr-policy
placementRef:
kind: Placement
name: multi-ns-app-placement
pvcSelector:
matchLabels:
protect: "true"
protectedNamespaces:
- app-frontend
- app-backend
- app-database
kubeObjectProtection:
captureInterval: 5m
Usage
Enabling DR for an Application
Prerequisites:
- Application deployed with OCM Placement
- DRPolicy created
- PVCs labeled appropriately
Steps:
Label your PVCs:
kubectl label pvc my-pvc app=myapp -n myappCreate the DRPC:
kubectl apply -f drpc.yamlMonitor the DRPC status:
kubectl get drpc -n myapp kubectl describe drpc myapp-drpc -n myappWait for
Deployedphase:kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.phase}'
Performing a Failover
Scenario: East cluster has failed, need to recover on west cluster.
kubectl patch drpc myapp-drpc -n myapp --type merge -p '
{
"spec": {
"action": "Failover",
"failoverCluster": "west-cluster"
}
}'
Monitor progress:
kubectl get drpc myapp-drpc -n myapp -w
Check status:
kubectl get drpc myapp-drpc -n myapp -o yaml
Look for phase: FailedOver and progression: Completed.
Performing a Relocate
Scenario: East cluster is healthy again, relocate application back.
kubectl patch drpc myapp-drpc -n myapp --type merge -p '
{
"spec": {
"action": "Relocate",
"preferredCluster": "east-cluster"
}
}'
Monitor progress:
kubectl get drpc myapp-drpc -n myapp -w
Disabling DR Protection
To remove DR protection:
kubectl delete drpc myapp-drpc -n myapp
Note: This does NOT delete the application, only removes DR protection.
Monitoring and Observability
Check DRPC Phase
kubectl get drpc -A
Output shows: name, age, preferredCluster, failoverCluster, desiredState, currentState.
View Detailed Status
kubectl describe drpc myapp-drpc -n myapp
Check Replication Status
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.lastGroupSyncTime}'
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.lastGroupSyncBytes}'
View Conditions
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.conditions}' | jq
Troubleshooting
General Diagnosis
Check DRPC status and progression to identify issues:
kubectl get drpc myapp-drpc -n myapp
kubectl describe drpc myapp-drpc -n myapp
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.progression}'
DRPC Stuck in Deploying
Check: Verify PVCs match the selector and VRG is created.
kubectl get pvc -n myapp -l app=myapp
kubectl get manifestwork -A | grep myapp
Common causes: PVC selector mismatch, storage class not found on target cluster, or VRG not becoming ready.
Solution: Ensure PVCs have correct labels, storage class exists on managed cluster, and check VRG status for errors.
Failover Not Progressing
Check: Look for WaitForFencing or WaitForReadiness progression.
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.progression}'
kubectl get pods -n myapp --context west-cluster
Common causes: Storage fencing in progress, application pods not ready, or S3 storage not accessible.
Solution: Wait for fencing to complete (normal for Metro DR), fix application issues (image pull, resources), or verify S3 connectivity.
Relocate Taking Too Long
Check: Monitor progression for RunningFinalSync status.
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.progression}'
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.status.lastGroupSyncBytes}'
Common causes: Large data sync in progress or source cluster not accessible.
Solution: Wait for final sync to complete. If source cluster is down, use Failover instead of Relocate.
PeerReady Condition False
Check: Verify peer cluster connectivity and VRG status.
kubectl get managedcluster west-cluster
kubectl get vrg myapp-drpc -n myapp --context west-cluster
Common causes: Peer cluster unavailable or storage replication not established.
Solution: Ensure peer cluster is healthy and replication is configured correctly.
Cannot Delete DRPC
Check: Look for stuck finalizers or VRG cleanup issues.
kubectl get drpc myapp-drpc -n myapp -o jsonpath='{.metadata.finalizers}'
kubectl get vrg -n myapp --context east-cluster
Common causes: VRG cleanup pending on managed clusters.
Solution: Wait for VRG cleanup. If stuck, manually delete VRG or remove finalizers (use with caution).
Best Practices
Use descriptive names - Include app name in DRPC name (e.g.,
myapp-drpc)Label PVCs specifically - Use unique labels to avoid protecting wrong PVCs
Monitor status regularly - Check
lastGroupSyncTimeto ensure replication is workingTest failover - Perform planned failover tests before actual disasters
Document procedures - Create runbooks for DR operations specific to your apps
Use GitOps when possible - For easier application recreation
Set appropriate capture intervals - Balance protection vs. overhead
- Critical apps: 5m
- Standard apps: 15m to 30m
- Low-priority: 1h
Verify peer readiness - Check
PeerReadycondition before triggering DRClean up after testing - Remove DRPCs for apps that don’t need DR
Related Resources
- DRPolicy CRD - Defines DR topology referenced by DRPC
- VolumeReplicationGroup CRD - Created by DRPC on managed clusters
- Usage Guide - How to protect workloads with Ramen
- Recipe Documentation - For Recipe-based protection