Database di Kubernetes #
Menjalankan database di Kubernetes adalah topik yang sering memicu perdebatan di komunitas engineering. Sebagian berpendapat Kubernetes tidak cocok untuk workload stateful. Sebagian lagi berhasil menjalankan database di Kubernetes dalam skala besar di produksi. Keduanya tidak salah — konteksnya yang berbeda. Artikel ini membantu kamu memutuskan dengan data, bukan dengan opini.
Apa yang Membuat Database Berbeda #
Database bukan sekadar aplikasi biasa yang perlu storage. Ada beberapa karakteristik yang membuatnya lebih kompleks:
Perbedaan database vs aplikasi stateless:
Aplikasi stateless:
✓ Semua instance identik — bisa kill dan replace mana saja
✓ Scale-out dengan menambah replica lebih mudah
✓ Tidak ada state yang perlu dijaga konsisten antar instance
✓ Restart = fresh start tanpa konsekuensi
Database:
✗ Setiap instance punya identitas (primary, secondary, replica-1, dst)
✗ Scale-out butuh proses khusus (join cluster, sync data dulu)
✗ State harus konsisten dan terjaga saat ada kegagalan
✗ Restart bisa memerlukan recovery procedure
✗ Upgrade versi butuh koordinasi antar node cluster
Kapan Database di Kubernetes Masuk Akal #
Pertimbangkan database di Kubernetes jika:
✓ Tim punya keahlian operasional database di Kubernetes
✓ Butuh portabilitas (berjalan sama di cloud manapun atau on-premise)
✓ Strategi multi-cloud atau menghindari vendor lock-in
✓ Database development/staging yang boleh lebih sederhana
✓ Database untuk microservice kecil dengan traffic rendah
✓ Sudah menggunakan operator (Zalando Postgres Operator, Vitess, dll)
Pertimbangkan managed service (RDS, Cloud SQL, Atlas) jika:
✓ Database adalah core business dan downtime sangat mahal
✓ Tim tidak punya bandwidth untuk mengelola operasional database
✓ SLA tinggi (99.99%) lebih mudah dicapai dengan managed service
✓ Backup, failover, patching diinginkan "by default" tanpa setup
✓ Cost operasional yang diperhitungkan
Pola Dasar: StatefulSet untuk Database Tunggal #
Untuk database sederhana (single instance, bukan cluster), StatefulSet dengan PVC sudah cukup:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: production
spec:
serviceName: postgres
replicas: 1 # single instance — tidak ada replication
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15.4
env:
- name: POSTGRES_DB
value: "appdb"
- name: POSTGRES_USER
value: "appuser"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "4Gi"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
livenessProbe:
exec:
command:
- pg_isready
- -U
- appuser
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- appuser
initialDelaySeconds: 5
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: db-storage # StorageClass dengan IOPS tinggi
resources:
requests:
storage: 50Gi
Service untuk Akses Database #
# Service untuk koneksi internal cluster
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: production
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
clusterIP: None # Headless Service untuk StatefulSet
# DNS: postgres.production.svc.cluster.local
---
# Jika butuh koneksi dari luar cluster (untuk debugging)
apiVersion: v1
kind: Service
metadata:
name: postgres-external
namespace: production
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
type: ClusterIP # Jangan ekspos database ke internet!
# Gunakan kubectl port-forward untuk debugging
Operator Pattern untuk Database Kompleks #
Untuk database dengan replication, high availability, dan automated failover, pendekatan manual tidak scalable. Operator adalah solusinya — program yang mengotomasi semua operasional kompleks menggunakan Kubernetes API.
Operator Pattern:
Custom Resource Definition (CRD):
apiVersion: acid.zalan.do/v1
kind: postgresql ← resource kustom yang didefinisikan operator
metadata:
name: production-db
spec:
teamId: "platform"
volume:
size: 100Gi
numberOfInstances: 3 ← 1 primary + 2 secondary
postgresql:
version: "15"
backup:
retentionDays: 14
Operator Controller:
→ Baca spec postgresql "production-db"
→ Buat StatefulSet dengan 3 instance PostgreSQL
→ Konfigurasi Patroni untuk HA dan automatic failover
→ Setup backup terjadwal ke S3
→ Handle failover otomatis saat primary mati
→ Manage rolling upgrade saat versi PostgreSQL diperbarui
Operator populer untuk database di Kubernetes:
PostgreSQL:
→ Zalando Postgres Operator (paling mature, production-proven)
→ CloudNativePG (CNCF project, modern design)
→ Crunchy Data PGO
MySQL / MariaDB:
→ Percona Operator for MySQL
→ Oracle MySQL Operator
MongoDB:
→ MongoDB Community Operator
→ Percona Operator for MongoDB
Redis:
→ Redis Operator (Spotahome)
→ Redis Enterprise Operator
Kafka:
→ Strimzi (CNCF project, paling mature)
Checklist Sebelum Database ke Kubernetes Production #
STORAGE:
□ StorageClass dengan IOPS yang tepat untuk workload
□ volumeBindingMode: WaitForFirstConsumer (untuk multi-AZ)
□ reclaimPolicy: Retain agar data tidak terhapus saat PVC dihapus
□ Storage yang cukup dengan buffer minimal 30%
BACKUP:
□ Backup otomatis terjadwal (minimal sekali sehari)
□ Backup disimpan di tempat terpisah dari cluster
□ Proses restore sudah diuji dan terdokumentasi
□ Point-in-time recovery dikonfigurasi jika butuh
HIGH AVAILABILITY:
□ Minimal 2 node untuk replicated database
□ Anti-affinity rules agar replica tidak di node yang sama
□ Automatic failover dikonfigurasi dan diuji
□ Connection pooling untuk mengelola koneksi
MONITORING:
□ Database metrics di-export ke Prometheus
□ Alert untuk: disk usage > 80%, replication lag, connection saturation
□ Slow query logging aktif
SECURITY:
□ Kredensial database disimpan di Secret (bukan ConfigMap)
□ Akses network dibatasi dengan NetworkPolicy
□ Database tidak di-expose keluar cluster
Ringkasan #
- Database di Kubernetes bisa dilakukan, tapi lebih kompleks — stateful lifecycle, replication, failover, dan backup butuh lebih dari sekadar membuat StatefulSet.
- Managed service untuk database kritikal — jika downtime sangat mahal dan tim tidak punya bandwidth operasional, RDS/Cloud SQL/Atlas lebih pragmatis.
- StatefulSet untuk database sederhana — single-instance database untuk microservice kecil atau non-kritikal sudah cukup dengan StatefulSet + PVC.
- Operator untuk database kompleks — Zalando Postgres Operator, CloudNativePG, Strimzi untuk Kafka; operator mengotomasi semua yang tidak bisa dilakukan StatefulSet biasa.
- StorageClass dengan IOPS tinggi untuk database — jangan gunakan default StorageClass yang dioptimalkan untuk cost; database butuh throughput dan latensi yang konsisten.
- Backup adalah keharusan absolut — backup yang tidak diuji sama dengan tidak punya backup; test restore procedure secara regular.