Kembali ke Artikel

Belajar Kubernetes #5: Pod, Unit Terkecil Kubernetes

Solusi IT

Pod Kubernetes adalah unit terkecil yang bisa kamu deploy di sebuah cluster. Bukan container. Ini poin yang sering bikin pemula bingung, karena di Docker kita terbiasa berpikir dalam satuan container. Di Kubernetes, container tidak pernah berdiri sendiri. Container selalu dibungkus dalam pod, dan pod itulah yang dijadwalkan ke node, diberi alamat IP, dan dikelola oleh cluster.

Di artikel ini kita akan membuat pod pertama, membedahnya dengan kubectl describe, memahami lifecycle-nya, membuktikan bahwa container dalam satu pod berbagi network, lalu sengaja membuat error ImagePullBackOff dan CrashLoopBackOff supaya kamu tahu cara mendiagnosanya. Artikel ini bagian kelima dari seri Belajar Kubernetes dari Nol, jadi kalau kamu baru masuk di tengah, mampir dulu ke halaman hub itu untuk lihat urutan lengkapnya.

Prasyarat Sebelum Praktik

Kamu butuh Minikube yang sudah jalan dan kubectl yang sudah terhubung ke cluster. Di seri ini saya memakai Minikube v1.36 dengan Kubernetes v1.33. Pastikan juga kamu sudah nyaman dengan perintah dasar seperti kubectl get dan kubectl describe. Kalau belum, baca dulu Belajar Kubernetes #4: Perintah Dasar kubectl karena semua perintah di artikel ini dibangun dari sana.

Cek dulu cluster kamu hidup:

kubectl get nodes

Output yang diharapkan:

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   10d   v1.33.1

Kenapa Pod, Bukan Container, yang Jadi Unit Terkecil

Kubernetes tidak menjadwalkan container satu per satu. Kubernetes menjadwalkan pod. Satu pod adalah satu “kapsul” berisi satu atau lebih container yang selalu hidup bersama di node yang sama, berbagi alamat IP yang sama, dan bisa berbagi volume yang sama.

Kenapa perlu lapisan ekstra ini? Karena ada kasus di mana dua proses harus benar-benar nempel: dijadwalkan bareng, mati bareng, dan saling akses lewat localhost. Kalau unit terkecilnya container, Kubernetes tidak punya cara menjamin dua container selalu ada di node yang sama. Dengan pod, jaminan itu otomatis.

Kapan Satu Pod Berisi Lebih dari Satu Container

Praktiknya, mayoritas pod berisi satu container. Satu aplikasi, satu container, satu pod. Pola lebih dari satu container dipakai untuk kasus khusus yang biasa disebut sidecar, misalnya:

  • Container log shipper yang membaca file log dari container utama lalu mengirimnya ke sistem logging terpusat.
  • Proxy seperti Envoy yang duduk di samping aplikasi untuk mengatur trafik (ini fondasi service mesh seperti Istio).
  • Container helper yang men-sync file konfigurasi atau konten secara berkala untuk dipakai container utama.

Aturan praktisnya sederhana. Kalau dua proses bisa di-scale terpisah, pisahkan ke pod berbeda. Kalau dua proses tidak ada gunanya hidup tanpa satu sama lain, baru pertimbangkan satu pod.

Praktik: Membuat Pod Nginx dengan kubectl run

Cara paling cepat membuat pod adalah perintah imperatif kubectl run:

kubectl run web-nginx --image=nginx:1.27

Output:

pod/web-nginx created

Cek statusnya:

kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
web-nginx   1/1     Running   0          15s

Kolom READY 1/1 artinya 1 dari 1 container di pod ini siap. Sekarang bedah pod-nya:

kubectl describe pod web-nginx

Outputnya panjang, tapi ada empat bagian yang paling sering saya baca saat debugging di proyek klien:

  • Node: di node mana pod ini dijadwalkan. Di Minikube selalu minikube, di cluster produksi ini penting saat ada node bermasalah.
  • IP: alamat IP pod. Setiap pod dapat IP sendiri di jaringan internal cluster.
  • Containers: image apa yang dipakai, port apa yang dibuka, dan state container saat ini.
  • Events: riwayat kejadian dari scheduler sampai container jalan. Ini tempat pertama mencari petunjuk saat pod bermasalah.

Bagian Events untuk pod yang sehat terlihat seperti ini:

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  40s   default-scheduler  Successfully assigned default/web-nginx to minikube
  Normal  Pulling    40s   kubelet            Pulling image "nginx:1.27"
  Normal  Pulled     31s   kubelet            Successfully pulled image "nginx:1.27"
  Normal  Created    31s   kubelet            Created container: web-nginx
  Normal  Started    31s   kubelet            Started container web-nginx

Urutan ini menceritakan alur hidup pod: dijadwalkan ke node, image ditarik dari registry, container dibuat, lalu dijalankan.

Lifecycle Pod: Pending, Running, Succeeded, Failed

Setiap pod punya fase (phase) yang bisa kamu lihat di kolom STATUS. Ini fase resminya:

Fase Artinya
Pending Pod sudah diterima cluster tapi container belum jalan. Biasanya sedang menunggu jadwal atau menunggu image ditarik.
Running Pod sudah menempel di node dan minimal satu container sedang berjalan.
Succeeded Semua container selesai dengan sukses dan tidak akan di-restart. Umum untuk pod tipe job atau task sekali jalan.
Failed Semua container berhenti dan minimal satu berakhir dengan error.

Kamu mungkin juga melihat status seperti ContainerCreating, ImagePullBackOff, atau CrashLoopBackOff di kolom STATUS. Itu bukan fase resmi, melainkan alasan detail yang ditampilkan kubectl supaya lebih informatif. ContainerCreating misalnya, muncul saat pod masih di fase Pending dan kubelet sedang menyiapkan container.

Pod Bersifat Sekali Pakai

Ini konsep yang wajib tertanam sejak awal: pod itu ephemeral, alias sekali pakai. Kalau pod mati atau dihapus, Kubernetes tidak menghidupkan pod yang sama. Tidak ada “restart pod” dalam arti pod lama bangkit lagi. Yang ada hanyalah pod baru dengan identitas baru dan IP baru. Buktikan:

kubectl delete pod web-nginx
pod "web-nginx" deleted

Jalankan kubectl get pods lagi. Kosong. Tidak ada yang menghidupkan ulang pod itu, karena kita membuatnya langsung tanpa controller. Fakta inilah yang nanti menjelaskan kenapa Deployment itu penting. Simpan dulu, kita bahas di akhir artikel.

Container dalam Satu Pod Berbagi Network dan Storage

Sekarang kita buktikan klaim tadi: semua container dalam satu pod berbagi network namespace yang sama. Artinya mereka saling akses lewat localhost tanpa perlu tahu IP siapa pun.

Buat file pod-duo.yaml berisi pod dengan dua container, nginx sebagai container utama dan sebuah sidecar berisi curl:

apiVersion: v1
kind: Pod
metadata:
  name: pod-duo
spec:
  containers:
    - name: web
      image: nginx:1.27
    - name: sidecar
      image: curlimages/curl:8.8.0
      command: ["sleep", "infinity"]

Jangan pusing dulu dengan struktur YAML-nya, kita bedah lengkap di bagian berikutnya dari seri ini. Terapkan:

kubectl apply -f pod-duo.yaml
kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
pod-duo   2/2     Running   0          20s

Perhatikan READY 2/2. Dua container, satu pod. Sekarang eksekusi curl dari dalam container sidecar ke localhost:

kubectl exec pod-duo -c sidecar -- curl -s localhost

Output:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Container sidecar berhasil mengakses nginx lewat localhost padahal nginx berjalan di container lain. Ini bukti dua container itu berbagi satu network namespace. Flag -c sidecar menentukan container mana yang menjalankan perintah, karena pod ini punya lebih dari satu container.

Selain network, container dalam satu pod juga bisa berbagi storage lewat volume yang di-mount ke masing-masing container. Topik volume kita dalami di bagian tersendiri, yang penting sekarang kamu tahu kemampuannya ada. Bersihkan dulu:

kubectl delete pod pod-duo

Troubleshooting: Error Pod yang Pasti Ditemui Pemula

Dua error ini hampir pasti kamu temui di minggu pertama belajar Kubernetes. Kita sengaja reproduksi supaya kamu kenal wajahnya.

ImagePullBackOff: Image Tidak Bisa Ditarik

Buat pod dengan nama image yang typo:

kubectl run salah-ketik --image=ngincx:1.27

Tunggu beberapa detik lalu cek:

kubectl get pods
NAME          READY   STATUS             RESTARTS   AGE
salah-ketik   0/1     ImagePullBackOff   0          30s

Penyebab paling umum: nama image salah ketik, tag tidak ada, atau image berada di registry privat tanpa kredensial. Cara diagnosa, baca Events:

kubectl describe pod salah-ketik

Di bagian Events akan ada baris seperti ini:

Failed to pull image "ngincx:1.27": ... repository does not exist or may require 'docker login'

Pesannya jujur: repository tidak ditemukan. Solusinya perbaiki nama image. Karena field image bisa diedit langsung, tidak perlu hapus pod:

kubectl set image pod/salah-ketik salah-ketik=nginx:1.27

Beberapa saat kemudian pod akan Running. Kata BackOff sendiri artinya Kubernetes menunggu makin lama di tiap percobaan ulang, mulai beberapa detik sampai maksimal lima menit, supaya registry tidak dihujani request.

CrashLoopBackOff: Aplikasi Mati Terus

Sekarang buat container yang langsung exit dengan kode error:

kubectl run crash-demo --image=busybox:1.36 -- sh -c "echo boom; exit 1"
kubectl get pods
NAME         READY   STATUS             RESTARTS      AGE
crash-demo   0/1     CrashLoopBackOff   3 (25s ago)   1m

Polanya: container jalan, mati, di-restart, mati lagi, dan jeda restart makin lama. Bedanya dengan ImagePullBackOff, di sini image berhasil ditarik tapi prosesnya sendiri yang mati. Penyebab umum di dunia nyata: aplikasi gagal konek ke database, environment variable wajib belum di-set, atau memang ada bug yang bikin proses exit.

Langkah diagnosa selalu sama. Pertama describe untuk lihat exit code, kedua baca log aplikasi:

kubectl logs crash-demo
boom

Kalau container sudah terlanjur di-restart dan kamu butuh log dari proses yang mati sebelumnya, pakai flag --previous:

kubectl logs crash-demo --previous

Di pengalaman tim kami menangani backend Go dan Laravel milik klien, hampir semua CrashLoopBackOff ujungnya ketahuan dari kubectl logs. Jadi biasakan urutannya: get pods untuk lihat gejala, describe untuk konteks, logs untuk akar masalah. Bersihkan kedua pod percobaan:

kubectl delete pod salah-ketik crash-demo

Pod Nyangkut di Pending

Satu lagi yang sering muncul: pod diam di status Pending lama sekali. Artinya scheduler belum menemukan node yang muat. Di Minikube ini biasanya terjadi kalau kamu meminta resource lebih besar dari kapasitas VM. Diagnosa tetap sama, kubectl describe pod lalu baca Events. Biasanya ada pesan Insufficient cpu atau Insufficient memory. Solusinya turunkan permintaan resource pod, atau besarkan Minikube dengan minikube start --cpus=4 --memory=4096.

Kenapa di Dunia Nyata Kita Jarang Membuat Pod Langsung

Setelah semua praktik di atas, ini pelajaran penutupnya: pod telanjang (bare pod) hampir tidak pernah dipakai di produksi. Alasannya balik ke sifat sekali pakai tadi. Kalau node tempat pod berjalan mati, pod ikut hilang dan tidak ada yang menggantikannya. Tidak ada self-healing, tidak ada scaling, tidak ada rolling update.

Di dunia nyata, pod selalu dikelola oleh controller seperti Deployment. Kamu mendeklarasikan “saya mau 3 replika aplikasi ini”, lalu Deployment yang memastikan selalu ada 3 pod hidup. Pod mati satu, dibuatkan penggantinya secara otomatis. Ini pola yang tim Arrazy pakai saat membangun sistem aplikasi untuk klien: tidak ada satu pun bare pod, semuanya lewat Deployment atau controller lain.

Lalu kenapa kita belajar pod duluan? Karena Deployment pada dasarnya hanyalah mesin pengelola pod. Semua skill hari ini, membaca describe, membaca Events, membaca logs, akan kamu pakai persis sama saat pod-nya dikelola Deployment.

Rangkuman dan Lanjut ke Mana

Hari ini kamu sudah pegang konsep paling fundamental di Kubernetes. Pod adalah unit terkecil yang bisa di-deploy, container di dalamnya berbagi network dan storage, lifecycle-nya berjalan dari Pending sampai Running atau Failed, dan sifatnya sekali pakai sehingga butuh controller untuk produksi. Kamu juga sudah kenal dua error klasik, ImagePullBackOff dan CrashLoopBackOff, lengkap dengan cara diagnosanya.

Sejauh ini kita banyak memakai perintah imperatif seperti kubectl run. Cara itu cepat untuk belajar, tapi tidak cocok untuk kerja tim karena tidak ada catatan konfigurasi yang bisa di-review dan di-versioning. Solusinya menulis manifest YAML, dan itu tepat bahasan berikutnya: “Belajar Kubernetes #6: Cara Membuat File YAML Kubernetes”. Bagian itu terbit menyusul, pantau daftarnya di halaman hub Belajar Kubernetes dari Nol.

Referensi

BACA JUGA

Artikel Lainnya di Kategori Kubernetes

Ingin Membaca Artikel Lainnya?

Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.

Lihat Semua Artikel