Backup & Restore #

Di dalam ekosistem Kubernetes yang dinamis dan terdistribusi, kita sering kali terbuai oleh kemampuan self-healing yang dimiliki platform ini. Kita melihat bagaimana Pod yang mati langsung digantikan oleh Pod baru, atau bagaimana node yang mengalami kegagalan langsung ditangani dengan memindahkan beban kerja ke node yang sehat. Namun, kita harus sadar bahwa self-healing bukanlah pengganti dari strategi pemulihan bencana (Disaster Recovery) dan pencadangan data (Backup). Kehilangan data akibat kesalahan manusia, kegagalan sistem penyimpanan (storage backend), serangan siber (ransomware), atau bencana alam regional tidak bisa disembuhkan secara otomatis oleh control plane Kubernetes.

Backup adalah asuransi terbaik kita dalam mengoperasikan sistem produksi. Artikel ini akan membahas secara mendalam strategi backup dan restore penyimpanan di Kubernetes, mengeksplorasi perbedaan mendasar dengan lingkungan tradisional, mengupas arsitektur Volume Snapshot bawaan Kubernetes, serta mendemonstrasikan implementasi nyata menggunakan Velero dan backup etcd.


Mengapa Backup Kubernetes Berbeda? #

Apabila kita terbiasa mengelola server tradisional atau mesin virtual (VM), kita mungkin terbiasa dengan metode backup satu tombol seperti VM snapshot. Pada model VM tradisional, snapshot mengambil seluruh keadaan sistem: sistem operasi, konfigurasi jaringan, biner aplikasi, memori, dan data disk dalam satu paket terpadu.

Di Kubernetes, pendekatan tersebut tidak lagi relevan karena arsitektur kluster yang terfragmentasi dan terdistribusi. Mari kita perhatikan perbedaan fundamental berikut:

Backup di Lingkungan Tradisional (VM):
  [OS + Aplikasi + Konfigurasi + Data Disk]
                     │
                     ▼ (Satu Unit Snapshot)
         [Backup Image VM Tunggal]

Backup di Lingkungan Kubernetes:
  ├── State Kluster & Metadata (Deployment, ConfigMap, Secret, RBAC) ──> Tersimpan di Etcd
  ├── Data State Aplikasi (Database, Upload File) ───────────────────> Tersimpan di PVC / Storage Backend
  └── Image Kontainer (Biner Aplikasi & Library) ────────────────────> Tersimpan di Container Registry

Oleh karena itu, jika kita ingin merancang sistem backup yang andal di Kubernetes, kita harus memecah strategi kita menjadi beberapa lapisan:

  1. Pencadangan State Kluster (Etcd): Menyimpan seluruh manifes deklaratif, relasi resource, konfigurasi keamanan, dan status kluster saat ini.
  2. Pencadangan Data Volume (Persistent Volume): Menyimpan bit-bit data riil yang ditulis oleh database atau aplikasi stateful kita ke storage backend.
  3. Pencadangan Level Aplikasi (Logical Backup): Melakukan ekstraksi data secara logis dari dalam aplikasi (misalnya dump database SQL) untuk menjamin konsistensi transaksional.

Volume Snapshot: Standar Pencadangan Berbasis CSI #

Sejak diperkenalkannya Container Storage Interface (CSI) di Kubernetes, kita memiliki cara standar untuk berinteraksi dengan berbagai penyedia storage pihak ketiga (AWS EBS, GCP Persistent Disk, Azure Disk, Ceph, Rook, dll). Salah satu fitur terpenting dari CSI adalah Volume Snapshot API, yang memungkinkan kita mengambil snapshot point-in-time dari PersistentVolumeClaim (PVC) langsung melalui API Kubernetes.

Arsitektur dan Alur Kerja Volume Snapshot #

Manifes Volume Snapshot di Kubernetes terdiri dari tiga resource utama:

  • VolumeSnapshotClass: Menentukan driver CSI yang digunakan dan parameter penghapusan snapshot.
  • VolumeSnapshot: Permintaan pembuatan snapshot oleh developer (mirip dengan PVC).
  • VolumeSnapshotContent: Representasi snapshot fisik yang sebenarnya di storage backend (mirip dengan PV).

Mari kita visualisasikan alur interaksi pembuatan Volume Snapshot melalui diagram berikut:

flowchart TD
    User["Developer (VolumeSnapshot)"] -. Membuat .-> API["Kubernetes API Server"]
    API -. Trigger .-> CSI["CSI Snapshot Controller"]
    CSI -. Request .-> Driver["CSI Driver (AWS/GCP/Ceph)"]
    Driver -. Memanggil API .-> Cloud["Cloud Storage API (EBS Snapshot)"]
    Cloud -. Membuat snapshot fisik .-> Physical["Physical Snapshot (AWS/GCP)"]

1. Membuat VolumeSnapshotClass #

Sebelum kita bisa membuat snapshot, administrator kluster harus mendefinisikan VolumeSnapshotClass. Resource ini menentukan driver mana yang bertanggung jawab untuk mengambil snapshot dan bagaimana siklus hidup snapshot tersebut dikelola.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-aws-ebs-snapshotclass
driver: ebs.csi.aws.com
deletionPolicy: Retain
parameters:
  tagSpecification_1: "key=Environment,value=Production"
  tagSpecification_2: "key=BackupType,value=CSI-Snapshot"
  • driver: Harus cocok dengan driver CSI yang aktif di kluster kita (contoh: ebs.csi.aws.com untuk AWS EBS).
  • deletionPolicy: Menentukan apakah snapshot fisik di cloud akan dihapus (Delete) atau dipertahankan (Retain) ketika objek VolumeSnapshot di Kubernetes dihapus. Kita sangat disarankan memilih Retain untuk lingkungan produksi guna menghindari kehilangan data yang tidak disengaja.

2. Mengajukan Pembuatan VolumeSnapshot #

Setelah VolumeSnapshotClass tersedia, developer dapat membuat snapshot dari PVC tertentu dengan membuat manifes VolumeSnapshot.

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: postgres-data-snapshot-20260617
  namespace: database
spec:
  volumeSnapshotClassName: csi-aws-ebs-snapshotclass
  source:
    persistentVolumeClaimName: postgres-pvc-postgres-0

Kita dapat memantau proses pembuatan snapshot dengan perintah berikut:

kubectl get volumesnapshot -n database

Output yang akan kita lihat:

NAME                              READYTOUSE   SOURCEPVC                  SOURCESNAPSHOTCONTENT   RESTORESIZE   AGE
postgres-data-snapshot-20260617   true         postgres-pvc-postgres-0   snapcontent-123456...   50Gi          2m

Pastikan kolom READYTOUSE bernilai true, yang menandakan bahwa snapshot telah berhasil dibuat secara fisik di storage backend dan siap digunakan untuk proses restore.

3. Melakukan Restore Data dari Volume Snapshot #

Apabila kita ingin mengembalikan data kita dari snapshot yang telah dibuat, kita tidak menimpa PVC yang lama. Sebagai gantinya, kita membuat PVC baru dengan menentukan dataSource yang menunjuk pada objek VolumeSnapshot kita.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc-restored
  namespace: database
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: premium-rwo
  resources:
    requests:
      storage: 50Gi
  dataSource:
    name: postgres-data-snapshot-20260617
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io

Ketika kita menerapkan manifes ini, driver CSI akan mendeteksi dataSource, lalu membuat volume baru di cloud provider berdasarkan snapshot fisik yang tersimpan, dan kemudian melakukan binding volume tersebut ke objek PVC baru ini. Kita kemudian dapat me-mount PVC postgres-pvc-restored ke Pod database kita yang baru.


Logical Backup: Konsistensi Level Aplikasi #

Meskipun Volume Snapshot berbasis CSI sangat cepat dan efisien, kita harus memahami keterbatasannya. Snapshot CSI bekerja pada level blok storage (crash-consistent). Artinya, snapshot hanya menjamin bahwa struktur sistem berkas (filesystem) aman, tetapi tidak menjamin konsistensi data aplikasi yang sedang berada di memori (buffer pool atau caching layer).

Jika kita mengambil snapshot database PostgreSQL atau MySQL yang sedang sibuk menerima transaksi tulis tanpa melakukan penguncian (locking atau flushing), ada kemungkinan besar data transaksi yang tersimpan di snapshot tersebut menjadi tidak konsisten (corrupted).

Untuk mengatasi masalah ini, kita harus menerapkan Logical Backup (Backup Level Aplikasi) menggunakan utilitas bawaan database seperti pg_dump, mysqldump, atau mongodump.

Implementasi CronJob Backup Postgres ke Object Storage (S3) #

Mari kita buat manifes CronJob yang andal untuk menjalankan backup logis database PostgreSQL secara rutin setiap hari pada jam 02:00 pagi. Backup ini akan langsung dikompresi dan dikirimkan ke bucket AWS S3 eksternal tanpa meninggalkan file sampah di node.

Pertama, kita siapkan Secret berisi kredensial AWS S3 dan database kita:

apiVersion: v1
kind: Secret
metadata:
  name: postgres-backup-secret
  namespace: database
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
  AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  POSTGRES_PASSWORD: "SuperSecurePostgresPassword123"

Selanjutnya, kita definisikan manifes CronJob kita:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: postgres-logical-backup
  namespace: database
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: postgres-backup-agent
              image: amazon/aws-cli:2.15.15
              command:
                - /bin/sh
                - -c
                - |
                  set -e
                  echo "Starting logical database backup..."
                  
                  # Instalasi postgresql client secara runtime jika image aws-cli tidak memilikinya
                  yum install -y postgresql15
                  
                  BACKUP_DATE=$(date +%Y-%m-%d-%H%M%S)
                  FILENAME="postgres-backup-${BACKUP_DATE}.sql.gz"
                  
                  echo "Dumping database 'app_production'..."
                  PGPASSWORD="${POSTGRES_PASSWORD}" pg_dump -h postgres-service.database.svc.cluster.local -U postgres -d app_production | gzip > "/tmp/${FILENAME}"
                  
                  echo "Uploading backup to AWS S3..."
                  aws s3 cp "/tmp/${FILENAME}" "s3://production-k8s-database-backups/postgres/${FILENAME}"
                  
                  echo "Backup and upload process completed successfully!"
                  rm -f "/tmp/${FILENAME}"                  
              env:
                - name: POSTGRES_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: postgres-backup-secret
                      key: POSTGRES_PASSWORD
                - name: AWS_ACCESS_KEY_ID
                  valueFrom:
                    secretKeyRef:
                      name: postgres-backup-secret
                      key: AWS_ACCESS_KEY_ID
                - name: AWS_SECRET_ACCESS_KEY
                  valueFrom:
                    secretKeyRef:
                      name: postgres-backup-secret
                      key: AWS_SECRET_ACCESS_KEY
                - name: AWS_DEFAULT_REGION
                  value: "ap-southeast-1"
  • concurrencyPolicy: Forbid: Menjamin bahwa jika proses backup hari ini berjalan lambat (karena ukuran data membengkak), Kubernetes tidak akan menjalankan job backup baru secara paralel keesokan harinya yang dapat mengacaukan performa database.
  • set -e: Memastikan bahwa jika salah satu baris perintah gagal (misalnya gagal koneksi database atau gagal upload ke S3), container akan langsung keluar dengan status error agar scheduler tahu bahwa backup gagal dan memicu alert.

Velero: Solusi Disaster Recovery Komprehensif #

Apabila kita ingin mengamankan seluruh kluster kita secara holistik (tidak hanya data disk, tetapi juga seluruh manifest konfigurasi API Server), kita membutuhkan tool khusus. Velero (sebelumnya dikenal sebagai Heptio Ark) adalah standar industri open-source terpopuler untuk melakukan pencadangan dan pemulihan kluster Kubernetes secara keseluruhan.

Velero bekerja dengan cara menangkap keadaan objek-objek API Kubernetes dan menyimpannya ke dalam bentuk tarball di Object Storage, serta berintegrasi dengan API Volume Snapshot CSI untuk mencadangkan data PVC.

Mari kita lihat alur kerja Velero saat melakukan backup dan restore:

flowchart TD
    Velero["Velero CLI / CRD"] -. Trigger Backup .-> Controller["Velero Controller"]
    Controller -. Query Resources .-> API["Kubernetes API Server"]
    Controller -. Backup Manifests .-> S3["Object Storage (S3/GCS)"]
    Controller -. Snapshot Volume .-> CSI["CSI Volume Snapshot"]
    CSI -. Membuat Snapshot .-> Storage["Cloud / Persistent Storage"]

1. Mempersiapkan Instalasi Velero #

Untuk menginstal Velero di kluster kita, kita harus menyiapkan bucket Object Storage eksternal (misalnya S3) dan kredensial akses yang sesuai. Simpan kredensial AWS kita di file lokal bernama credentials-velero:

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Kemudian, jalankan perintah instalasi berikut menggunakan CLI Velero:

velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.9.0 \
  --bucket production-k8s-velero-backups \
  --backup-location-config region=ap-southeast-1 \
  --snapshot-location-config region=ap-southeast-1 \
  --secret-file ./credentials-velero \
  --use-volume-snapshots=true

Perintah di atas akan membuat namespace velero, menginstal Custom Resource Definitions (CRDs) yang diperlukan, mendeploy controller Velero, dan mengonfigurasi integrasi dengan bucket AWS S3 kita.

2. Melakukan Backup Menggunakan Velero #

Setelah Velero terpasang, kita bisa melakukan backup satu namespace secara keseluruhan (termasuk manifest Deployment, Service, ConfigMap, Secret, dan PVC) dengan perintah berikut:

velero backup create production-ns-backup-20260617 \
  --include-namespaces production \
  --snapshot-volumes

Jika kita ingin membuat jadwal backup otomatis (misalnya setiap hari jam 03:00 pagi), kita dapat membuat resource Schedule Velero:

velero schedule create daily-production-backup \
  --schedule="0 3 * * *" \
  --include-namespaces production \
  --ttl 168h0m0s
  • --ttl 168h0m0s: Menentukan Time To Live (masa simpan) backup selama 7 hari (168 jam). Velero secara otomatis akan menghapus tarball manifest dan snapshot disk di cloud provider yang umurnya melebihi batas waktu tersebut untuk menghemat biaya penyimpanan.

3. Melakukan Pemulihan (Restore) dengan Velero #

Jika terjadi bencana total di mana kluster kita rusak parah, kita dapat membuat kluster baru yang kosong, menginstal Velero dengan konfigurasi bucket yang sama, lalu menarik backup yang ada:

# Ambil daftar backup yang tersedia di bucket
velero backup get

Setelah menemukan backup yang kita inginkan, kita jalankan perintah restore:

velero restore create --from-backup production-ns-backup-20260617 \
  --include-namespaces production \
  --restore-volumes=true

Velero akan membaca file tarball dari bucket, merekonstruksi seluruh objek di API Server Kubernetes dengan urutan yang benar (misalnya Namespace dibuat dulu, lalu Secret dan PVC, lalu Deployment), dan mengembalikan volume data kita dari snapshot CSI.


Etcd Backup: Jantung Keamanan Kluster Self-Managed #

Jika kita mengoperasikan kluster Kubernetes secara mandiri (self-managed) di atas VM bare-metal menggunakan utility seperti kubeadm atau kops, kita memiliki tanggung jawab penuh atas data control plane kluster kita yang disimpan di etcd.

Etcd adalah database key-value terdistribusi yang menyimpan kebenaran tunggal (single source of truth) dari konfigurasi dan status kluster Kubernetes. Kehilangan database etcd tanpa adanya backup berarti kita kehilangan seluruh kluster kita secara permanen.

[!NOTE] Bagi kita yang menggunakan managed service (seperti AWS EKS, GCP GKE, atau Azure AKS), control plane dan database etcd sepenuhnya dikelola oleh cloud provider. Oleh karena itu, kita tidak perlu memikirkan backup etcd dan bisa langsung memfokuskan strategi pada backup data PVC dan manifes aplikasi kita.

1. Membuat Snapshot Etcd Secara Manual #

Kita harus mengeksekusi utility etcdctl langsung di dalam node control plane tempat etcd berjalan. Karena etcd berkomunikasi menggunakan TLS, kita harus menyertakan sertifikat otentikasi kluster kita.

Jalankan perintah berikut di control plane node:

ETCDCTL_API=3 etcdctl snapshot save /var/lib/db-backup/etcd-snapshot-20260617.db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

Setelah snapshot selesai dibuat, kita harus memverifikasi integritas file database tersebut:

ETCDCTL_API=3 etcdctl snapshot status /var/lib/db-backup/etcd-snapshot-20260617.db --write-out=table

Output verifikasi yang valid akan menampilkan hash database, ukuran file, dan index transaksi terakhir:

+----------+----------+------------------+------------------+
|   HASH   | REVISION | TOTAL KEYS (EST) | TOTAL SIZE (EST) |
+----------+----------+------------------+------------------+
| c8e9e1a7 | 24950381 |             5204 |            4.8MB |
+----------+----------+------------------+------------------+

Jangan lupa untuk langsung mengirimkan file snapshot .db ini ke server eksternal atau Object Storage menggunakan cron job terpisah, agar data backup tidak ikut musnah jika node control plane tersebut meledak atau mengalami kerusakan hardware.

2. Memulihkan Kluster Menggunakan Snapshot Etcd #

Jika database etcd utama kita korup, kita bisa mengembalikan keadaan kluster ke titik waktu snapshot dibuat. Proses ini mengharuskan kita menghentikan layanan kontroler Kubernetes terlebih dahulu agar tidak ada transaksi baru saat data ditimpa.

# 1. Hentikan kube-apiserver dan etcd di control plane node (pindahkan manifest statis)
mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/
mv /etc/kubernetes/manifests/etcd.yaml /tmp/

# 2. Hapus atau backup data direktori etcd yang korup saat ini
mv /var/lib/etcd /var/lib/etcd-corrupted

# 3. Jalankan restore snapshot ke direktori baru
ETCDCTL_API=3 etcdctl snapshot restore /var/lib/db-backup/etcd-snapshot-20260617.db \
  --data-dir=/var/lib/etcd \
  --initial-cluster=control-plane-node=https://127.0.0.1:2380 \
  --initial-cluster-token=etcd-cluster-1 \
  --initial-advertise-peer-urls=https://127.0.0.1:2380 \
  --name=control-plane-node

# 4. Kembalikan manifes statis etcd dan kube-apiserver agar control plane aktif kembali
mv /tmp/etcd.yaml /etc/kubernetes/manifests/
mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/

Setelah kubelet memuat ulang objek-objek control plane, kita dapat memeriksa kesehatan kluster kembali menggunakan kubectl get nodes.


Anti-Pattern vs Solusi dalam Backup & Restore #

Mari kita pelajari beberapa kesalahan fatal (anti-pattern) yang sering dilakukan saat merancang strategi pencadangan data di Kubernetes, beserta contoh kode untuk memperbaikinya.

Anti-Pattern 1: Mengambil Snapshot DB Tanpa Fsync Lock/Logical Dump #

Kita membuat snapshot volume pada database PostgreSQL atau MySQL yang sedang aktif memproses ribuan transaksi tulis per detik tanpa menghentikan sementara proses tulis ke disk. Hal ini menghasilkan snapshot disk yang kotor (dirty snapshot) dan rentan mengalami kegagalan proses baca saat di-restore.

Kode Manifest Salah (Snapshot Langsung Tanpa Proteksi Data) #

# JANGAN LAKUKAN INI PADA DATABASE SIBUK
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: postgres-dirty-snapshot
  namespace: database
spec:
  volumeSnapshotClassName: csi-aws-ebs-snapshotclass
  source:
    persistentVolumeClaimName: postgres-pvc-0 # PVC database aktif langsung di-snapshot

Kode Solusi (Menggunakan Pre-Snapshot Hook via Velero) #

Kita disarankan menggunakan Velero Container Hooks untuk memberitahu database agar menulis seluruh data memori ke disk dan mengunci transaksi tulis sesaat sebelum snapshot dibuat, lalu melepas kuncinya setelah snapshot selesai.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  namespace: database
spec:
  serviceName: postgres-service
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
      annotations:
        # Pre-backup hook: Kunci tulis ke database
        pre.backup.velero.io/command: '["/bin/sh", "-c", "psql -U postgres -c \"SELECT pg_backup_start(''velero-backup'');\""]'
        pre.backup.velero.io/container: "postgres-db"
        # Post-backup hook: Lepas kunci tulis setelah snapshot selesai diambil
        post.backup.velero.io/command: '["/bin/sh", "-c", "psql -U postgres -c \"SELECT pg_backup_stop();\""]'
        post.backup.velero.io/container: "postgres-db"
    spec:
      containers:
        - name: postgres-db
          image: postgres:15
          # ... rest of container spec ...

Anti-Pattern 2: Menyimpan Backup di Disk Lokal Node Worker (hostPath) #

Kita membuat CronJob backup database dan menyimpannya ke dalam direktori node lokal menggunakan volume type hostPath. Jika node worker tersebut mati akibat kegagalan perangkat keras, data backup kita akan ikut hilang bersama node tersebut.

Kode Manifest Salah (Mengandalkan Disk Lokal Node) #

# JANGAN LAKUKAN INI: Backup tersimpan di node fisik
apiVersion: batch/v1
kind: CronJob
metadata:
  name: insecure-local-backup
  namespace: database
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: mysql-backup
              image: mysql:8.0
              command: ["/bin/sh", "-c", "mysqldump -h mysql-service -u root -p$MYSQL_ROOT_PASSWORD appdb > /backup/appdb.sql"]
              env:
                - name: MYSQL_ROOT_PASSWORD
                  value: "password"
              volumeMounts:
                - name: backup-dir
                  mountPath: /backup
          volumes:
            - name: backup-dir
              hostPath:
                path: /var/lib/mysql-backups # Data terikat pada satu node fisik saja!
                type: DirectoryOrCreate

Kode Solusi (Streaming Langsung ke External Cloud Storage) #

Kita harus mengalirkan hasil backup langsung ke Object Storage eksternal (seperti AWS S3, Google Cloud Storage, atau Azure Blob) melalui jaringan aman tanpa menyimpannya ke disk lokal node worker secara permanen.

# SOLUSI: Menggunakan AWS CLI S3 integration via pipe stream
apiVersion: batch/v1
kind: CronJob
metadata:
  name: secure-cloud-backup
  namespace: database
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: mysql-backup
              image: mysql:8.0
              command:
                - /bin/sh
                - -c
                - |
                  # Stream database dump langsung ke AWS S3 via CLI pipe
                  mysqldump -h mysql-service -u root -p"${MYSQL_ROOT_PASSWORD}" appdb | gzip | aws s3 cp - s3://my-cloud-backup-bucket/mysql/backup-$(date +%Y%m%d).sql.gz                  
              env:
                - name: MYSQL_ROOT_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysql-secret
                      key: database-password
                - name: AWS_ACCESS_KEY_ID
                  valueFrom:
                    secretKeyRef:
                      name: aws-credentials
                      key: access-key-id
                - name: AWS_SECRET_ACCESS_KEY
                  valueFrom:
                    secretKeyRef:
                      name: aws-credentials
                      key: secret-access-key

Panduan Rekomendasi Strategi & DR Drill #

Memiliki backup data tidak menjamin keberhasilan pemulihan bencana jika kita tidak pernah melakukan pengujian restore secara berkala. Sebagai panduan bagi tim platform, mari kita ikuti prinsip-prinsip berikut:

1. Terapkan Aturan Pencadangan 3-2-1 #

  • 3 Salinan Data: Kita harus memiliki setidaknya tiga salinan data: 1 data aktif di kluster produksi, 1 backup cepat berupa CSI volume snapshot di cloud local backend, dan 1 logical backup (misalnya dump file SQL).
  • 2 Media Berbeda: Simpan data backup pada setidaknya dua jenis media penyimpanan yang terpisah (misalnya volume block storage snapshot, dan object storage bucket).
  • 1 Offsite Location: Pastikan setidaknya satu salinan backup disimpan di luar wilayah/region geografi utama kluster produksi kita (misalnya jika kluster berjalan di region AWS ap-southeast-1 Singapura, simpan backup offsite di region ap-southeast-3 Jakarta) untuk mengantisipasi kegagalan total pusat data regional cloud provider.

2. Lakukan Disaster Recovery (DR) Drill Secara Berkala #

Sering kali kita baru menyadari bahwa file backup kita rusak atau tidak lengkap saat situasi darurat terjadi. Untuk mencegah bencana ini:

  • Jadwalkan latihan pemulihan data (DR Drill) secara rutin, minimal satu kali setiap bulan.
  • Gunakan kluster non-produksi (staging atau testing) untuk mensimulasikan kegagalan total, dan lakukan restore data menggunakan Velero atau manifest snapshot CSI.
  • Ukur RTO (Recovery Time Objective - berapa lama waktu pemulihan kluster kembali online) dan RPO (Recovery Point Objective - berapa banyak data transaksi terakhir yang hilang akibat selisih waktu backup) untuk disesuaikan dengan kebutuhan bisnis perusahaan kita.

Ringkasan #

  • Backup Kubernetes bersifat terfragmentasi: Kita harus memilah strategi pencadangan menjadi tiga pilar utama: State Kluster (Etcd), Data Volume (Persistent Volumes), dan Logika Aplikasi (Database dump).
  • Volume Snapshot CSI: Membantu kita melakukan backup disk secara point-in-time secara efisien di level infrastruktur. Kita dapat memulihkannya dengan mendefinisikan objek PVC baru menggunakan dataSource.
  • Logical Dump untuk Database: Sangat disarankan untuk database aktif guna menghindari risiko ketidakkonsistenan data (corrupted state) yang kerap terjadi pada model crash-consistent snapshot.
  • Velero sebagai Solusi Utama: Gunakan Velero untuk menangkap keadaan kluster secara menyeluruh dan mengotomatiskan siklus backup/restore manifest Kubernetes beserta volume datanya ke Object Storage eksternal.
  • Lindungi Etcd pada Kluster Mandiri: Jika mengelola kontrol plane sendiri, backup etcd dengan etcdctl snapshot save secara terjadwal adalah kewajiban mutlak.
  • Lakukan Simulasi Rutin: Backup data yang tidak pernah diuji proses restore-nya memiliki nilai pemulihan nol persen. Selalu lakukan latihan DR minimal satu bulan sekali.

← Sebelumnya: StatefulSet + PVC   Berikutnya: Dynamic Provisioning →

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