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 manifestapiVersion, kind, metadata, spec; field status dikelola 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: IfNotPresent untuk 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.
  • terminationGracePeriodSeconds sesuaikan 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 →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact