Category: Kubernetes

  • Belajar Kubernetes #5: Pod, Unit Terkecil Kubernetes

    Belajar Kubernetes #5: Pod, Unit Terkecil Kubernetes

    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

  • Belajar Kubernetes #4: Perintah Dasar kubectl

    Belajar Kubernetes #4: Perintah Dasar kubectl

    Perintah dasar kubectl selalu mengikuti satu pola: kubectl [verb] [resource] [nama] [flag]. Verb adalah aksinya (get, describe, delete), resource adalah objek yang dikenai aksi (pod, deployment, service), nama menunjuk objek spesifik, dan flag mengatur detail perilakunya. Begitu pola ini nempel di kepala, kamu tidak perlu lagi menghafal puluhan perintah satu per satu.

    Artikel ini bagian keempat dari seri Belajar Kubernetes dari Nol. Kita akan praktik langsung: menjalankan perintah harian kubectl ke deployment nginx, membaca outputnya, lalu menutup dengan trik produktivitas yang dipakai tim Arrazy sehari-hari saat mengelola cluster untuk backend Go dan Laravel milik klien.

    Prasyarat Sebelum Mulai

    Pastikan Minikube dari bagian 1 masih jalan. Tutorial ini diuji dengan Minikube v1.33, kubectl v1.30, dan Kubernetes v1.30. Kalau kamu belum paham siapa yang sebenarnya menerima perintah kubectl di sisi cluster, baca dulu Belajar Kubernetes #3: Arsitektur Kubernetes Cluster. Singkatnya, kubectl hanyalah klien yang mengirim request HTTP ke API server.

    Cek dulu cluster hidup:

    minikube status
    kubectl version

    Lalu siapkan deployment nginx sebagai bahan praktik. Kalau deployment dari bagian 1 sudah terhapus, buat lagi:

    kubectl create deployment nginx --image=nginx:1.27

    Anatomi Perintah kubectl

    Bedah satu contoh nyata:

    kubectl get pods nginx-7584b6f84c-x2m9q -o wide
    • get adalah verb, artinya ambil dan tampilkan data
    • pods adalah resource yang dituju
    • nginx-7584b6f84c-x2m9q adalah nama objek spesifik, boleh dikosongkan untuk menampilkan semua
    • -o wide adalah flag, di sini mengatur format output

    Nama resource punya bentuk panjang dan singkatan. pods bisa ditulis pod atau po, deployments jadi deploy, services jadi svc. Daftar lengkapnya bisa dilihat dengan kubectl api-resources.

    Context dan Kubeconfig, Penentu Cluster Mana yang Kamu Sentuh

    kubectl tahu harus mengirim perintah ke cluster mana dari file kubeconfig, defaultnya di ~/.kube/config. File ini menyimpan daftar cluster, user, dan context. Context adalah pasangan cluster plus user plus namespace default. Saat kamu install Minikube, context bernama minikube otomatis dibuat dan diaktifkan.

    kubectl config current-context

    Output yang diharapkan:

    minikube

    Kalau nanti kamu pegang lebih dari satu cluster, misalnya Minikube di laptop dan k3s di VPS, gunakan kubectl config get-contexts untuk melihat semuanya dan kubectl config use-context minikube untuk pindah. Kebiasaan mengecek context sebelum menjalankan perintah destruktif itu penting. Salah context berarti perintah delete kamu mendarat di cluster yang salah.

    Tujuh Perintah Harian kubectl

    Tujuh verb ini menutupi mayoritas pekerjaan harian: get, describe, logs, exec, apply, delete, dan edit. Kita coba satu per satu ke deployment nginx.

    kubectl get, Melihat Daftar Resource

    kubectl get deployments
    kubectl get pods

    Output yang diharapkan kurang lebih:

    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    nginx   1/1     1            1           3m
    
    NAME                     READY   STATUS    RESTARTS   AGE
    nginx-7584b6f84c-x2m9q   1/1     Running   0          3m

    Bagian acak di belakang nama pod akan berbeda di mesinmu, itu normal karena pod dibuat otomatis oleh ReplicaSet. Mau lihat beberapa jenis resource sekaligus juga bisa:

    kubectl get deploy,pods,svc

    kubectl describe, Melihat Detail dan Event

    get memberi ringkasan, describe memberi cerita lengkap. Ganti nama pod sesuai output di mesinmu:

    kubectl describe pod nginx-7584b6f84c-x2m9q

    Scroll ke bagian paling bawah, ada tabel Events. Di sinilah Kubernetes mencatat riwayat pod: kapan dijadwalkan ke node, kapan image ditarik, kapan container dinyalakan. Saat pod bermasalah, Events hampir selalu jadi tempat pertama untuk mencari petunjuk.

    kubectl logs, Membaca Output Aplikasi

    kubectl logs deployment/nginx

    Perintah ini menampilkan log nginx, termasuk access log tiap request yang masuk. Dua flag yang sering dipakai: -f untuk mengikuti log secara live seperti tail -f, dan --previous untuk membaca log container yang sudah mati karena restart. Flag kedua ini penyelamat saat aplikasi crash berulang dan log-nya hilang tiap restart.

    kubectl exec, Masuk ke Dalam Container

    Kadang kamu perlu mengecek langsung dari dalam container: isi file konfigurasi, environment variable, atau koneksi ke service lain.

    kubectl exec -it deployment/nginx -- /bin/bash

    Flag -it membuat sesi interaktif dengan terminal, dan -- memisahkan argumen kubectl dari perintah yang dijalankan di dalam container. Setelah masuk, coba:

    cat /etc/nginx/conf.d/default.conf
    exit

    Untuk perintah sekali jalan tanpa masuk shell, langsung saja:

    kubectl exec deployment/nginx -- nginx -v

    Output yang diharapkan:

    nginx version: nginx/1.27.5

    kubectl apply, Menerapkan File YAML

    apply membaca file manifest lalu menyamakan kondisi cluster dengan isi file. Buat file percobaan bernama nginx-scale.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.27

    Terapkan lalu cek hasilnya:

    kubectl apply -f nginx-scale.yaml
    kubectl get pods

    Sekarang ada dua pod nginx. Jangan pusing dulu dengan struktur YAML-nya, itu jatah bagian 6. Yang penting dipahami sekarang: apply bersifat deklaratif. Kamu menyatakan kondisi akhir yang diinginkan, Kubernetes yang mengurus caranya.

    kubectl delete, Menghapus Resource

    Coba hapus salah satu pod, ganti dengan nama pod di mesinmu:

    kubectl delete pod nginx-7584b6f84c-x2m9q
    kubectl get pods

    Hasilnya menarik: pod yang dihapus hilang, tapi pod baru langsung muncul menggantikannya. Itu kerjaan ReplicaSet yang menjaga jumlah replicas tetap dua. Kalau mau benar-benar bersih, hapus deployment-nya, tapi jangan lakukan sekarang karena masih kita pakai.

    kubectl edit, Mengubah Resource Langsung

    kubectl edit deployment nginx

    Perintah ini membuka manifest deployment di editor terminal, defaultnya vi. Ubah replicas: 2 menjadi replicas: 3, simpan, keluar, lalu cek kubectl get pods. Pod ketiga muncul. Praktis untuk eksperimen, tapi di pekerjaan nyata tim Arrazy lebih memilih mengubah file YAML lalu apply ulang, supaya semua perubahan tercatat di Git dan bisa di-review.

    Cara Membaca Output kubectl get pods

    Empat kolom output kubectl get pods sering bikin pemula salah paham, jadi kita bedah:

    Kolom Arti
    READY Jumlah container siap dibanding total container di pod. 1/1 artinya satu dari satu container siap. 0/1 artinya container ada tapi belum siap menerima traffic
    STATUS Fase pod saat ini. Running berarti jalan normal. Pending berarti belum dijadwalkan atau image masih ditarik. CrashLoopBackOff berarti container terus mati dan Kubernetes menunda restart berikutnya. ImagePullBackOff berarti image gagal ditarik, biasanya salah nama atau tag
    RESTARTS Berapa kali container di-restart. Angka yang terus naik adalah alarm, cek logs --previous dan describe
    AGE Umur pod sejak dibuat. Berguna untuk memastikan pod baru benar-benar tercipta setelah update

    Kombinasi ketiganya yang perlu dibaca sebagai satu kesatuan. Pod dengan STATUS Running tapi READY 0/1 berarti proses jalan tapi belum lolos pemeriksaan kesiapan, topik yang kita dalami di bagian 13 tentang probe.

    Trik Produktivitas kubectl

    Alias k dan Autocompletion

    Mengetik kubectl ratusan kali sehari itu melelahkan. Hampir semua praktisi memakai alias satu huruf. Untuk pengguna bash:

    echo 'alias k=kubectl' >> ~/.bashrc
    echo 'source <(kubectl completion bash)' >> ~/.bashrc
    echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
    source ~/.bashrc

    Baris kedua mengaktifkan autocompletion, jadi menekan Tab akan melengkapi nama perintah, resource, bahkan nama pod. Baris ketiga membuat autocompletion ikut bekerja pada alias k. Pengguna zsh tinggal ganti bash menjadi zsh dan ~/.bashrc menjadi ~/.zshrc, tanpa baris complete.

    kubectl explain, Dokumentasi di Terminal

    Lupa field apa saja yang valid di sebuah resource? Tidak perlu buka browser:

    kubectl explain pod.spec.containers

    Output-nya menjelaskan setiap field beserta tipenya, langsung dari API server sesuai versi cluster yang kamu pakai. Perintah ini akan sangat sering kamu pakai saat mulai menulis YAML sendiri.

    Flag -o wide dan -o yaml

    kubectl get pods -o wide

    Flag -o wide menambah kolom IP pod dan node tempat pod berjalan. Sementara -o yaml menampilkan manifest lengkap sebuah resource persis seperti yang tersimpan di cluster:

    kubectl get deployment nginx -o yaml

    Ini cara cepat mempelajari struktur resource dari objek yang sudah jalan, termasuk field default yang diisi otomatis oleh Kubernetes.

    kubectl port-forward, Akses Cepat Tanpa Service

    Mau membuka nginx di browser tanpa bikin Service dulu? Forward saja port-nya:

    kubectl port-forward deployment/nginx 8080:80

    Output yang diharapkan:

    Forwarding from 127.0.0.1:8080 -> 80
    Forwarding from [::1]:8080 -> 80

    Buka http://localhost:8080 di browser dan halaman selamat datang nginx muncul. Tekan Ctrl+C untuk berhenti. Teknik ini juga aman dipakai di cluster production untuk mengintip dashboard internal atau database tanpa mengekspos apa pun ke publik. Tim kami memakainya hampir tiap hari saat membangun sistem aplikasi untuk klien, misalnya mengecek service backend yang belum punya Ingress.

    Troubleshooting Error Umum kubectl

    error: You must be logged in to the server (Unauthorized)

    Artinya request sampai ke API server tapi kredensialmu ditolak. Penyebab tersering di Minikube adalah sertifikat client yang kedaluwarsa atau kubeconfig yang menunjuk kredensial lama setelah cluster dibuat ulang. Solusi:

    minikube update-context

    Kalau masih gagal, jalan terakhir yang hampir selalu beres adalah minikube delete lalu minikube start. Cek juga apakah variabel KUBECONFIG sedang menunjuk file lain dengan echo $KUBECONFIG.

    The connection to the server localhost:8080 was refused

    Error klasik yang artinya kubectl tidak menemukan kubeconfig sama sekali, lalu jatuh ke alamat default localhost:8080. Biasanya karena Minikube belum dinyalakan atau kamu menjalankan kubectl sebagai user lain, misalnya lewat sudo, yang home directory-nya tidak punya ~/.kube/config. Jalankan minikube start dan jangan pakai sudo untuk kubectl.

    Perintah Mendarat di Cluster yang Salah

    Kamu merasa sudah membuat deployment tapi kubectl get pods hasilnya kosong, atau sebaliknya muncul resource asing yang tidak pernah kamu buat. Hampir pasti context-mu sedang menunjuk cluster lain. Cek dan pindahkan:

    kubectl config get-contexts
    kubectl config use-context minikube

    Tanda bintang di output get-contexts menunjukkan context aktif. Biasakan melirik context setiap kali membuka terminal baru, apalagi kalau kamu pegang cluster production.

    exec Gagal: /bin/bash no such file or directory

    Tidak semua image punya bash. Image berbasis Alpine misalnya hanya menyediakan sh. Kalau kubectl exec -it ... -- /bin/bash gagal dengan error ini, ganti dengan:

    kubectl exec -it deployment/nginx -- /bin/sh

    Rangkuman dan Lanjut ke Bagian 5

    Kamu sekarang pegang fondasi terpenting untuk bekerja dengan Kubernetes: pola verb resource nama flag, tujuh perintah harian, cara membaca output get, plus alias dan autocompletion supaya kerja lebih cepat. Semua materi setelah ini tinggal soal mengenal resource baru, karena cara mengoperasikannya tetap lewat perintah yang sama.

    Di bagian berikutnya, Belajar Kubernetes #5: Pod, Unit Terkecil Kubernetes, kita bedah pod lebih dalam: lifecycle-nya, kenapa satu pod bisa berisi lebih dari satu container, dan kapan itu berguna. Artikelnya terbit menyusul, pantau daftarnya di halaman hub Belajar Kubernetes.

    Referensi

  • Belajar Kubernetes #3: Arsitektur Kubernetes Cluster

    Belajar Kubernetes #3: Arsitektur Kubernetes Cluster

    Arsitektur Kubernetes terdiri dari dua bagian besar: control plane yang bertugas mengatur seluruh cluster, dan worker node tempat aplikasi kamu benar-benar berjalan. Control plane berisi kube-apiserver, etcd, scheduler, dan controller-manager. Worker node berisi kubelet, kube-proxy, dan container runtime seperti containerd. Semua komunikasi antar komponen lewat satu pintu, yaitu kube-apiserver.

    Kalau di dua bagian sebelumnya kita sudah install Minikube dan paham posisi Kubernetes dibanding Docker, sekarang saatnya membuka kap mesinnya. Artikel ini bagian ketiga dari seri Belajar Kubernetes dari Nol. Kita akan bedah tiap komponen, lihat langsung wujudnya di Minikube, lalu telusuri perjalanan satu perintah kubectl apply dari terminal sampai container menyala di node.

    Prasyarat Sebelum Mulai

    Kamu butuh Minikube yang sudah jalan. Di seri ini saya pakai Minikube v1.36.0 dengan Kubernetes v1.33 dan driver Docker. Kalau belum install, kembali dulu ke bagian pertama seri. Kalau masih bingung kenapa Kubernetes perlu banyak komponen padahal Docker terlihat sederhana, baca dulu Belajar Kubernetes #2: Perbedaan Docker dan Kubernetes. Bagian itu menjelaskan kenapa orkestrasi butuh “otak” terpisah dari mesin yang menjalankan container.

    Pastikan cluster hidup:

    minikube status

    Output yang diharapkan:

    minikube
    type: Control Plane
    host: Running
    kubelet: Running
    apiserver: Running
    kubeconfig: Configured

    Gambaran Besar: Control Plane vs Worker Node

    Bayangkan cluster Kubernetes sebagai sebuah kantor. Control plane adalah lantai manajemen. Worker node adalah lantai produksi tempat pekerjaan dikerjakan. Manajemen tidak pernah mengerjakan produksi langsung. Mereka hanya mencatat pesanan, memutuskan siapa mengerjakan apa, lalu memantau hasilnya.

    +--------------------- CONTROL PLANE ---------------------+
    |                                                          |
    |   +----------------+        +---------------------+     |
    |   | kube-apiserver |<------>|        etcd         |     |
    |   |  (pintu masuk) |        |  (penyimpan state)  |     |
    |   +-------+--------+        +---------------------+     |
    |           ^                                              |
    |           |                                              |
    |   +-------+--------+        +---------------------+     |
    |   | kube-scheduler |        | controller-manager  |     |
    |   +----------------+        +---------------------+     |
    |                                                          |
    +---------------------------+------------------------------+
                                |
                  semua lewat apiserver (HTTPS)
                                |
    +--------------------- WORKER NODE ------------------------+
    |                                                           |
    |   +---------+     +------------+     +----------------+  |
    |   | kubelet |---->| containerd |---->| container app  |  |
    |   +---------+     +------------+     +----------------+  |
    |                                                           |
    |   +------------+                                          |
    |   | kube-proxy |  (mengatur lalu lintas jaringan)         |
    |   +------------+                                          |
    |                                                           |
    +-----------------------------------------------------------+

    Di production, control plane biasanya punya server sendiri, bahkan tiga server sekaligus supaya tahan gangguan. Worker node bisa puluhan sampai ribuan. Di Minikube, semuanya dijejalkan ke satu mesin. Praktis untuk belajar, tapi konsepnya tetap sama persis.

    Komponen Control Plane dan Tugasnya

    kube-apiserver, Resepsionis Satu Pintu

    Semua permintaan ke cluster masuk lewat kube-apiserver. Perintah kubectl, laporan dari kubelet, keputusan scheduler, semuanya. Tidak ada komponen yang boleh saling bicara langsung. Persis resepsionis kantor yang memvalidasi tamu, mencatat keperluan, lalu meneruskan ke bagian yang tepat. Apiserver juga yang memeriksa autentikasi dan otorisasi, jadi dia sekaligus satpamnya.

    etcd, Lemari Arsip Cluster

    etcd adalah database key-value yang menyimpan seluruh kondisi cluster. Berapa replika yang diminta, pod apa berjalan di node mana, isi ConfigMap, semuanya ada di sini. Hanya apiserver yang boleh membuka lemari arsip ini. Kalau etcd hilang tanpa backup, cluster kehilangan ingatannya. Aplikasi mungkin masih jalan sebentar, tapi cluster tidak lagi tahu apa yang seharusnya dia kelola.

    kube-scheduler, Manajer Penempatan

    Setiap kali ada pod baru yang belum punya node, scheduler yang memutuskan pod itu jalan di mana. Dia menimbang sisa CPU dan memori tiap node, aturan afinitas, dan batasan lain. Seperti manajer yang menerima tumpukan tugas baru lalu membagikannya ke karyawan yang bebannya paling ringan dan keahliannya cocok. Penting diingat, scheduler hanya memutuskan. Dia tidak menjalankan apa pun. Keputusannya dicatat kembali lewat apiserver.

    kube-controller-manager, Supervisor yang Tidak Pernah Tidur

    Controller-manager berisi banyak controller kecil yang kerjanya satu: membandingkan kondisi nyata dengan kondisi yang diinginkan, lalu mengoreksi selisihnya. Kamu minta 3 replika, ternyata satu pod mati, controller membuat penggantinya. Seperti supervisor yang tiap beberapa detik keliling lantai produksi sambil membawa daftar pesanan. Ada yang kurang, dia langsung menugaskan ulang. Pola “desired state vs actual state” ini adalah jantung cara kerja Kubernetes.

    Komponen Worker Node dan Alurnya

    kubelet, Mandor di Tiap Node

    kubelet adalah agen yang berjalan di setiap node. Dia rajin bertanya ke apiserver, “ada pod yang ditugaskan ke node saya?” Kalau ada, dia yang mengeksekusi: minta container runtime menarik image, membuat container, lalu melaporkan statusnya balik ke apiserver. kubelet juga yang menjalankan health check ke container.

    Container Runtime (containerd), Tukang yang Benar-Benar Bekerja

    kubelet tidak bisa menjalankan container sendiri. Dia menyuruh container runtime lewat antarmuka standar bernama CRI (Container Runtime Interface). Runtime yang paling umum sekarang adalah containerd, yang juga dipakai Minikube secara default sejak versi 1.30-an ketika memakai driver Docker. containerd yang menarik image dari registry, membuat filesystem container, dan menjalankan prosesnya.

    kube-proxy, Petugas Lalu Lintas Jaringan

    kube-proxy mengatur aturan jaringan di tiap node supaya traffic ke sebuah Service bisa sampai ke pod yang tepat, meskipun pod itu pindah-pindah node. Dia bekerja dengan menulis aturan iptables atau IPVS. Kita akan sering ketemu komponen ini lagi di bagian Service nanti.

    Praktik: Bedah Komponen di Minikube

    Teori cukup. Sekarang buktikan semua komponen itu benar-benar ada. Di Minikube, komponen control plane sendiri dijalankan sebagai pod di namespace kube-system:

    kubectl get pods -n kube-system

    Output yang diharapkan kurang lebih seperti ini:

    NAME                               READY   STATUS    RESTARTS   AGE
    coredns-674b8bbfcf-x7k2m           1/1     Running   0          15m
    etcd-minikube                      1/1     Running   0          15m
    kube-apiserver-minikube            1/1     Running   0          15m
    kube-controller-manager-minikube   1/1     Running   0          15m
    kube-proxy-9fkq4                   1/1     Running   0          15m
    kube-scheduler-minikube            1/1     Running   0          15m
    storage-provisioner                1/1     Running   0          15m

    Semua nama yang kita bahas ada di sana. coredns dan storage-provisioner adalah komponen tambahan, nanti kita bahas di bagian lain. Sekarang masuk ke dalam node Minikube untuk melihat kubelet, karena kubelet tidak berjalan sebagai pod melainkan sebagai service di sistem operasi node:

    minikube ssh

    Setelah masuk, cek kubelet dan containerd:

    docker@minikube:~$ pgrep -a kubelet
    1123 /var/lib/minikube/binaries/v1.33.1/kubelet --bootstrap-kubeconfig=...
    
    docker@minikube:~$ sudo crictl ps | head -5
    CONTAINER      IMAGE          CREATED         STATE     NAME
    a1b2c3d4e5f6   6ba9545b2183   16 minutes ago  Running   kube-apiserver
    ...

    crictl adalah CLI untuk bicara langsung ke container runtime lewat CRI. Dari sini terlihat jelas: apiserver, etcd, dan kawan-kawannya pada akhirnya juga cuma container yang dijalankan containerd, diasuh oleh kubelet. Ketik exit untuk keluar dari node.

    Terakhir, cek ke mana sebenarnya kubectl kamu mengirim perintah:

    kubectl cluster-info

    Output yang diharapkan:

    Kubernetes control plane is running at https://192.168.49.2:8443
    CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

    Catat alamat itu. 192.168.49.2 adalah IP node Minikube, dan 8443 adalah port kube-apiserver. Angka ini akan berguna sekali di bagian troubleshooting.

    Alur Lengkap Satu Perintah kubectl apply

    Sekarang gabungkan semuanya. Misal kamu menjalankan kubectl apply -f deployment.yaml yang meminta 1 replika nginx. Ini yang terjadi di balik layar, urut:

    1. kubectl membaca kubeconfig di ~/.kube/config, menemukan alamat apiserver (di Minikube: https://192.168.49.2:8443), lalu mengirim request HTTPS berisi manifest kamu.
    2. kube-apiserver memvalidasi request itu. Autentikasi lolos, format YAML benar, lalu objek Deployment dicatat ke etcd. Sampai sini kubectl sudah menjawab “deployment.apps/nginx created”, padahal belum ada container apa pun yang jalan.
    3. Controller-manager melihat ada Deployment baru yang butuh 1 replika tapi realitasnya 0. Dia membuat objek Pod lewat apiserver. Pod ini statusnya Pending, belum punya node.
    4. Scheduler melihat ada pod tanpa node. Dia menilai node yang tersedia, memilih satu, lalu mencatat keputusannya lewat apiserver.
    5. kubelet di node terpilih melihat ada pod yang ditugaskan untuknya. Dia menyuruh containerd menarik image nginx dan menjalankan container.
    6. kubelet melaporkan status balik ke apiserver, yang menyimpannya di etcd. Status pod berubah menjadi Running, dan itulah yang kamu lihat saat menjalankan kubectl get pods.

    Perhatikan polanya. Tidak ada satu pun komponen yang saling perintah langsung. Semua menulis dan membaca lewat apiserver, mirip karyawan kantor yang berkoordinasi lewat satu sistem tiket, bukan teriak-teriakan antar meja. Pola ini yang membuat Kubernetes tahan banting. Satu komponen mati, komponen lain tinggal melanjutkan dari catatan terakhir di etcd. Pemahaman alur ini juga yang kami pakai sehari-hari di Arrazy saat menelusuri masalah deployment di server klien, karena begitu tahu alurnya, kamu tahu persis komponen mana yang harus dicurigai saat sesuatu macet.

    Troubleshooting: Error yang Sering Dialami Pemula

    connection refused ke port 8443

    The connection to the server 192.168.49.2:8443 was refused - did you specify the right host or port?

    Cara membacanya: kubectl mencoba menghubungi kube-apiserver di IP node Minikube port 8443, tapi tidak ada yang menjawab. Artinya apiserver mati, dan penyebab paling umum adalah cluster Minikube-nya memang tidak sedang berjalan, misalnya setelah laptop restart. Solusinya:

    minikube status
    minikube start

    Kalau minikube status menunjukkan host Running tapi apiserver Stopped, jalankan minikube logs untuk melihat kenapa apiserver gagal naik. Sering kali penyebabnya resource, coba minikube start --memory=4096.

    connection refused ke localhost:8080

    The connection to the server localhost:8080 was refused - did you specify the right host or port?

    Beda dengan error sebelumnya, yang ini alamatnya localhost:8080. Itu alamat fallback kubectl saat dia tidak menemukan kubeconfig sama sekali. Biasanya karena file ~/.kube/config hilang, variabel KUBECONFIG menunjuk file yang salah, atau kamu menjalankan kubectl sebagai user lain (misalnya pakai sudo, yang home directory-nya beda). Cek dengan kubectl config view. Kalau kosong, jalankan minikube update-context atau minikube start supaya kubeconfig ditulis ulang.

    Pod kube-system CrashLoopBackOff setelah laptop sleep

    Kadang setelah laptop suspend lama, kubectl get pods -n kube-system menunjukkan etcd atau apiserver restart berkali-kali. Jam internal node melompat dan sertifikat internal sempat dianggap tidak valid. Solusi paling cepat untuk lingkungan belajar:

    minikube stop
    minikube start

    Kalau masih bermasalah juga, minikube delete lalu minikube start membuat cluster baru yang bersih. Di Minikube ini aman, karena tidak ada data production di dalamnya.

    Penutup dan Lanjutan Seri

    Sekarang kamu tahu isi kap mesin Kubernetes: control plane sebagai lantai manajemen dengan apiserver, etcd, scheduler, dan controller-manager, lalu worker node sebagai lantai produksi dengan kubelet, containerd, dan kube-proxy. Kamu juga sudah membuktikan sendiri komponennya lewat kubectl get pods -n kube-system dan minikube ssh, plus paham perjalanan lengkap satu kubectl apply.

    Bagian berikutnya, “Belajar Kubernetes #4: Perintah Dasar kubectl”, akan fokus melatih tanganmu dengan perintah kubectl yang paling sering dipakai sehari-hari. Artikelnya terbit menyusul, pantau daftarnya di halaman hub Belajar Kubernetes dari Nol.

    Referensi

  • Belajar Kubernetes #2: Perbedaan Docker dan Kubernetes

    Belajar Kubernetes #2: Perbedaan Docker dan Kubernetes

    Perbedaan Docker dan Kubernetes sebenarnya sederhana. Docker adalah alat untuk membungkus aplikasi menjadi container dan menjalankannya di satu mesin. Kubernetes adalah alat untuk mengatur banyak container di banyak mesin sekaligus: menyalakan ulang container yang mati, menambah salinan saat trafik naik, dan membagi beban antar container. Keduanya bukan pesaing. Docker bekerja di level “bagaimana satu container dibuat dan dijalankan”, Kubernetes bekerja di level “bagaimana ratusan container dikelola bersama”.

    Artikel ini bagian kedua dari seri Belajar Kubernetes dari Nol. Kita tidak akan berhenti di teori. Di bagian praktik nanti, kamu akan menghapus pod nginx secara paksa dan melihat sendiri Kubernetes menghidupkannya lagi tanpa disuruh. Itu cara paling cepat memahami kenapa orkestrasi itu ada.

    Prasyarat Sebelum Mulai

    Tutorial ini melanjutkan setup dari Belajar Kubernetes #1: Kubernetes Adalah + Install Minikube. Pastikan Minikube v1.36 sudah terpasang dan cluster bisa jalan dengan minikube start. Versi Kubernetes yang dipakai Minikube saat artikel ini ditulis adalah v1.33. Kalau kamu belum paham konsep container sama sekali, mampir dulu ke seri Belajar Docker, karena semua contoh di sini menganggap kamu sudah pernah menjalankan docker run.

    Rekap Singkat: Apa yang Docker Kerjakan

    Container adalah cara mengemas aplikasi beserta semua dependensinya menjadi satu paket yang bisa jalan di mana saja. Docker mempopulerkan konsep ini lewat tiga hal: Dockerfile untuk mendefinisikan isi paket, image sebagai hasil build yang siap didistribusikan, dan Docker Engine yang menjalankan image tersebut menjadi container.

    Untuk satu server, Docker sudah sangat cukup. Kamu build image, push ke registry, tarik di server, jalankan. Selesai. Ditambah docker compose, kamu bahkan bisa mengelola beberapa container sekaligus, misalnya aplikasi Laravel plus MySQL plus Redis, semuanya didefinisikan dalam satu file YAML.

    Di Mana Docker Saja Mulai Kewalahan

    Masalah muncul ketika aplikasi tumbuh melewati satu mesin. Coba bayangkan beberapa situasi ini:

    • Container mati jam 2 pagi. Docker punya restart policy seperti --restart unless-stopped, tapi itu hanya bekerja selama mesinnya masih hidup. Kalau servernya sendiri yang tumbang, tidak ada yang memindahkan container ke server lain.
    • Trafik naik mendadak. Kamu perlu menambah salinan aplikasi di beberapa server. Dengan Docker murni, kamu SSH ke tiap server satu per satu, jalankan container, lalu atur load balancer manual.
    • Deploy versi baru tanpa downtime. Prosedurnya manual: nyalakan container versi baru, cek sehat, alihkan trafik, matikan versi lama. Salah urutan sedikit, user kena error.
    • Container perlu saling menemukan. Aplikasi di server A perlu tahu alamat database di server B. IP berubah tiap kali container dibuat ulang, jadi hardcode alamat bukan pilihan.

    Semua masalah di atas bisa diselesaikan dengan skrip buatan sendiri. Banyak tim melakukannya, sampai skripnya jadi lebih rumit daripada aplikasinya. Kubernetes lahir untuk menstandarkan solusi masalah-masalah ini.

    Kenapa Perlu Orkestrasi: Empat Kemampuan Inti

    Orkestrasi artinya ada satu sistem yang terus mengawasi kondisi container dan mencocokkannya dengan kondisi yang kamu inginkan. Kamu tidak lagi memberi perintah “jalankan container ini”, melainkan mendeklarasikan “saya mau 3 salinan aplikasi ini selalu hidup”. Sisanya urusan Kubernetes.

    Scaling: menambah salinan dengan satu perintah

    Di Kubernetes, menambah salinan aplikasi dari 1 menjadi 5 cukup satu perintah, dan Kubernetes yang memutuskan container baru ditaruh di mesin mana. Tidak perlu SSH ke server satu per satu.

    Self-healing: container mati dihidupkan sendiri

    Kubernetes membandingkan jumlah container yang hidup dengan jumlah yang kamu deklarasikan. Kurang satu, dia buat satu lagi. Ini bukan fitur tambahan, ini perilaku default. Kita buktikan di bagian praktik nanti.

    Rolling update: ganti versi tanpa downtime

    Saat kamu update image ke versi baru, Kubernetes mengganti container secara bertahap. Container baru dinyalakan dulu, dicek sehat, baru container lama dimatikan. Kalau versi baru bermasalah, ada perintah rollback untuk kembali ke versi sebelumnya. Detailnya kita bahas di bagian 8 seri ini.

    Service discovery: container saling menemukan lewat nama

    Kubernetes memberi nama DNS internal untuk sekelompok container. Aplikasi cukup memanggil http://backend tanpa peduli container backend sedang hidup di mesin mana atau IP-nya berapa. Load balancing antar salinan juga otomatis.

    Perbedaan Peran: Docker Membangun, Kubernetes Mengatur

    Cara paling mudah membedakan keduanya adalah lewat pembagian kerja di alur pengembangan:

    Aspek Docker Kubernetes
    Peran utama Membangun image dan menjalankan container Mengatur container di banyak mesin
    Lingkup Satu mesin Cluster berisi banyak mesin
    Unit kerja Container Pod (berisi satu atau lebih container)
    Kalau container mati Restart di mesin yang sama, kalau restart policy diset Dibuat ulang otomatis, bisa di mesin lain
    Scaling Manual per mesin Deklaratif, satu perintah untuk seluruh cluster
    Contoh perintah docker build, docker run kubectl apply, kubectl scale

    Dalam praktik keduanya dipakai bersama. Alur umumnya: developer menulis Dockerfile, docker build menghasilkan image, image dipush ke registry, lalu Kubernetes menarik image itu dan menjalankannya sebagai container di cluster. Docker hidup di laptop developer dan pipeline CI, Kubernetes hidup di server produksi.

    Posisi containerd setelah dockershim dihapus

    Kamu mungkin pernah baca judul berita “Kubernetes membuang Docker”. Yang sebenarnya terjadi lebih teknis dari itu. Kubernetes berkomunikasi dengan container runtime lewat standar bernama CRI (Container Runtime Interface). Docker Engine tidak berbicara CRI secara native, jadi dulu Kubernetes memelihara kode perantara bernama dockershim. Sejak Kubernetes 1.24 (2022), dockershim dihapus dan Kubernetes memakai runtime yang mendukung CRI langsung, paling umum containerd.

    Bagian menariknya: containerd justru komponen di dalam Docker itu sendiri. Saat kamu menjalankan docker run, yang benar-benar mengeksekusi container adalah containerd. Kubernetes hanya memotong jalur, memanggil containerd langsung tanpa lewat Docker Engine. Image hasil docker build tetap jalan normal di Kubernetes karena keduanya mengikuti standar OCI (Open Container Initiative). Jadi keahlian Docker kamu tidak ada yang terbuang.

    Praktik: Membuktikan Self-Healing di Minikube

    Sekarang bagian paling penting. Nyalakan cluster dulu:

    minikube start

    Di bagian 1 kita menjalankan nginx sebagai pod tunggal. Kali ini kita jalankan nginx lewat Deployment, yaitu objek Kubernetes yang menyimpan deklarasi “berapa salinan yang harus selalu hidup”. Detail Deployment dibahas di bagian 7, sekarang cukup pakai dulu:

    kubectl create deployment web-demo --image=nginx:1.27

    Output yang diharapkan:

    deployment.apps/web-demo created

    Cek pod yang dibuat:

    kubectl get pods
    NAME                        READY   STATUS    RESTARTS   AGE
    web-demo-7c9b8d6f4d-x2k9p   1/1     Running   0          20s

    Nama pod kamu pasti berbeda di bagian akhirnya, karena akhiran itu acak. Sekarang kita berperan jadi bencana. Hapus pod itu secara paksa (ganti nama pod sesuai output di terminalmu):

    kubectl delete pod web-demo-7c9b8d6f4d-x2k9p
    pod "web-demo-7c9b8d6f4d-x2k9p" deleted

    Kalau ini Docker biasa, cerita selesai, container hilang. Sekarang cek lagi:

    kubectl get pods
    NAME                        READY   STATUS    RESTARTS   AGE
    web-demo-7c9b8d6f4d-m5j7q   1/1     Running   0          8s

    Pod baru dengan nama akhiran berbeda muncul dalam hitungan detik, tanpa kamu melakukan apa pun. Kubernetes melihat jumlah pod hidup (0) tidak sesuai deklarasi (1), lalu memperbaikinya sendiri. Ini self-healing yang tadi kita bahas.

    Coba juga scaling. Satu perintah, tiga salinan:

    kubectl scale deployment web-demo --replicas=3
    kubectl get pods
    NAME                        READY   STATUS    RESTARTS   AGE
    web-demo-7c9b8d6f4d-m5j7q   1/1     Running   0          2m
    web-demo-7c9b8d6f4d-b8w4r   1/1     Running   0          10s
    web-demo-7c9b8d6f4d-t6n2c   1/1     Running   0          10s

    Selesai bereksperimen, bersihkan:

    kubectl delete deployment web-demo

    Kapan Kamu Tidak Perlu Kubernetes

    Bagian ini jarang ditulis di tutorial, tapi penting. Kubernetes punya biaya: kurva belajar panjang, komponen yang harus dirawat, dan kebutuhan resource server yang lebih besar. Untuk banyak kasus, docker compose di satu VPS adalah pilihan yang lebih waras.

    Cukup docker compose kalau: aplikasimu jalan nyaman di satu server, downtime beberapa menit saat deploy masih bisa diterima, dan timnya kecil. Di proyek sistem aplikasi yang tim Arrazy kerjakan untuk klien, sebagian besar backend Go dan Laravel memang kami jalankan dengan docker compose di satu VPS, karena skalanya belum menuntut lebih. Pindah ke Kubernetes baru masuk akal ketika kamu butuh lebih dari satu server, zero-downtime deploy jadi keharusan, atau frekuensi deploy sudah tinggi.

    Aturan praktisnya: mulai dari compose, pindah ke Kubernetes saat rasa sakitnya nyata, bukan karena ikut tren.

    Salah Paham yang Sering Muncul

    “Kubernetes adalah pengganti Docker”

    Salah. Keduanya beroperasi di lapisan berbeda dan justru saling melengkapi. Kamu tetap butuh Docker (atau alat sejenis seperti Podman dan Buildah) untuk membangun image. Yang benar-benar digantikan Kubernetes hanyalah Docker Engine sebagai runtime di node cluster, itu pun digantikan oleh containerd yang notabene bagian dari Docker sendiri.

    “Docker Swarm sama dengan Kubernetes”

    Keduanya memang sama-sama orkestrator, tapi bukan barang yang sama. Docker Swarm adalah orkestrator bawaan Docker, lebih sederhana dipelajari, dengan fitur yang jauh lebih terbatas. Kubernetes menang di ekosistem: autoscaling, ekstensi, tooling, dukungan semua cloud provider besar, dan lowongan kerja. Swarm masih hidup dan dipakai, tapi arah industri sudah jelas ke Kubernetes. Untuk belajar yang nilainya jangka panjang, Kubernetes pilihan yang lebih aman.

    Troubleshooting: Error yang Sering Dialami Pemula

    The connection to the server … was refused

    Muncul saat menjalankan perintah kubectl apa pun. Penyebab paling umum: cluster Minikube belum jalan. Solusinya jalankan minikube status, dan kalau statusnya Stopped, nyalakan dengan minikube start. Kalau masih gagal, cek apakah Docker Desktop atau service Docker di mesinmu sudah hidup, karena Minikube dengan driver docker menumpang di situ.

    Pod dihapus tapi tidak hidup lagi

    Kamu praktik self-healing tapi pod tidak muncul kembali. Hampir pasti pod itu dibuat dengan kubectl run (pod tunggal tanpa pengawas), bukan lewat Deployment. Pod tunggal tidak punya siapa pun yang mengawasi jumlahnya. Solusinya buat lewat kubectl create deployment seperti contoh di atas, lalu ulangi eksperimennya.

    Status pod ImagePullBackOff

    Kubernetes gagal menarik image dari registry. Cek dua hal: nama dan tag image salah ketik (misalnya ngnix atau tag yang tidak ada), atau koneksi internet dari dalam Minikube bermasalah. Jalankan kubectl describe pod nama-pod dan baca bagian Events di paling bawah, di situ tertulis alasan persisnya.

    Image hasil docker build tidak ditemukan di Minikube

    Kamu build image lokal, lalu deploy ke Minikube dan kena ErrImagePull. Penyebabnya Docker di laptopmu dan runtime di dalam Minikube punya penyimpanan image terpisah. Solusi paling mudah: minikube image load nama-image:tag untuk menyalin image ke dalam cluster, atau build langsung di dalam Minikube dengan minikube image build -t nama-image:tag .

    Lanjut ke Bagian Berikutnya

    Kamu sekarang paham pembagian kerjanya: Docker membangun dan mengemas, Kubernetes menjalankan dan menjaga. Kamu juga sudah melihat self-healing bekerja dengan mata sendiri. Pertanyaan berikutnya, siapa sebenarnya yang mengawasi pod tadi dan memutuskan pod baru harus dibuat? Jawabannya ada di komponen-komponen cluster, dan itu bahasan “Belajar Kubernetes #3: Arsitektur Kubernetes Cluster” yang terbit menyusul. Pantau daftar terbarunya di halaman Belajar Kubernetes dari Nol.

    Referensi

  • Belajar Kubernetes #1: Kubernetes Adalah + Install Minikube

    Belajar Kubernetes #1: Kubernetes Adalah + Install Minikube

    Kubernetes adalah platform open source untuk mengelola aplikasi berbasis container secara otomatis. Tugasnya mencakup menjalankan container di banyak server sekaligus, menghidupkan ulang container yang mati, membagi beban trafik, dan menaikkan jumlah container saat trafik ramai. Singkatnya, kalau Docker menjalankan satu container, Kubernetes mengatur ratusan container di banyak mesin supaya kamu tidak perlu mengurusnya satu per satu.

    Artikel ini bagian pertama dari seri Belajar Kubernetes dari Nol, total 26 bagian sampai kamu bisa deploy aplikasi web plus database di VPS sendiri. Di bagian ini kita bahas konsep dasarnya, lalu langsung praktik: install kubectl dan Minikube, jalankan cluster pertama, dan deploy nginx sebagai bukti environment kamu hidup. Prasyaratnya cuma satu: paham Docker dasar. Kalau belum, selesaikan dulu seri Belajar Docker dari Nol minimal sampai paham image, container, dan port mapping.

    Kubernetes Adalah Solusi untuk Masalah Banyak Container

    Bayangkan kamu punya aplikasi toko online yang sudah di-container-kan dengan Docker. Di laptop, satu perintah docker run sudah cukup. Masalah muncul waktu aplikasi itu masuk production dan trafiknya naik. Satu server tidak kuat, jadi kamu sewa tiga server. Sekarang pertanyaannya:

    • Container mana jalan di server mana?
    • Kalau satu container crash jam 3 pagi, siapa yang menghidupkan ulang?
    • Kalau satu server mati total, siapa yang memindahkan container ke server lain?
    • Kalau ada update versi aplikasi, bagaimana caranya ganti 20 container tanpa downtime?
    • Trafik naik saat flash sale, siapa yang menambah container lalu menguranginya lagi setelah sepi?

    Semua itu bisa dikerjakan manual dengan SSH ke tiap server dan menjalankan perintah Docker satu per satu. Untuk dua tiga container masih masuk akal. Untuk puluhan container di beberapa server, itu resep begadang. Kubernetes lahir untuk mengambil alih pekerjaan ini. Istilah kerennya container orchestration, orkestrasi container.

    Analogi paling gampang: Kubernetes itu seperti mandor proyek bangunan. Kamu sebagai pemilik proyek cukup bilang “saya mau 5 tukang ngecat tembok”. Mandor yang mengatur tukang mana ditempatkan di sisi mana, mencarikan pengganti kalau ada tukang yang sakit, dan menambah tukang kalau target dipercepat. Kamu tidak perlu mengawasi tukang satu per satu. Di Kubernetes, kamu menulis keinginan itu dalam file konfigurasi, misalnya “jalankan 5 replika aplikasi saya”, lalu Kubernetes yang menjaga kondisi itu terus terpenuhi. Konsep ini disebut desired state, dan ini yang membedakan Kubernetes dari sekadar menjalankan container manual.

    Tim kami di Arrazy memakai pola yang sama saat mengelola backend Go dan Laravel milik klien. Saat aplikasi masih kecil, Docker Compose di satu VPS cukup. Begitu kebutuhan uptime dan skala naik, orkestrasi seperti Kubernetes atau k3s jadi jauh lebih masuk akal daripada mengelola container manual lintas server.

    Alat yang Dibutuhkan: kubectl dan Minikube

    Untuk belajar, kamu tidak perlu sewa tiga server. Ada dua alat yang kita pakai sepanjang seri ini:

    • kubectl: command line untuk berkomunikasi dengan cluster Kubernetes. Semua perintah ke cluster lewat sini.
    • Minikube: alat untuk menjalankan cluster Kubernetes mini di laptop, cukup satu mesin. Cocok untuk belajar dan development.

    Spesifikasi minimum untuk Minikube: 2 CPU, 2 GB RAM bebas, 20 GB disk, dan Docker sudah terinstall (versi 20.10 ke atas, cek dengan docker version). Kita pakai Docker sebagai driver Minikube karena paling ringan dan tidak butuh VirtualBox.

    Install kubectl dan Minikube di Linux

    Contoh untuk Ubuntu 22.04 atau 24.04, arsitektur x86_64. Install kubectl versi stabil terbaru:

    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
    kubectl version --client

    Output yang diharapkan kurang lebih seperti ini (versi minor bisa berbeda):

    Client Version: v1.31.0
    Kustomize Version: v5.4.2

    Lanjut install Minikube:

    curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    sudo install minikube-linux-amd64 /usr/local/bin/minikube
    minikube version

    Output: minikube version: v1.34.0 atau lebih baru.

    Install kubectl dan Minikube di macOS

    Paling cepat lewat Homebrew:

    brew install kubectl minikube
    kubectl version --client
    minikube version

    Berlaku untuk Mac Intel maupun Apple Silicon. Pastikan Docker Desktop sudah jalan sebelum lanjut ke langkah berikutnya.

    Install kubectl dan Minikube di Windows

    Pakai winget dari PowerShell (jalankan sebagai Administrator):

    winget install -e --id Kubernetes.kubectl
    winget install -e --id Kubernetes.minikube

    Tutup dan buka lagi PowerShell supaya PATH terbaca, lalu verifikasi dengan kubectl version --client dan minikube version. Untuk Windows, saya sarankan Docker Desktop dengan backend WSL 2. Kalau kamu sudah terbiasa kerja di WSL 2 Ubuntu, boleh juga ikuti langkah Linux di atas langsung dari dalam WSL.

    Menjalankan Cluster Kubernetes Pertama

    Sekarang bagian serunya. Jalankan cluster dengan Kubernetes versi 1.31 supaya seragam sepanjang seri:

    minikube start --driver=docker --kubernetes-version=v1.31.0

    Proses pertama butuh beberapa menit karena Minikube mengunduh image Kubernetes sekitar 1 GB. Kalau sukses, baris terakhirnya seperti ini:

    Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

    Cek kondisi cluster dengan tiga perintah ini:

    minikube status

    Output yang diharapkan:

    minikube
    type: Control Plane
    host: Running
    kubelet: Running
    apiserver: Running
    kubeconfig: Configured

    Lalu cek node, yaitu mesin yang jadi anggota cluster. Di Minikube cuma ada satu:

    kubectl get nodes
    NAME       STATUS   ROLES           AGE   VERSION
    minikube   Ready    control-plane   1m    v1.31.0

    Terakhir, cek alamat komponen inti cluster:

    kubectl cluster-info
    Kubernetes control plane is running at https://192.168.49.2:8443
    CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

    Kalau ketiga perintah itu keluar tanpa error, selamat, kamu resmi punya cluster Kubernetes di laptop. Istilah seperti control plane dan node akan kita bedah di bagian 3 tentang arsitektur. Untuk sekarang cukup pahami: node adalah mesin pekerja, control plane adalah otaknya.

    Deploy Percobaan: Membuktikan Cluster Hidup

    Kita belum akan belajar deployment secara serius, itu jatah bagian 7. Tapi tidak afdol rasanya punya cluster tanpa menjalankan apa pun. Deploy nginx dengan satu perintah:

    kubectl create deployment nginx --image=nginx:1.27

    Output: deployment.apps/nginx created. Lalu lihat hasilnya:

    kubectl get pods
    NAME                     READY   STATUS    RESTARTS   AGE
    nginx-676b6c5bbc-8k2vw   1/1     Running   0          30s

    Kalau STATUS masih ContainerCreating, tunggu beberapa detik lalu jalankan lagi. Begitu Running, artinya Kubernetes berhasil menarik image nginx dan menjalankannya sebagai pod. Apa itu pod? Sabar, itu materi bagian 5. Sekarang hapus dulu percobaan ini supaya cluster bersih:

    kubectl delete deployment nginx

    Kalau mau istirahat, matikan cluster dengan minikube stop. Data dan konfigurasi tetap tersimpan, tinggal minikube start lagi kapan pun.

    Error Umum Saat Install Minikube dan Solusinya

    Virtualisasi belum aktif di BIOS

    Gejala: Minikube atau Docker Desktop gagal start dengan pesan seperti This computer doesn't have VT-X/AMD-v enabled. Penyebabnya fitur virtualisasi (Intel VT-x atau AMD-V) belum dinyalakan di BIOS/UEFI. Solusi: restart komputer, masuk BIOS (biasanya tombol F2, F10, atau Del), cari opsi bernama Intel Virtualization Technology, VT-x, AMD-V, atau SVM Mode, lalu set ke Enabled. Di Linux kamu bisa cek dulu dengan egrep -c '(vmx|svm)' /proc/cpuinfo. Kalau hasilnya lebih dari 0, virtualisasi didukung CPU kamu.

    Bingung driver docker vs virtualbox

    Minikube bisa jalan di atas beberapa driver. Dua yang paling sering dipakai pemula: docker dan virtualbox. Rekomendasi saya tegas: pakai --driver=docker. Lebih ringan, start lebih cepat, dan tidak perlu install aplikasi tambahan kalau Docker sudah ada. VirtualBox baru relevan kalau kamu memang tidak bisa memasang Docker. Kalau Minikube kamu telanjur terbuat dengan driver lain dan mau ganti, hapus dulu clusternya dengan minikube delete, lalu start ulang dengan flag driver yang benar. Ganti driver tidak bisa dilakukan pada cluster yang sudah jadi.

    minikube start gagal karena RAM kurang

    Gejala: muncul pesan seperti Requested memory allocation is less than the recommended minimum atau proses start macet lalu gagal. Minikube default meminta 2 GB ke atas, dan kalau laptop kamu sisa RAM-nya tipis karena browser membuka 30 tab, start bisa gagal. Solusi: tutup aplikasi berat, lalu jalankan dengan alokasi eksplisit, misalnya minikube start --driver=docker --memory=2048 --cpus=2 --kubernetes-version=v1.31.0. Kalau total RAM laptop 4 GB, pengalaman belajarnya akan berat. Pertimbangkan pakai VPS murah untuk lab, nanti di bagian 24 kita bahas install k3s di VPS yang jauh lebih hemat resource.

    Docker daemon tidak jalan atau permission denied

    Gejala: Cannot connect to the Docker daemon atau permission denied while trying to connect to the Docker daemon socket. Yang pertama artinya service Docker belum hidup, jalankan sudo systemctl start docker di Linux atau buka Docker Desktop di Windows/macOS. Yang kedua artinya user kamu belum masuk grup docker, perbaiki dengan sudo usermod -aG docker $USER lalu logout dan login lagi. Satu catatan penting: jangan menjalankan minikube start sebagai root, driver docker memang menolak dijalankan dengan sudo.

    Peta Lengkap Seri Belajar Kubernetes dari Nol

    Supaya kamu tahu arah perjalanan, ini peta 26 bagian yang akan kita lalui. Semuanya praktik di Minikube dulu, lalu pindah ke VPS sungguhan menjelang akhir.

    Bagian Topik Yang kamu kuasai
    1 sampai 4 Pengenalan, beda Docker vs Kubernetes, arsitektur cluster, perintah dasar kubectl Fondasi konsep dan alat kerja
    5 sampai 8 Pod, YAML manifest, Deployment dan ReplicaSet, rolling update dan rollback Menjalankan dan meng-update aplikasi tanpa downtime
    9 sampai 10 Service (ClusterIP, NodePort) dan Ingress Membuka akses aplikasi dari luar cluster
    11 sampai 14 ConfigMap, Secret, liveness dan readiness probe, resource request dan limit Konfigurasi dan kesehatan aplikasi ala production
    15 sampai 17 Volume, Persistent Volume dan PVC, StatefulSet Menyimpan data dan menjalankan database
    18 sampai 22 Namespace, RBAC, HPA autoscaling, Helm, logging dan monitoring Mengelola cluster secara rapi dan aman
    23 sampai 26 Deploy web plus database lengkap, install k3s di VPS, HTTPS dengan cert-manager, proyek akhir Aplikasi nyata jalan di VPS dengan domain dan HTTPS

    Di akhir seri, kamu akan punya aplikasi web lengkap dengan database yang berjalan di cluster milikmu sendiri di VPS, bisa diakses lewat domain dengan HTTPS. Itu portofolio yang layak ditunjukkan saat melamar kerja sebagai backend atau DevOps engineer.

    Rangkuman dan Lanjut ke Bagian 2

    Hari ini kamu sudah paham bahwa Kubernetes adalah orkestrator container, si mandor yang menjaga aplikasi tetap jalan sesuai keinginanmu di banyak mesin. Kamu juga sudah install kubectl dan Minikube, menjalankan cluster Kubernetes 1.31 pertama, membuktikannya hidup lewat kubectl get nodes, dan sempat deploy nginx sebagai pemanasan.

    Pertanyaan yang paling sering muncul setelah ini: kalau sudah bisa Docker, kenapa repot belajar Kubernetes, dan kapan Docker Compose saja sudah cukup? Itu tema bagian berikutnya, “Belajar Kubernetes #2: Perbedaan Docker dan Kubernetes”, yang terbit menyusul di halaman hub Belajar Kubernetes dari Nol. Sambil menunggu, biarkan Minikube terpasang dan coba ulangi perintah hari ini sampai lancar di luar kepala.

    Referensi