DEV Community

Engr.Hamza
Engr.Hamza

Posted on

Silent Cluster Killer: How to Prevent Total Data Loss on Small Kubernetes Clusters

Cover Image

Silent Cluster Killer: How to Prevent Total Data Loss on Small Kubernetes Clusters

You have built a tight, efficient three-node Kubernetes cluster. It hosts your staging workloads, key internal microservices, and a small PostgreSQL instance. Then, an unannounced cloud provider maintenance event hits, taking down two control plane nodes at once, and etcd loses quorum.

When the control plane recovers, your persistent volume claims fail to bind, stateful pods hang endlessly in ContainerCreating, and your persistent volumes are suddenly empty. Over 60% of small-scale Kubernetes setups run without a battle-tested disaster recovery mechanism because engineers mistakenly assume cloud-backed PersistentVolumes or basic local storage are inherently indestructible.


The Problem Everyone Ignores

Running a small cluster means balancing tight resource constraints against production-grade reliability requirements. Most teams start by deploying standard local path provisioners or cloud disk attachments, setting up scheduled application-level database dumps, and calling it a day.

The trouble starts when you realize application dumps only cover known, structured databases. They completely miss object stores, message queues, stateful application configuration, key-value caches, and cluster-wide state mounted directly on PVCs.

When a underlying node suffers disk corruption or an unrecoverable kernel panic, your local storage driver cannot replicate block-level changes elsewhere. Cloud disks sound safer until an availability zone network partition hits, leaving your volumes locked in a region where your replacement pods cannot schedule.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 20Gi
Enter fullscreen mode Exit fullscreen mode

This default local path setup offers zero replication, leaving your workload bound to a single physical disk that will eventually fail.


What Actually Works

To survive complete node loss without breaking the bank on expensive enterprise storage arrays, you need block-level snapshotting paired with external, S3-compatible offsite object storage. This approach decouples state replication from compute nodes entirely.

Instead of writing custom scripts to back up individual directories, we use continuous, volume-aware snapshot engines like Longhorn or Velero. This architecture captures raw block modifications, compresses them, encrypts them at rest, and ships incremental delta blocks directly to offsite storage.

When a disaster strikes, you do not need the original hardware or cluster state to restore your system. You spin up a completely clean Kubernetes cluster anywhere, point your backup engine to the offsite object store bucket, and restore both your volume claims and cluster manifests in minutes.

apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
  name: s3-offsite-backup
  namespace: velero
spec:
  provider: aws
  objectStorage:
    bucket: my-k8s-disaster-recovery-bucket
    prefix: cluster-backups
  config:
    region: us-east-1
    s3Url: https://s3.us-east-1.amazonaws.com
    s3ForcePathStyle: "true"
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
  name: daily-app-backup
  namespace: velero
spec:
  schedule: "0 2 * * *"
  template:
    includedNamespaces:
      - production
    snapshotVolumes: true
    ttl: 720h0m0s
Enter fullscreen mode Exit fullscreen mode

This configuration sets up Velero to run automated daily block-level volume snapshots and ships them offsite to an external S3-compatible bucket with a 30-day retention period.


Step-by-Step: Let's Build It Together

We will build a resilient storage strategy for a small Kubernetes cluster using Velero for cluster-wide disaster recovery and block snapshotting.

Step 1: Establish Offsite S3 Storage and Cluster Credentials

First, we create an isolated storage bucket outside our cluster infrastructure and configure the necessary Kubernetes secrets so our backup engine can securely read and write volume data.

# Create target S3 bucket for disaster recovery
aws s3api create-bucket \
    --bucket k8s-small-cluster-dr-backup \
    --region us-east-1

# Create dedicated IAM policy credentials file
cat <<EOF > velero-credentials
[default]
aws_access_key_id=YOUR_IAM_ACCESS_KEY_ID
aws_secret_access_key=YOUR_IAM_SECRET_ACCESS_KEY
EOF

# Deploy Velero system secret to the cluster
kubectl create namespace velero
kubectl create secret generic cloud-credentials \
    --namespace velero \
    --from-file cloud=velero-credentials
Enter fullscreen mode Exit fullscreen mode

We created an offsite target S3 bucket and sealed our cloud access credentials inside the cluster under the velero namespace.

Step 2: Install Velero with Container Storage Interface (CSI) Snapshot Support

Next, we deploy Velero using the Helm package manager, enabling CSI volume snapshotting to leverage modern Linux kernel block driver snapshot capabilities directly.

# velero-values.yaml
configuration:
  backupStorageLocation:
    - name: default
      provider: aws
      bucket: k8s-small-cluster-dr-backup
      config:
        region: us-east-1
  volumeSnapshotLocation:
    - name: default
      provider: aws
      config:
        region: us-east-1
initContainers:
  - name: velero-plugin-for-aws
    image: velero/velero-plugin-for-aws:v1.9.0
    volumeMounts:
      - mountPath: /target
        name: plugins
credentials:
  useSecret: true
  existingSecret: cloud-credentials
deployNodeAgent: true
Enter fullscreen mode Exit fullscreen mode
# Deploy Velero using Helm chart
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm repo update
helm install velero vmware-tanzu/velero \
    --namespace velero \
    -f velero-values.yaml
Enter fullscreen mode Exit fullscreen mode

We configured Velero to run node-agent daemons across all nodes to extract data directly from persistent volumes and sync it to external object storage.

Step 3: Trigger and Verify an On-Demand On-Site Snapshot

Before relying on automated schedules, we manually trigger an immediate backup of our production workloads and inspect the snapshot status to ensure integrity.

# Trigger an on-demand snapshot for stateful production workloads
velero backup create prod-manual-backup-01 \
    --include-namespaces production \
    --wait

# Verify backup completion and volume snapshot inclusion
velero backup describe prod-manual-backup-01 --details

# Check for successful offsite S3 object generation
aws s3 ls s3://k8s-small-cluster-dr-backup/backups/prod-manual-backup-01/
Enter fullscreen mode Exit fullscreen mode

We verified that our stateful production application was cleanly snapshotted, packaged, and transferred off-cluster to our remote S3 bucket.


The Mistakes That Will Burn You

  • Mistake 1: Assuming cloud provider disk snapshots are offsite backups. If your cloud provider account gets compromised, your primary disks and their cloud-native snapshots disappear together in a single command.
  • Mistake 2: Ignoring persistent volume read/write locks during snapshotting. Taking a snapshot on an active, un-flushed database write engine causes filesystem corruption, leaving you with useless, un-bootable restore images.
  • Mistake 3: Never testing the actual restore procedure on clean infrastructure. A backup pipeline you haven't restored on a fresh, isolated cluster is nothing more than an unverified hypothesis.

Production Checklist

  • Do this: Validate that your database system supports application-level pre-freeze and post-unfreeze hooks before triggering snapshots.
  • Do this: Store cluster encryption keys, sealed secrets, and S3 credentials in a secure, off-cluster password manager or vault.
  • Never do this: Never target your disaster recovery backup buckets within the same cloud region or node infrastructure hosting your primary cluster.

Key Takeaways

  • Local persistent storage on small clusters offers performance, but zero disaster protection when underlying hardware fails.
  • Decouple compute from storage state by continuously shipping block-level deltas directly to isolated S3 object stores.
  • Leverage CSI snapshots and dedicated tools like Velero to capture both Kubernetes cluster manifests and persistent disk state together.
  • Regularly execute dry-run restores on a clean target cluster to confirm your recovery point objective (RPO) and recovery time objective (RTO).

Engr. Hamza | AI & MLOps Engineer | Building autonomous systems at the edge of possibility

Top comments (0)