Rantai Kepemilikan
Deployment ──membuat──> ReplicaSet ──membuat──> Pod (kelola rilis) (jaga jumlah) (jalankan kontainer)
Anda membuat Deployment. Deployment membuat ReplicaSet. ReplicaSet membuat Pod. Saat Anda memperbarui image, Deployment membuat ReplicaSet baru dan mengecilkan yang lama secara bertahap — itulah cara rolling update bekerja.
Deployment yang Layak Produksi
apiVersion: apps/v1
kind: Deployment
metadata:
name: layanan-pesanan
labels:
app: layanan-pesanan
spec:
replicas: 3
revisionHistoryLimit: 5
selector:
matchLabels:
app: layanan-pesanan # HARUS cocok dengan label template
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0 # kapasitas tidak pernah turun
template:
metadata:
labels:
app: layanan-pesanan
spec:
containers:
- name: api
image: registry.contoh.com/pesanan:2.4.0
ports:
- name: http
containerPort: 8080
env:
- name: LINGKUNGAN
value: produksi
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 512Mi
livenessProbe:
httpGet: { path: /healthz, port: http }
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet: { path: /readyz, port: http }
periodSeconds: 5
lifecycle:
preStop:
exec: { command: ["sleep", "5"] }
terminationGracePeriodSeconds: 45
Field spec.selector tidak bisa diubah setelah Deployment dibuat. Bila Anda perlu mengubahnya, Deployment harus dihapus dan dibuat ulang. Karena itu pilih label selector yang stabil sejak awal — jangan memasukkan nomor versi ke dalamnya.
Label dan Selector
Kubernetes tidak menghubungkan objek lewat referensi langsung, melainkan lewat label. Service menemukan Pod dengan mencocokkan label. ReplicaSet mengklaim Pod dengan mencocokkan label. Ini fleksibel, tetapi juga sumber kebingungan.
# Label yang dianjurkan (konvensi resmi)
metadata:
labels:
app.kubernetes.io/name: pesanan
app.kubernetes.io/instance: pesanan-produksi
app.kubernetes.io/version: "2.4.0"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: platform-toko
# Menyaring dengan selector kubectl get pods -l app=layanan-pesanan kubectl get pods -l 'lingkungan in (produksi,staging)' kubectl get pods -l 'app=pesanan,versi!=2.3.0' kubectl get pods --show-labels
Bila dua Deployment berbeda memakai label yang sama, Service akan mengirim trafik ke keduanya, dan ReplicaSet bisa saling "mencuri" pod. Gejalanya sangat membingungkan: sebagian permintaan mendapat respons dari aplikasi yang salah. Selalu sertakan nama aplikasi dan instansi di dalam label.
Mengendalikan Rilis
kubectl set image deploy/layanan-pesanan api=registry.contoh.com/pesanan:2.5.0 kubectl rollout status deploy/layanan-pesanan --timeout=180s kubectl rollout history deploy/layanan-pesanan kubectl rollout undo deploy/layanan-pesanan kubectl rollout undo deploy/layanan-pesanan --to-revision=3 # Menghentikan rilis di tengah jalan kubectl rollout pause deploy/layanan-pesanan kubectl rollout resume deploy/layanan-pesanan # Memaksa pembuatan ulang seluruh pod (misal untuk memuat Secret baru) kubectl rollout restart deploy/layanan-pesanan
Dengan maxUnavailable: 0 dan maxSurge: 1, Kubernetes selalu menyalakan pod baru dulu dan menunggunya siap sebelum mematikan yang lama. Kapasitas layanan tidak pernah berkurang selama rilis. Harganya: sementara waktu Anda memakai sumber daya satu pod lebih banyak. Untuk layanan yang menghadap pengguna, ini hampir selalu pertukaran yang tepat.
Jangan Pernah Memakai Tag :latest
Kubernetes memutuskan perlu-tidaknya rilis baru dengan membandingkan spesifikasi pod. Bila spesifikasinya tetap app:latest, tidak ada yang berubah — sehingga kubectl apply tidak melakukan apa pun meski image di registry sudah diperbarui. Lebih buruk lagi, pod yang di-restart di waktu berbeda bisa menarik image yang berbeda, sehingga replika Anda tidak lagi menjalankan kode yang sama. Selalu pakai tag versi atau digest.