Menerbangkan tokokita ke Kubernetes: menulis Deployment, Service, HPA, PVC, ConfigMap, dan Secret per layanan, memasang liveness/readiness probes, ingress yang hanya mengekspos api-gateway, sampai strategi RollingUpdate yang aman

Kompose di episode 16 sudah membuat semua service berjalan sebagai container. Episode ini membawa tokokita ke anak tangga berikutnya: Kubernetes. Docker Compose merapikan satu host; Kubernetes mengorkestrasi banyak host dan memberi yang tidak dimiliki compose: self-healing, autoscaling, rolling update, service discovery DNS, dan declarative reconciliation.
Mengapa episode ini penting? Karena pola yang kita pakai di sini — Deployment + Service + probe + ingress — sama persis yang dipakai tim produksi nyata. Setelah episode ini, semua topik fase 5 dan 6 (mesh, scaling, GitOps) berpijak di atas cluster yang sama.
Gunakan k3d (atau kind) — cluster ringan untuk lab:
k3d cluster create tokokita \
--servers 1 --agents 2 \
--ports "8080:80@server:0"
kubectl cluster-infoSetiap service di infra/k8s/ punya pola yang sama. Contoh order-service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: tokokita
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: ghcr.io/tokokita/order-service:v1.4.2
ports:
- containerPort: 3004
envFrom:
- configMapRef:
name: tokokita-config
- secretRef:
name: tokokita-secrets
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /healthz
port: 3004
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /readyz
port: 3004
periodSeconds: 5apiVersion: v1
kind: Service
metadata:
name: order-service
namespace: tokokita
spec:
selector:
app: order-service
type: ClusterIP
ports:
- port: 80
targetPort: 3004Liveness vs readiness: livenessProbe memutus kapan pod mati dan di-restart; readinessProbe memutus kapan pod layak menerima traffic. Aplikasi wajib menyediakan dua endpoint berbeda: /healthz (proses hidup) dan /readyz (dependency siap — DB, cache tersambung).
Config non-rahasia di ConfigMap; rahasia di Secret (base64 di sini — di episode 19 diganti External Secrets):
apiVersion: v1
kind: ConfigMap
metadata:
name: tokokita-config
namespace: tokokita
data:
KAFKA_BROKERS: "kafka-cluster-kafka-bootstrap.kafka.svc.cluster.local:9092"
REDIS_URL: "redis://redis.redis.svc.cluster.local:6379"Database PostgreSQL butuh penyimpanan persisten:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: tokokita
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 20GiPVC dipasang ke volume di pod. Pada managed cloud, ini memicu dynamic provisioning ke disk cloud — data bertahan walau pod di-restart.
Prinsip episode 16 berlanjut di cluster: hanya api-gateway yang ter-expose ke luar. Service internal tetap ClusterIP yang hanya bisa diakses sesama cluster:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tokokita-ingress
namespace: tokokita
spec:
ingressClassName: nginx
tls:
- hosts: [tokokita.id]
secretName: tokokita-tls
rules:
- host: tokokita.id
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-gateway
port:
number: 80Ingress + TLS terminator bukan sekadar kenyamanan: ia juga memusatkan WAF/rate-limit opsional sebelum request menyentuh layanan apa pun. Detail lebih lanjut di episode 18-19.
Kafka bisa dijalankan di cluster lewat operator Strimzi (pengelolaan broker otomatis) atau broker eksternal. Untuk lab, biarkan Kafka/Redpanda di luar cluster dan hubungkan via address internal — topik dan partisi tetap sama, yang berubah hanya tempat broker tinggal. Prinsip: service tidak peduli broker di mana, selama endpoint KAFKA_BROKERS dikonfigurasi via ConfigMap.
Strategi default Deployment adalah RollingUpdate — pod baru diganti bertahap, tanpa downtime. Tuning yang aman untuk layanan stateless:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0maxSurge: 1 — paling banyak 1 pod ekstra saat naik; cluster tidak kedatangan banyak beban tiba-tiba.maxUnavailable: 0 — tidak ada pod yang mati baru diganti; layanan tak pernah kehilangan kapasitas penuh saat deploy.Aturan sosialnya: jangan deploy banyak service dalam satu waktu. Satu service di-rollout terlebih dahulu, dipantau, baru lanjut — kalau tidak, tidak tahu mana yang menyebabkan regresi. Ini juga bekal episode 23 (CI/CD & canary).
kubectl -n tokokita get deployments,svc,pods
kubectl -n tokokita get hpa
kubectl -n tokokita rollout status deployment/order-service --timeout=60s
curl -s https://tokokita.id/api/healthNote
HPA (Horizontal Pod Autoscaler) yang dipakai di manifest belum dijelaskan — tenang, ini dibahas penuh di episode 21 bersama KEDA dan capacity planning. Yang penting di episode ini: pola Deployment + Service + probe + ingress sudah benar dan berlaku untuk semua service tokokita.
Episode 17 menerbangkan tokokita ke Kubernetes:
ClusterIP + envFrom ConfigMap/Secret.livenessProbe (hidup) vs readinessProbe (siap terima trafik).maxSurge:1, maxUnavailable:0; deploy satu service pada satu waktu.Di episode 18 selanjutnya, kita akan mengenal service mesh (Istio/Linkerd) & mTLS — kapan sebuah tim benar-benar membutuhkan mesh, perbedaan Istio vs Linkerd, dan bagaimana mTLS mengamankan komunikasi antar layanan di dalam cluster. Sampai jumpa di episode 18!