Live
Native PyTorch TPU Support Arrives via Open‑Source TorchTPUML Drift simplifies on-device GPU inference across heterogeneous hardwareRethinking Kubernetes for AI Agents: Sandbox Isolation and Warm‑Pool ExecutionCloudflare WAF adds default‑log rules for Brotli encoding and Next.js image endpointGPU Capacity Planning: Validate Outcomes Before Adding HardwareEmbedding Vercel’s Zig Coding Agent: Architecture and Ops ImpactGemini 4 Argon trims ADK session prep and import latency by up to 40%Rethinking CI/CD: The Sensor Limits of an Agentic Software FactoryNative PyTorch TPU Support Arrives via Open‑Source TorchTPUML Drift simplifies on-device GPU inference across heterogeneous hardwareRethinking Kubernetes for AI Agents: Sandbox Isolation and Warm‑Pool ExecutionCloudflare WAF adds default‑log rules for Brotli encoding and Next.js image endpointGPU Capacity Planning: Validate Outcomes Before Adding HardwareEmbedding Vercel’s Zig Coding Agent: Architecture and Ops ImpactGemini 4 Argon trims ADK session prep and import latency by up to 40%Rethinking CI/CD: The Sensor Limits of an Agentic Software Factory
Kubernetes

Kubernetes Disaster Recovery: Practical Lessons from Three Failure Scenarios

AI SummaryPowered by AI

The article shows how three reproducible failure scenarios expose gaps between backup completion, declared state, and actual data restoration in Kubernetes environments. Understanding these gaps helps engineers design DR processes that verify data movement, combine GitOps with backups, and plan for infrastructure recreation, reducing RPO/RTO risk.

Kubernetes disaster recovery is often treated as a single step—run a backup tool and restore. The three lab‑based failure scenarios demonstrate that a backup’s Completed status, a GitOps sync, and a restored cluster each leave a hidden gap that can break recovery if not explicitly addressed.

Scenario 1 – Verifying that backup data actually left the cluster

The lab uses Velero with its data‑mover to copy volume bytes to an S3‑compatible bucket. A typical check stops at the backup’s Completed phase, assuming the data is safe. The experiment adds a second step: query the DataUpload resource to confirm the byte count that was transferred.

kubectl -n velero get datauploads -l velero.io/backup-name=$BACKUP \
  -o custom-columns='NAME:.metadata.name,PHASE:.status.phase,BYTES:.status.progress.bytesDone'
NAME                                 PHASE      BYTES
guestbook-rehearsal-20260727001126-q2j9m  Completed  47989888

Seeing ~48 MiB reported confirms that the volume data left the source cluster. The implication is clear: a backup tool that cannot surface this metric should be scrutinized. Moreover, a successful restore that recreates a PostgreSQL pod and returns the original four rows only occurs because the test also configured quiesce hooks and mapped the source storage class to the target environment. Without those, the restored pod could start with a corrupt or empty database.

Scenario 2 – GitOps restores intent, not stored data

In the second failure mode the production cluster is powered off, leaving a pre‑existing recovery cluster that runs a GitOps controller pointed at a Git repository containing only manifests. The controller syncs the StatefulSet, creates a PVC, and the database pod becomes ready. A query then fails with ERROR: relation "attendees" does not exist because the volume is brand new and empty.

This illustrates the classic “GitOps trap”: the version‑controlled YAML defines the desired objects, but it does not carry the persistent data. The backup store holds that data, and only a coordinated restore that pulls both the manifests and the volume snapshots can reconstitute the application state. The lab’s corrective path was to delete the empty resources, invoke Velero to restore the PVCs from the shared bucket, and then validate the rows.

Related CloudNinjas coverage: hands-on guides.

What This Means For Practitioners

Both scenarios converge on three actionable takeaways:

  • End‑to‑end verification is mandatory. Treat the backup’s status as a checkpoint, not a guarantee. Automate checks that confirm byte counts, snapshot integrity, and post‑restore data queries.
  • Separate the recovery of infrastructure, declared state, and stored state. Use infrastructure‑as‑code (e.g., Cluster API) to rebuild the cluster, a GitOps pipeline to apply manifests, and a backup tool to restore volumes. Document the exact hand‑off points.
  • Test portability and transformation. Restores may land on different nodes, storage classes, or cloud providers. Validate that class mappings, CSI drivers, and any required quiesce hooks work across those boundaries.

Practitioners should add regular rehearsals that cover the full chain—from provisioning a fresh cluster to confirming that application‑level data matches expectations. Monitoring the backup tool’s progress fields and integrating those metrics into alerting can surface failures before a real disaster strikes. Finally, ensure that the external backup bucket is protected with appropriate access controls, because it becomes the single source of truth for stored state.

Originally published atCNCF