Storage Problem di Distributed Systems #

Storage di sistem terdistribusi bukan sekadar “simpan file di disk”. Ketika aplikasi berjalan di banyak node yang bisa gagal kapan saja, bisa di-restart, bisa dipindah ke node lain, muncul serangkaian masalah yang tidak ada di environment non-distributed. Memahami masalah-masalah ini adalah prasyarat untuk merancang solusi storage yang benar — dan untuk memutuskan kapan lebih baik menggunakan managed service daripada mengelola sendiri di Kubernetes.

Masalah 1: Pod Berpindah, Data Tidak #

Kubernetes bisa memindahkan Pod ke node lain kapan saja — saat rolling update, node maintenance, atau node failure. Ini menimbulkan masalah fundamental dengan storage yang terikat ke node tertentu.

Skenario dengan node-local storage:

Node A: postgres-0 berjalan
  └── /data/postgres/ ← data tersimpan di disk Node A

Node A mengalami masalah → Pod di-evict → dijadwalkan ulang ke Node B

Node B: postgres-0 berjalan
  └── /data/postgres/ ← direktori ini KOSONG di Node B
  └── Data hilang!

Solusinya adalah storage yang independen dari node — cloud persistent disk (EBS, GCE PD), network storage (NFS, Ceph), atau distributed storage. Volume semacam ini bisa “di-attach” ke node mana saja saat Pod berpindah.

Dengan cloud persistent disk:

Node A: postgres-0 → EBS volume vol-abc123 (attached ke Node A)

Node A down → Pod pindah ke Node B
  → EBS volume di-detach dari Node A
  → EBS volume di-attach ke Node B
  → postgres-0 di Node B mount EBS volume yang sama
  → Data tetap ada dan konsisten

Masalah 2: Banyak Pod, Satu Storage #

Beberapa workload butuh banyak Pod yang membaca dan menulis ke storage yang sama — misalnya web server yang melayani file statis, atau aplikasi yang berbagi session storage berbasis file.

Masalah dengan block storage (EBS, GCE PD):

EBS volume hanya bisa di-attach ke SATU node dalam satu waktu (RWO)

Pod A (Node 1) ─── mount EBS vol-abc ✓
Pod B (Node 2) ─── mount EBS vol-abc ✗ GAGAL — sudah dipakai Pod A

Jika Pod B perlu akses volume yang sama, ada dua opsi:

Opsi 1: Pastikan Pod A dan Pod B selalu di node yang sama
  → Menggunakan Pod Affinity
  → Mengurangi ketersediaan (satu node down → semua Pod down)

Opsi 2: Gunakan network filesystem yang mendukung RWX
  → NFS, CephFS, Azure Files, Amazon EFS
  → Banyak node bisa mount bersamaan
  → Ada overhead performa dari network filesystem

Masalah 3: Konsistensi Data di Database Terdistribusi #

Menjalankan database dengan replication di Kubernetes menghadirkan tantangan konsistensi yang serius.

Database dengan primary-secondary replication:

postgres-0 (primary) ← semua write masuk ke sini
postgres-1 (secondary) ← replika dari primary, hanya read
postgres-2 (secondary) ← replika dari primary, hanya read

Skenario yang harus ditangani:
  1. postgres-0 down → siapa yang jadi primary?
     → Butuh mekanisme leader election (Patroni, pg_auto_failover)
     → Selama election berlangsung: write tidak bisa dilakukan

  2. postgres-1 tertinggal replikasinya (replication lag)
     → Read dari postgres-1 mungkin tidak mendapat data terbaru
     → Bisa menyebabkan inconsistency dari perspektif user

  3. Network partition: postgres-0 tidak bisa berkomunikasi dengan postgres-1
     → Apakah postgres-0 terus menerima write?
     → Apakah postgres-1 mempromosikan dirinya jadi primary?
     → Split-brain: dua node sama-sama menganggap diri primary

Split-brain adalah skenario paling berbahaya: dua instance database secara bersamaan menerima write tanpa sinkronisasi. Hasilnya adalah data yang divergen dan sangat sulit di-merge.


Masalah 4: Volume Attachment Race Condition #

Ketika Pod berpindah dengan cepat (misalnya node failure diikuti rescheduling cepat), ada race condition dalam proses detach-attach volume:

Race condition pada volume attachment:

[10:00:00] Node A down
[10:00:00] Kubernetes mulai proses eviction Pod dari Node A
[10:00:15] Pod dijadwalkan ke Node B
[10:00:15] Kubernetes coba attach EBS volume ke Node B

Masalah:
  → EBS volume masih tercatat "attached" ke Node A (walaupun Node A sudah down)
  → Cloud provider butuh waktu untuk memverifikasi Node A benar-benar down
  → Sampai verifikasi selesai, volume tidak bisa di-attach ke Node B

Kubernetes menangani ini dengan:
  → Volume attachment timeout (default ~6 menit untuk beberapa provider)
  → Selama itu, Pod baru tidak bisa dimulai dan menunggu

Ini adalah salah satu alasan mengapa recovery database di Kubernetes bisa lebih lambat dari yang diharapkan — bukan karena Pod lambat dimulai, tapi karena volume lambat di-attach.


Masalah 5: Storage Performance di Multi-Tenant Cluster #

Di cluster yang digunakan bersama banyak tim (multi-tenant), workload satu tim bisa mempengaruhi performa storage tim lain — fenomena yang disebut noisy neighbor.

Noisy neighbor pada shared storage:

Team A: batch job yang menulis 500 MB/s ke NFS
Team B: database yang butuh latensi read < 5ms

Tanpa isolasi:
  → Batch job Team A menyebabkan NFS overload
  → Latensi read Team B naik dari 2ms ke 50ms
  → Database Team B mengalami timeout

Solusi yang umum digunakan:
  → StorageClass berbeda untuk workload berbeda
    (storage premium untuk database, storage biasa untuk batch)
  → IOPS limit per volume (didukung beberapa cloud provider)
  → Pisahkan workload ke node pool yang berbeda dengan storage terpisah

Mengapa Ini Penting untuk Keputusan Arsitektur #

Masalah-masalah di atas bukan berarti tidak boleh menjalankan stateful workload di Kubernetes — tapi mereka menjelaskan mengapa ini lebih kompleks dari stateless workload dan membutuhkan perencanaan yang matang.

Decision framework untuk stateful workload di Kubernetes:

Apakah data ini kritikal dan tidak boleh hilang?
  └─ Ya → Apakah tim punya keahlian mengelola database di Kubernetes?
            └─ Tidak → Pertimbangkan managed database service (RDS, Cloud SQL)
            └─ Ya  → Gunakan StatefulSet dengan CSI driver yang tepat
                      Pastikan ada backup dan tested restore procedure

Apakah butuh shared storage (banyak Pod akses bersamaan)?
  └─ Ya → Apakah RWX performance overhead acceptable?
            └─ Ya → NFS, CephFS, atau cloud file storage (EFS, Azure Files)
            └─ Tidak → Pertimbangkan object storage (S3) atau arsitektur ulang

Apakah ini storage sementara dalam satu Pod?
  └─ Ya → emptyDir sudah cukup

Ringkasan #

  • Pod berpindah, data tidak — storage yang terikat ke node hilang saat Pod pindah; gunakan network-attached storage atau cloud persistent disk yang bisa follow Pod.
  • Block storage (RWO) untuk satu Pod, network filesystem (RWX) untuk banyak Pod — pilih access mode berdasarkan pola akses; RWX ada overhead performa.
  • Split-brain adalah risiko terbesar database terdistribusi — butuh mekanisme leader election yang solid; ini salah satu alasan mengelola database di Kubernetes lebih kompleks dari sekedar membuat StatefulSet.
  • Volume attachment race condition — saat node failure, ada periode ~6 menit sebelum volume bisa di-attach ke node baru; rancang availability target sesuai realita ini.
  • Noisy neighbor di shared cluster — isolasi workload storage-intensive dengan StorageClass berbeda dan IOPS limit untuk mencegah satu workload mendegradasi yang lain.
  • Pertimbangkan managed service untuk database kritikal — kompleksitas operasional database di Kubernetes nyata; managed service sering lebih pragmatis kecuali ada alasan spesifik.

← Sebelumnya: Volume   Berikutnya: PersistentVolume →

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