🎯 DR Strategies — The Four Tiers

Choose your DR strategy based on your RTO/RPO requirements and budget. Each tier roughly doubles cost while halving recovery time.

💾

Backup & Restore

RTO: hours
RPO: hours
Cost: lowest

etcd snapshots + Velero to S3. Restore to a new cluster when primary fails.

🌡️

Pilot Light

RTO: 30–60 min
RPO: minutes
Cost: low

Minimal cluster running in DR region. Scale up and restore data on failover.

🌊

Warm Standby

RTO: 5–30 min
RPO: seconds
Cost: medium

Full cluster at reduced capacity. Database replicated. Scale up on failover.

🔥

Active-Active

RTO: seconds
RPO: near-zero
Cost: highest

Two full clusters, both serving traffic. DNS failover or global LB.

Cost → Recovery Speed → B&R Pilot Warm A-A hours 30–60m 5–30m seconds

RTO & RPO Definitions

TermDefinitionTypical targets by tier
RTO (Recovery Time Objective)Maximum acceptable time from disaster to full service recoveryTier 1: 4h | Tier 2: 1h | Tier 3: 15m | Tier 4: <1m
RPO (Recovery Point Objective)Maximum acceptable data loss measured in timeTier 1: 1h | Tier 2: 15m | Tier 3: 1m | Tier 4: <1s
MTTR (Mean Time to Recovery)Average time to restore service after an incidentMeasure from incidents; improve iteratively
MTBF (Mean Time Between Failures)Average time between incidentsTrack to understand failure frequency

💾 What to Back Up & How Often

DataToolFrequencyRetentionStorage
etcd cluster stateetcdctl snapshotHourly7 daysS3 cross-region
Persistent Volume dataVelero + CSI snapshotsHourly7 daysS3 / cloud snapshots
Application manifestsGit (ArgoCD/Flux)Continuous (every commit)PermanentGit remote
SecretsExternal Secrets storeReal-time (ESO)Vault/AWS SM versioningSecrets manager
Container imagesHarbor replicationOn pushPermanent (semver tags)Cross-region registry
Helm values / Kustomize overlaysGitContinuousPermanentGit remote
Observability dataPrometheus remote_write to MimirContinuous13 monthsS3
💡 GitOps makes cluster-state recovery trivial If all Kubernetes manifests are in Git managed by ArgoCD/Flux, recovering a cluster is: (1) provision new cluster, (2) install ArgoCD, (3) point at the Git repo. The cluster self-heals to the desired state. The only irreplaceable data is etcd (for in-flight state) and PV data.

Automated etcd Backup CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: etcd-backup
  namespace: kube-system
spec:
  schedule: "0 * * * *"    # every hour
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      template:
        spec:
          hostNetwork: true
          nodeName: cp-1               # run on first control-plane node
          containers:
            - name: etcd-backup
              image: bitnami/etcd:3.5
              command:
                - /bin/sh
                - -c
                - |
                  ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-$(date +%Y%m%d-%H%M).db \
                    --endpoints=https://127.0.0.1:2379 \
                    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
                    --cert=/etc/kubernetes/pki/apiserver-etcd-client.crt \
                    --key=/etc/kubernetes/pki/apiserver-etcd-client.key
                  aws s3 cp /backup/etcd-$(date +%Y%m%d-%H%M).db \
                    s3://my-etcd-backups/$(date +%Y/%m/%d)/ \
                    --storage-class STANDARD_IA
              volumeMounts:
                - name: etcd-certs
                  mountPath: /etc/kubernetes/pki/etcd
                  readOnly: true
          volumes:
            - name: etcd-certs
              hostPath:
                path: /etc/kubernetes/pki/etcd
          restartPolicy: OnFailure
          tolerations:
            - key: node-role.kubernetes.io/control-plane
              effect: NoSchedule

Velero Scheduled Backup for PV Data

velero schedule create hourly-production \
  --schedule="@every 1h" \
  --include-namespaces production,staging \
  --ttl 168h \
  --storage-location default

# Monitor backup health
velero backup get
velero schedule get

# Alert if latest backup is older than 2 hours (Prometheus)
# time() - velero_backup_last_successful_timestamp > 7200

🌍 Multi-Region & Cluster Failover

Global Load Balancer

AWS Global Accelerator, GCP Cloud Load Balancing, or Cloudflare directs traffic to the nearest healthy region. Health checks detect region failure in <10s.

Database Replication

Cross-region database replication (RDS Multi-AZ + read replica, CloudSQL HA, CockroachDB) is the hardest part of active-active. Define write locality.

Image Registry Replication

Harbor geo-replication or ECR cross-region replication ensures images are available in the DR region before you need them — not during the incident.

DNS TTL Management

Reduce DNS TTL to 60s 24h before planned failover tests. In active-active, use low TTL always (30–60s) to enable fast failover.

Active-Active Multi-Cluster with Submariner

# Submariner creates an encrypted overlay between clusters
# allowing cross-cluster service discovery and pod-to-pod routing

# Install on both clusters
subctl deploy-broker --kubeconfig primary.kubeconfig
subctl join broker-info.subm \
  --kubeconfig secondary.kubeconfig \
  --clusterid secondary

# Export a service to be discoverable from other clusters
kubectl apply -f - <<EOF
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: my-api
  namespace: production
EOF

# From secondary cluster, discover the service
kubectl get serviceimport -n production
# Access via: my-api.production.svc.clusterset.local

Cluster Failover Runbook (Backup & Restore tier)

  1. Declare incident — alert on-call team, open incident channel, assign incident commander
  2. Assess primary cluster — determine if recoverable or if full DR activation is needed
  3. Point DNS to DR region — update Route53/Cloud DNS health-check target or lower TTL to failover
  4. Provision DR cluster — use Terraform/Pulumi IaC; cluster should provision in 5–10 min
  5. Restore etcd snapshotetcdctl snapshot restore from latest S3 backup (see lesson 83)
  6. Bootstrap GitOps — install ArgoCD, apply root Application; manifests auto-apply from Git
  7. Restore PV datavelero restore create --from-backup <latest>
  8. Validate services — run smoke tests against DR endpoints, check database connectivity
  9. Communicate status — update status page, notify stakeholders, estimated recovery time
  10. Post-incident — write PIR (Post-Incident Review), update runbook with lessons learned
🚨 The runbook must be outside the cluster If your runbook is in a Confluence or internal wiki that's only accessible via the cluster you just lost, you cannot recover. Keep runbooks in an external system (Notion, Google Docs, printed binder) accessible without cluster access.

💥 Chaos Engineering & DR Testing

An untested DR plan is not a DR plan. Chaos engineering deliberately injects failures in controlled conditions to validate that your system handles them gracefully — and that your runbooks actually work.

LitmusChaos — Kubernetes-Native Chaos

helm repo add litmuschaos https://litmuschaos.github.io/litmus-helm
helm install chaos litmuschaos/litmus \
  --namespace litmus \
  --create-namespace

# Pod Delete experiment — kills random pods in a namespace
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
  name: pod-delete-chaos
  namespace: production
spec:
  appinfo:
    appns: production
    applabel: "app=my-api"
    appkind: deployment
  chaosServiceAccount: pod-delete-sa
  experiments:
    - name: pod-delete
      spec:
        components:
          env:
            - name: TOTAL_CHAOS_DURATION
              value: "60"      # run for 60 seconds
            - name: CHAOS_INTERVAL
              value: "10"      # delete a pod every 10s
            - name: FORCE
              value: "false"   # graceful termination
        probe:
          - name: check-availability
            type: httpProbe
            httpProbe/inputs:
              url: https://my-api.example.com/health
              insecureSkipVerify: false
              responseTimeout: 5000
            runProperties:
              probeTimeout: 10
              interval: 2
              attempt: 10

DR Testing Schedule

TestFrequencyWhat to validate
Single pod killContinuous (CI)Pod restarts, readiness probe, PDB holds
Node drainWeeklyPods reschedule cleanly, PDBs respected, no data loss
etcd snapshot restoreMonthlyFull restore to a fresh cluster within RTO
Velero restore drillMonthlyPV data recoverable within RPO
Zone failure simulationQuarterlyServices survive AZ loss, traffic reroutes
Full region failoverAnnuallyEnd-to-end DR runbook executes within RTO, data loss within RPO
💡 Game Days Schedule quarterly "Game Day" events where the team deliberately breaks production-like systems and practices the runbooks. The first time you execute a runbook should never be during a real incident.

Key DR Metrics to Track

Actual vs Target RTO

Measure time from incident declaration to full service restoration in every DR test. Is it within your SLA target?

Backup Success Rate

Alert when velero_backup_success_total or etcd snapshot jobs fail. A backup you don't know failed is not a backup.

Restore Test Results

Track every restore drill — success/failure, actual RTO, data loss observed. Trend over time to show DR capability improvement.

MTTR Trend

Calculate mean time to recovery from all incidents. A decreasing MTTR means your runbooks and automation are improving.

📝 Knowledge Check

Q1. Your RTO is 30 minutes and RPO is 5 minutes. Which DR strategy tier is appropriate?
  • A) Backup & Restore — hourly snapshots are sufficient
  • B) Pilot Light — minimal cluster with near-real-time data replication
  • C) Warm Standby — full cluster at reduced capacity with near-real-time replication
  • D) Active-Active — only this tier can meet 5-minute RPO
C) Warm Standby. RTO of 30 minutes rules out Backup & Restore (hours to restore). RPO of 5 minutes requires near-real-time replication — Pilot Light could work if scale-up is fast enough, but Warm Standby with a running reduced-capacity cluster is the safer choice. Active-Active is overkill and too expensive for a 30-minute RTO target.
Q2. A major region outage occurs. Your team tries to access the recovery runbook to start the failover procedure, but it's hosted in the internal wiki running in the failed region. What critical DR planning mistake was made?
  • A) The team should have memorised the runbook
  • B) Runbooks must be stored in an external system accessible without the failed infrastructure
  • C) The wiki should have been backed up to S3 as part of Velero
  • D) The runbook should be committed to the application Git repo
B) Runbooks must be externally accessible. This is a classic DR planning failure. Runbooks, contact lists, and recovery procedures must be accessible without the systems you're trying to recover. Store them in Google Docs, Notion, Confluence Cloud, or printed binders — anything that doesn't depend on your own infrastructure being healthy.
Q3. What is the primary purpose of chaos engineering in a DR program?
  • A) To stress test performance under load
  • B) To validate that the system handles failures gracefully and runbooks work, before a real incident reveals they don't
  • C) To generate incident reports for compliance auditors
  • D) To identify security vulnerabilities in the cluster
B) Validate failure handling and runbooks proactively. Chaos engineering builds confidence that the system is resilient by deliberately injecting failures under controlled conditions. The goal is to find weaknesses in your architecture, recovery procedures, and team response — in a safe environment — before a real disaster forces you to discover them under pressure.