Anatomi Pod #
Pod adalah unit terkecil yang bisa dijadwalkan di Kubernetes, tapi di balik kesederhanaannya tersimpan banyak field yang masing-masing punya implikasi terhadap perilaku, performa, dan ketersediaan aplikasi. Membaca dan menulis Pod spec dengan benar — bukan sekadar copy-paste dari dokumentasi — adalah keterampilan dasar yang membedakan engineer yang paham Kubernetes dari yang sekadar bisa menggunakannya.
Struktur Manifest Pod #
Setiap Pod manifest terdiri dari empat bagian besar yang perlu dipahami masing-masing perannya:
apiVersion: v1 # ← API version untuk Pod selalu v1
kind: Pod # ← jenis resource
metadata: # ← identitas dan metadata
...
spec: # ← spesifikasi yang diinginkan
...
Selain keempat field ini, ada satu field yang dikelola Kubernetes (bukan kamu):
status: # ← kondisi aktual, diisi Kubernetes secara otomatis
phase: Running
conditions: [...]
containerStatuses: [...]
Kamu tidak pernah menulis status di manifest — ini adalah output yang dibaca untuk monitoring, bukan input yang ditulis untuk konfigurasi.
Metadata #
Metadata adalah lapisan identitas Pod. Field-field di sini digunakan oleh hampir semua mekanisme Kubernetes — dari Service selector hingga RBAC, dari monitoring hingga log aggregation.
metadata:
name: api-server-abc123 # nama unik dalam namespace
namespace: production # namespace tempat Pod berada
labels:
app: api # label untuk Service selector
version: v2 # label untuk canary/blue-green
environment: production # label untuk filtering
team: platform # label untuk ownership
annotations:
deployment.kubernetes.io/revision: "3" # metadata non-selector
prometheus.io/scrape: "true" # digunakan Prometheus
prometheus.io/port: "9090"
Label — key-value pair yang digunakan untuk grouping, selection, dan filtering. Service selector, Deployment selector, dan HPA semuanya bergantung pada label. Konsistensi label antar resource sangat penting.
Annotations — key-value pair untuk metadata yang tidak digunakan untuk selection. Bebas menyimpan informasi apapun: revision history, link ke dokumentasi, konfigurasi untuk tools eksternal seperti Prometheus atau Istio.
Spec: Container #
Bagian paling substansial dari Pod spec adalah definisi container. Satu Pod bisa punya satu atau lebih container.
spec:
containers:
- name: api # nama container, unik dalam Pod
image: my-registry/api:v2.1.0 # image dengan tag eksplisit
imagePullPolicy: IfNotPresent # Always | IfNotPresent | Never
ports:
- name: http # nama port (opsional tapi berguna)
containerPort: 8080
protocol: TCP
command: ["/app/server"] # override ENTRYPOINT image
args: ["--port=8080", "--env=prod"] # override CMD image
imagePullPolicy — field yang sering diabaikan tapi penting:
Always → selalu pull dari registry, bahkan jika sudah ada di node
→ gunakan untuk :latest tag (yang seharusnya dihindari di produksi)
IfNotPresent → pull hanya jika image belum ada di node
→ default jika tag bukan :latest
→ efisien, cocok untuk produksi dengan tag versi eksplisit
Never → tidak pernah pull, error jika image tidak ada di node
→ untuk lingkungan air-gapped atau image pre-loaded
Spec: Resource Requests dan Limits #
Ini adalah kontrak resource antara Pod dan scheduler. Tidak mendefinisikan ini di produksi adalah kesalahan serius.
resources:
requests:
cpu: "250m" # 250 millicore = 0.25 core
memory: "128Mi" # 128 Mebibytes
limits:
cpu: "500m"
memory: "256Mi"
Cara membaca satuan resource:
CPU:
1 = 1 core penuh
0.5 = 500m = setengah core
0.25 = 250m = seperempat core
Memory:
Ki = Kibibyte (1024 bytes)
Mi = Mebibyte (1024 Ki)
Gi = Gibibyte (1024 Mi)
k, M, G = Kilobyte, Megabyte, Gigabyte (base 10) — jarang digunakan
Implikasi saat limits dilampaui:
CPU limit dilampaui:
→ Container di-throttle (diperlambat)
→ Tidak di-kill
Memory limit dilampaui:
→ Container di-kill dengan OOMKilled
→ Kubernetes restart container (sesuai restartPolicy)
→ Jika terus terjadi → CrashLoopBackOff
Spec: Environment Variable #
Ada beberapa cara menginjeksikan environment variable ke container:
env:
# Nilai langsung (untuk nilai non-sensitif yang statis)
- name: APP_ENV
value: "production"
# Dari ConfigMap (nilai non-sensitif yang dikelola terpisah)
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_HOST
# Dari Secret (nilai sensitif)
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: DATABASE_PASSWORD
# Dari metadata Pod itu sendiri (Downward API)
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
Downward API — cara Pod mengetahui informasi tentang dirinya sendiri (nama, namespace, node, label) tanpa harus query API Server. Berguna untuk logging dan tracing.
Spec: Volume dan Volume Mount #
Volume adalah cara container mengakses storage yang persisten atau berbagi file dengan container lain dalam Pod:
volumes:
- name: config-vol
configMap:
name: app-config # ConfigMap di-mount sebagai file
- name: secret-vol
secret:
secretName: app-secret
- name: data-vol
emptyDir: {} # volume sementara, hilang saat Pod mati
- name: persistent-vol
persistentVolumeClaim:
claimName: my-pvc # volume persisten via PVC
containers:
- name: api
volumeMounts:
- name: config-vol
mountPath: /etc/config # direktori di dalam container
readOnly: true
- name: data-vol
mountPath: /var/data
Spec: Health Check #
Liveness dan readiness probe adalah kontrak ketersediaan Pod dengan cluster:
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30 # tunggu 30 detik sebelum mulai probe
periodSeconds: 10 # probe setiap 10 detik
timeoutSeconds: 5 # timeout per probe
failureThreshold: 3 # restart setelah 3 kali gagal berturut-turut
successThreshold: 1 # butuh 1 sukses untuk dianggap sehat
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /health/live
port: 8080
failureThreshold: 30 # 30 * 10 detik = 5 menit waktu startup
periodSeconds: 10
Spec: Restart Policy dan Termination #
restartPolicy: Always # Always | OnFailure | Never
terminationGracePeriodSeconds: 60 # default: 30 detik
restartPolicy:
Always → selalu restart jika container mati (default, untuk long-running service)
OnFailure → restart hanya jika exit code != 0 (untuk Job)
Never → tidak pernah restart (untuk batch job yang harus selesai sekali)
terminationGracePeriodSeconds — waktu yang diberikan untuk graceful shutdown setelah SIGTERM dikirim. Setelah period ini, SIGKILL dikirim dan container mati paksa.
Spec: Init Container #
Init container berjalan sebelum container utama dan harus selesai sukses sebelum container utama dimulai:
initContainers:
- name: wait-for-db
image: busybox:1.35
command:
- sh
- -c
- |
until nc -z postgres-service 5432; do
echo "Waiting for database..."
sleep 2
done
echo "Database is ready"
containers:
- name: api
image: my-api:v2
# container ini baru jalan setelah wait-for-db selesai
Status Pod #
status adalah representasi kondisi aktual Pod yang diisi Kubernetes. Berguna untuk monitoring dan debugging:
status:
phase: Running # Pending | Running | Succeeded | Failed | Unknown
podIP: 192.168.1.42
hostIP: 10.0.0.5
startTime: "2024-01-15T08:30:00Z"
conditions:
- type: Ready
status: "True"
- type: ContainersReady
status: "True"
containerStatuses:
- name: api
ready: true
restartCount: 0
state:
running:
startedAt: "2024-01-15T08:30:15Z"
# Baca status Pod secara ringkas
kubectl get pod api-server-abc123
# Detail lengkap termasuk events
kubectl describe pod api-server-abc123
# Format JSON untuk scripting
kubectl get pod api-server-abc123 -o json | jq '.status'
Ringkasan #
- Empat bagian utama manifest —
apiVersion,kind,metadata,spec; fieldstatusdikelola Kubernetes, bukan ditulis manual.- Label untuk selection, annotation untuk metadata — Service dan Deployment selector bergantung pada label; annotation untuk informasi yang tidak dipakai untuk selection.
- Resource requests dan limits wajib di produksi — requests untuk scheduling, limits untuk perlindungan; memory limit yang terlampaui menyebabkan OOMKill.
imagePullPolicy: IfNotPresentuntuk produksi — efisien dan tidak bergantung pada koneksi registry saat startup; gunakan tag versi eksplisit, bukan:latest.- Downward API untuk self-awareness — Pod bisa mengetahui nama, namespace, dan node-nya sendiri tanpa query API Server.
terminationGracePeriodSecondssesuaikan dengan aplikasi — pastikan cukup waktu untuk graceful shutdown; default 30 detik sering tidak cukup untuk service yang menangani request berat.
← Sebelumnya: Etcd & Cluster Consistency Berikutnya: Single & Multi Container →