Disaster Recovery #

Backup yang tidak pernah di-test sama saja tidak ada. Disaster recovery plan yang hanya ada di dokumen tapi tidak pernah dipraktikkan akan gagal saat paling dibutuhkan. Artikel ini membahas komponen-komponen disaster recovery untuk Kubernetes cluster — dari backup yang benar sampai strategi failover — dengan fokus pada hal-hal yang bisa dieksekusi ketika insiden nyata terjadi di jam 3 pagi.

Apa yang Perlu Di-backup #

Kubernetes cluster punya dua jenis "state" yang perlu di-backup:

1. Cluster state (etcd):
   → Definisi semua resource Kubernetes (Deployment, Service, ConfigMap, dll)
   → Tanpa ini: cluster kosong, harus deploy ulang semua dari scratch
   → Solusi ideal: simpan manifest di Git (GitOps) — tidak perlu backup etcd

2. Data persistent (PersistentVolumes):
   → Database, file uploads, state aplikasi
   → Ini tidak ada di Git, ini adalah data user
   → WAJIB di-backup, ini yang paling kritikal

Velero: Backup Namespace Kubernetes #

Velero adalah tool yang bisa backup dan restore seluruh namespace Kubernetes, termasuk resource definitions dan PersistentVolumes:

# Install Velero (contoh: backup ke AWS S3)
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.8.0 \
  --bucket my-velero-backups \
  --backup-location-config region=ap-southeast-1 \
  --snapshot-location-config region=ap-southeast-1 \
  --secret-file ./credentials-velero

# Backup satu namespace
velero backup create production-backup-20240115 \
  --include-namespaces production

# Backup seluruh cluster
velero backup create full-cluster-backup \
  --include-namespaces "*"

# Lihat status backup
velero backup describe production-backup-20240115
velero backup logs production-backup-20240115

# Schedule backup otomatis setiap hari jam 2 pagi
velero schedule create daily-production-backup \
  --schedule="0 2 * * *" \
  --include-namespaces production \
  --ttl 720h      # simpan 30 hari

Restore dengan Velero #

# Restore namespace dari backup
velero restore create \
  --from-backup production-backup-20240115 \
  --include-namespaces production

# Restore ke namespace berbeda (untuk testing restore)
velero restore create \
  --from-backup production-backup-20240115 \
  --namespace-mappings production:production-restore-test

# Lihat status restore
velero restore describe <restore-name>
velero restore logs <restore-name>

# Restore resource tertentu saja
velero restore create \
  --from-backup production-backup-20240115 \
  --include-resources deployments,services,configmaps

# ⚠ PENTING: test restore secara regular!
# Jadwalkan restore test ke namespace staging setiap bulan

Backup Database Terpisah dari Velero #

Untuk database, snapshot disk (yang dilakukan Velero) seringkali tidak cukup — snapshot bisa dalam state yang inconsistent jika diambil saat database sedang write. Gunakan database-native backup:

# CronJob untuk backup PostgreSQL ke S3
apiVersion: batch/v1
kind: CronJob
metadata:
  name: postgres-backup
  namespace: production
spec:
  schedule: "0 1 * * *"      # setiap hari jam 1 pagi
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: backup
            image: postgres:16
            command:
            - /bin/sh
            - -c
            - |
              TIMESTAMP=$(date +%Y%m%d_%H%M%S)
              BACKUP_FILE="backup_${TIMESTAMP}.sql.gz"

              # Dump database
              PGPASSWORD=$DB_PASSWORD pg_dump \
                -h $DB_HOST -U $DB_USER -d $DB_NAME \
                | gzip > /tmp/${BACKUP_FILE}

              # Upload ke S3
              aws s3 cp /tmp/${BACKUP_FILE} \
                s3://my-db-backups/postgres/${BACKUP_FILE}

              echo "Backup selesai: ${BACKUP_FILE}"

              # Hapus backup lokal lebih dari 7 hari di S3
              aws s3 ls s3://my-db-backups/postgres/ \
                | awk '{print $4}' \
                | sort -r | tail -n +8 \
                | xargs -I {} aws s3 rm s3://my-db-backups/postgres/{}              
            env:
            - name: DB_HOST
              value: "postgres-service"
            - name: DB_USER
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: username
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: password
            - name: DB_NAME
              value: "production_db"

Strategi Multi-Cluster untuk DR #

Untuk aplikasi kritikal dengan RTO rendah, satu cluster tidak cukup:

Strategi 1: Active-Passive (Failover)
  Region A: cluster aktif, menerima semua traffic
  Region B: cluster standby, ter-deploy tapi tidak menerima traffic

  Failover:
  → Deteksi region A down
  → Update DNS untuk arahkan traffic ke region B
  → RTO: 5-15 menit (waktu DNS propagation + health check)
  → RPO: tergantung frekuensi replikasi data ke region B

Strategi 2: Active-Active
  Region A: menerima 50% traffic
  Region B: menerima 50% traffic

  Keuntungan:
  → RTO ~0 (jika satu region down, traffic otomatis ke yang lain)
  → No wasted capacity (berbeda dari active-passive)

  Tantangan:
  → Data consistency antar region (database multi-master)
  → Jauh lebih kompleks untuk stateful workload
  → Biaya 2x karena kedua region penuh

Strategi 3: GitOps Cluster Recreation
  → Tidak ada cluster standby
  → Semua manifest di Git
  → Saat disaster: buat cluster baru, apply manifest dari Git
  → RTO: 30-60 menit (provisioning + deploy semua aplikasi)
  → Cocok untuk aplikasi yang bisa toleransi RTO >30 menit

Mendefinisikan RTO dan RPO #

RTO (Recovery Time Objective):
  Berapa lama maksimum sistem boleh tidak available?
  Contoh: "Maksimum 15 menit downtime per insiden"

RPO (Recovery Point Objective):
  Berapa banyak data maksimum yang boleh hilang?
  Contoh: "Maksimum kehilangan data 1 jam terakhir"

Mapping ke strategi:

  RTO < 1 menit:
  → Active-Active multi-region
  → Tidak ada single point of failure sama sekali

  RTO 5-15 menit:
  → Active-Passive dengan automated failover
  → DNS TTL rendah, health check cepat

  RTO 30-60 menit:
  → GitOps recreation
  → Backup restore dari Velero + S3

  RPO < 1 jam:
  → Database replikasi sync ke region lain
  → Backup setiap jam

  RPO < 24 jam:
  → Daily backup sudah cukup
  → Velero schedule harian

Runbook Recovery: Template #

Runbook: Cluster Gagal Total

Severity: Critical
Waktu respons: Segera

LANGKAH 1: Konfirmasi cluster down (5 menit)
  □ kubectl get nodes → timeout atau error
  □ Cek cloud provider console: apakah control plane healthy?
  □ Cek status page cloud provider
  □ Notify tim dan stakeholder via Slack/PagerDuty

LANGKAH 2: Putuskan strategi (2 menit)
  □ Apakah ada cluster DR/standby? → Lanjut ke Langkah 3A
  □ Tidak ada cluster DR? → Lanjut ke Langkah 3B

LANGKAH 3A: Failover ke cluster standby
  □ Update DNS/Load Balancer ke cluster standby
  □ Verifikasi traffic sudah pindah
  □ Verifikasi semua health check passing
  □ Monitor untuk 30 menit

LANGKAH 3B: Recreate cluster dari Git
  □ Provision cluster baru via Terraform/gcloud/eksctl
  □ kubectl apply -k overlays/production
  □ Restore database dari backup terbaru
  □ Verifikasi semua service running
  □ Smoke test endpoint production
  □ Update DNS/Load Balancer

LANGKAH 4: Post-recovery
  □ Root cause analysis
  □ Update runbook jika perlu
  □ Post-mortem dalam 48 jam

Ringkasan #

  • GitOps adalah backup cluster state terbaik — jika semua manifest ada di Git, recreate cluster hanya perlu kubectl apply -k; tidak perlu backup etcd yang kompleks.
  • Velero untuk backup PersistentVolume dan resource definitions — terutama untuk namespace yang punya data persistent; schedule daily backup dan test restore setiap bulan.
  • Database backup terpisah dari snapshot disk — snapshot disk bisa inconsistent saat database sedang write; gunakan pg_dump atau backup tool database-native.
  • Test restore secara regular — backup yang tidak pernah di-test tidak bisa dipercaya; restore ke namespace test setiap bulan sebagai bagian DR drill.
  • Definisikan RTO dan RPO sebelum insiden — tanpa target yang jelas, tidak ada strategi yang tepat; RTO <15 menit butuh active-passive; RTO <1 menit butuh active-active.
  • Runbook yang bisa diikuti oleh engineer baru — dokumentasi recovery yang mengasumsikan pengetahuan mendalam tidak berguna saat insiden pukul 3 pagi; buat step-by-step yang eksplisit.

← Sebelumnya: Cost Optimization   Berikutnya: Multi-Tenancy →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact