StatefulSet #
StatefulSet adalah resource Kubernetes untuk menjalankan aplikasi stateful — aplikasi yang perlu mengingat siapa dirinya, di mana datanya, dan dalam urutan apa ia berjalan. Database, message queue, dan distributed cache adalah kandidat utama. Jika Deployment memperlakukan semua Pod sebagai identik dan bisa saling menggantikan, StatefulSet memberikan setiap Pod identitas yang unik dan persisten.
Perbedaan Fundamental dengan Deployment #
Deployment:
Pod bernama: api-abc123, api-def456, api-ghi789 (nama random)
Pod bisa mati dan diganti dengan nama baru
Semua Pod punya storage yang sama (atau tidak punya storage persisten)
Urutan startup tidak dijamin
StatefulSet:
Pod bernama: postgres-0, postgres-1, postgres-2 (nama ordinal, tetap)
Pod yang sama selalu mendapat nama yang sama setelah restart
Setiap Pod punya PersistentVolume sendiri yang tidak bisa diambil Pod lain
Startup, scaling, dan update dilakukan secara berurutan
Stabilitas identitas ini yang membuat StatefulSet cocok untuk workload seperti database replicated — setiap replica perlu identitas yang konsisten agar primary tahu siapa secondary-nya, dan agar secondary tahu di mana datanya.
Struktur Manifest StatefulSet #
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: production
spec:
serviceName: "postgres" # headless service yang diperlukan
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
# PVC template — setiap Pod mendapat PVC sendiri
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard-ssd"
resources:
requests:
storage: 10Gi
Field volumeClaimTemplates adalah pembeda kunci dari Deployment. Kubernetes akan otomatis membuat PVC terpisah untuk setiap Pod:
data-postgres-0untuk Podpostgres-0data-postgres-1untuk Podpostgres-1data-postgres-2untuk Podpostgres-2
Identitas Stabil: Nama dan DNS #
Setiap Pod StatefulSet mendapat nama yang terprediksi dan tidak berubah:
StatefulSet "postgres" dengan 3 replicas:
Pod yang dibuat:
postgres-0 ← selalu indeks 0, nama ini tidak berubah
postgres-1
postgres-2
DNS name untuk setiap Pod (via Headless Service):
postgres-0.postgres.production.svc.cluster.local
postgres-1.postgres.production.svc.cluster.local
postgres-2.postgres.production.svc.cluster.local
Format: <pod-name>.<service-name>.<namespace>.svc.cluster.local
Ini memungkinkan Pod untuk saling menemukan satu sama lain dengan nama yang deterministik. Primary postgres bisa mengkonfigurasi secondary di postgres-1.postgres dan postgres-2.postgres — dan konfigurasi itu tetap valid meskipun Pod di-restart.
Headless Service #
StatefulSet membutuhkan Headless Service — Service tanpa ClusterIP yang memberikan DNS record untuk setiap Pod secara individual.
apiVersion: v1
kind: Service
metadata:
name: postgres # nama ini harus sama dengan spec.serviceName di StatefulSet
namespace: production
spec:
clusterIP: None # ← ini yang menjadikannya headless
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
Tanpa headless service, DNS pod individual tidak akan berfungsi. Dengan headless service:
postgres.production.svc.cluster.local→ mengembalikan IP semua Pod (untuk discovery)postgres-0.postgres.production.svc.cluster.local→ mengembalikan IP Pod spesifik
Ordered Operations #
StatefulSet memastikan Pod dibuat, dihapus, dan di-update secara berurutan:
Scaling up dari 0 ke 3:
1. Buat postgres-0, tunggu sampai Ready
2. Buat postgres-1, tunggu sampai Ready
3. Buat postgres-2, tunggu sampai Ready
Tidak ada Pod berikutnya dibuat sebelum Pod sebelumnya Ready.
Ini penting untuk database cluster yang butuh
primary berjalan sebelum secondary bisa join.
Scaling down dari 3 ke 1:
1. Hapus postgres-2, tunggu sampai benar-benar hilang
2. Hapus postgres-1, tunggu sampai benar-benar hilang
3. postgres-0 tetap berjalan
Selalu hapus dari indeks tertinggi — secondary sebelum primary.
Update Strategy #
StatefulSet mendukung dua update strategy:
RollingUpdate (default) — update Pod satu per satu, dari indeks tertinggi ke terendah:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0 # update semua Pod (default)
# partition: 2 → hanya update Pod dengan indeks >= 2
# → berguna untuk canary di StatefulSet
OnDelete — Pod tidak di-update secara otomatis; update terjadi hanya ketika Pod dihapus secara manual:
updateStrategy:
type: OnDelete # kamu yang kontrol kapan update terjadi
OnDelete berguna untuk database cluster di mana kamu ingin mengontrol secara manual kapan setiap replica di-upgrade, untuk memastikan tidak terjadi masalah replication.
PVC Tidak Ikut Terhapus #
Ini adalah perilaku yang perlu dipahami: ketika StatefulSet dihapus atau di-scale down, PVC tidak ikut terhapus. Ini disengaja — Kubernetes melindungi data kamu dari penghapusan yang tidak sengaja.
# Hapus StatefulSet
kubectl delete statefulset postgres
# PVC masih ada
kubectl get pvc
# NAME STATUS VOLUME CAPACITY AGE
# data-postgres-0 Bound pv-abc123 10Gi 30d
# data-postgres-1 Bound pv-def456 10Gi 30d
# data-postgres-2 Bound pv-ghi789 10Gi 30d
# Jika StatefulSet dibuat ulang, PVC yang sama akan di-bind kembali
# ke Pod dengan nama yang sama → data tidak hilang
Untuk benar-benar menghapus data, kamu harus menghapus PVC secara manual:
kubectl delete pvc data-postgres-0 data-postgres-1 data-postgres-2
Kapan Menggunakan StatefulSet #
Gunakan StatefulSet untuk:
✓ Database dengan replication (PostgreSQL, MySQL, MongoDB)
✓ Distributed cache dengan persistence (Redis Cluster)
✓ Message queue (Kafka, RabbitMQ)
✓ Distributed coordination service (ZooKeeper, Consul)
✓ Aplikasi yang butuh identitas node yang stabil
Jangan gunakan StatefulSet untuk:
✗ Aplikasi stateless (API, web server) → gunakan Deployment
✗ Aplikasi yang butuh shared storage (bukan per-Pod storage)
→ Deployment dengan shared PVC lebih tepat
✗ Database tunggal tanpa replication
→ StatefulSet bisa digunakan, tapi Deployment dengan PVC juga bisa
(lebih sederhana untuk kasus ini)
Menjalankan database di Kubernetes dengan StatefulSet bisa dilakukan, tapi butuh perencanaan yang matang — terutama soal backup, failover, dan storage performance. Untuk production workload kritikal, pertimbangkan menggunakan managed database service (RDS, Cloud SQL) dan biarkan Kubernetes fokus untuk menjalankan aplikasi stateless.
Ringkasan #
- Pod punya identitas permanen — nama ordinal (postgres-0, postgres-1) dan DNS individual yang tidak berubah meskipun Pod di-restart.
- Setiap Pod punya PVC sendiri — lewat
volumeClaimTemplates; data Pod satu tidak bercampur dengan Pod lain.- Headless Service wajib — tanpa
clusterIP: None, DNS per-Pod tidak berfungsi; nama headless service harus cocok denganspec.serviceNameStatefulSet.- Ordered startup dan shutdown — Pod dibuat dari indeks terkecil ke terbesar, dihapus dari terbesar ke terkecil; Pod berikutnya baru dibuat setelah sebelumnya Ready.
- PVC tidak ikut terhapus — proteksi dari penghapusan data yang tidak disengaja; PVC harus dihapus manual jika memang ingin membuang data.
- Partition update untuk canary StatefulSet —
rollingUpdate.partitionmemungkinkan hanya sebagian Pod yang di-update, cocok untuk testing versi baru di secondary sebelum primary.