Kodeloka
  1. Kodeloka
  2. Kelas Kubernetes
  3. Materi

4 · Penyimpanan & Stateful · Modul 7 dari 14

Volume, PVC & StatefulSet

Menyimpan data yang bertahan melampaui umur pod, memahami mode akses yang sering disalahpahami, dan kapan StatefulSet benar-benar dibutuhkan.

Tiga Lapis Abstraksi Penyimpanan

StorageClass  →  cara menyediakan penyimpanan (SSD? HDD? terenkripsi?)
     │
PersistentVolume (PV)  →  potongan penyimpanan yang sebenarnya
     │
PersistentVolumeClaim (PVC)  →  permintaan dari aplikasi
     │
Pod  →  me-mount PVC sebagai direktori

Di kluster modern, Anda hampir tidak pernah membuat PV secara manual. Anda membuat PVC, dan StorageClass menyediakan PV secara dinamis.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-basisdata
spec:
  accessModes: [ReadWriteOnce]
  storageClassName: ssd-cepat
  resources:
    requests:
      storage: 50Gi

Mode Akses yang Sering Disalahpahami

ModeArti sebenarnya
ReadWriteOnce (RWO)Dapat di-mount baca-tulis oleh satu node — bukan satu pod. Beberapa pod di node yang sama bisa memakainya bersamaan.
ReadOnlyMany (ROX)Dapat di-mount baca-saja oleh banyak node.
ReadWriteMany (RWX)Dapat di-mount baca-tulis oleh banyak node. Butuh penyimpanan berbasis jaringan seperti NFS atau CephFS.
ReadWriteOncePodBenar-benar hanya satu pod. Ini yang sering sebenarnya Anda inginkan untuk database.
🚫 RWO adalah penyebab pod Pending yang sangat umum

Disk blok dari penyedia cloud (EBS, Persistent Disk) hampir selalu RWO — hanya bisa menempel pada satu node dalam satu waktu. Bila Deployment Anda punya 3 replika yang semuanya me-mount PVC RWO yang sama, hanya pod di node pertama yang berjalan; sisanya menggantung di Pending selamanya. Untuk beban kerja yang butuh penyimpanan bersama antar node, Anda perlu penyimpanan RWX seperti NFS — atau, yang biasanya lebih tepat, rancang ulang agar aplikasi tidak butuh berkas bersama sama sekali.

StatefulSet

Deployment memberi pod nama acak (pesanan-7d4f-x9k2) dan memperlakukan semuanya setara. Beberapa sistem tidak bisa hidup seperti itu — database perlu tahu siapa yang primer, dan tiap replika perlu penyimpanannya sendiri yang tetap.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless    # WAJIB
  replicas: 3
  selector:
    matchLabels: { app: postgres }
  template:
    metadata:
      labels: { app: postgres }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: postgres
          image: postgres:17-alpine
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:             # PVC terpisah untuk TIAP replika
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        storageClassName: ssd-cepat
        resources:
          requests: { storage: 100Gi }

Yang Diberikan StatefulSet

JaminanPenjelasan
Nama yang stabilpostgres-0, postgres-1, postgres-2 — tetap sama setelah restart
DNS per podpostgres-0.postgres-headless.ns.svc.cluster.local
Penyimpanan yang melekatPVC data-postgres-0 selalu kembali ke pod postgres-0
Urutan yang terjaminDibuat 0→1→2, dihapus 2→1→0
⚠️ PVC tidak ikut terhapus

Menghapus StatefulSet tidak menghapus PVC-nya — ini disengaja, agar data tidak hilang karena kesalahan. Konsekuensinya, PVC bisa menumpuk tanpa disadari dan terus menagih biaya penyimpanan. Bersihkan secara sadar:

kubectl delete pvc -l app=postgres

Haruskah Database Dijalankan di Kubernetes?

🚫 Pertimbangkan baik-baik

Menjalankan database stateful di Kubernetes menuntut Anda menangani sendiri: failover dan pemilihan primer, backup beserta uji pemulihan, upgrade versi mayor, penyetelan parameter, dan pemantauan replikasi. Kubernetes tidak menyelesaikan satu pun dari itu — StatefulSet hanya menjamin identitas dan penyimpanan yang stabil.

Untuk sebagian besar tim, basis data terkelola dari penyedia cloud adalah pilihan yang jauh lebih bijak. Bila memang harus di Kubernetes, gunakan operator yang matang (CloudNativePG untuk PostgreSQL, Strimzi untuk Kafka) — jangan menulis StatefulSet mentah untuk database produksi.

Jenis Volume Lain

# emptyDir — hidup selama pod hidup, hilang saat pod mati
volumes:
  - name: sementara
    emptyDir:
      sizeLimit: 1Gi

# emptyDir di memori — sangat cepat, memakai RAM
  - name: cache-cepat
    emptyDir:
      medium: Memory
      sizeLimit: 256Mi

# Menyuntikkan metadata pod sebagai berkas
  - name: info-pod
    downwardAPI:
      items:
        - path: "nama-pod"
          fieldRef: { fieldPath: metadata.name }

# Menggabungkan beberapa sumber dalam satu mount
  - name: gabungan
    projected:
      sources:
        - configMap: { name: konfigurasi }
        - secret: { name: kredensial }
kubectl get pvc,pv
kubectl get storageclass
kubectl describe pvc data-basisdata
kubectl get statefulset postgres -o wide