Mengapa Kubernetes Ada

Latar munculnya Kubernetes dari masalah pengelolaan container dalam skala besar dan peran platform orkestrasi.

Daftar isi

Topik ini menjelaskan latar munculnya Kubernetes dari dua arah, yaitu masalah yang timbul ketika aplikasi berbasis container dijalankan dalam jumlah besar dan jawaban yang diberikan platform orkestrasi terhadap masalah itu. Pembahasan dimulai dari perilaku satu container pada satu mesin, dilanjutkan dengan kesulitan yang muncul pada skala ratusan hingga ribuan container, kemudian ditutup dengan cara Kubernetes memandang infrastruktur sebagai keadaan yang dinyatakan dan dijaga. Setelah topik ini dibaca, alasan di balik istilah-istilah seperti kluster, Pod, dan rekonsiliasi menjadi jelas, sehingga dokumentasi Kubernetes lebih mudah diikuti.

Keterbatasan satu container pada satu mesin#

Alat seperti Docker menjalankan container dengan satu perintah, misalnya docker run, dan container yang dihasilkan berjalan pada satu mesin saja. Container mengemas aplikasi beserta seluruh dependensinya, sehingga aplikasi yang berjalan di mesin pengembang berperilaku sama ketika dipindahkan ke mesin lain. Untuk satu atau dua container, pengelolaan manual masih wajar dilakukan. Perintah dijalankan, log diperiksa, dan container yang berhenti cukup dinyalakan ulang secara manual.

Kondisi manual tersebut menyimpan beberapa kelemahan. Apabila proses di dalam container mengalami error dan berhenti, tidak ada mekanisme otomatis yang menyalakannya kembali. Pembaruan versi dilakukan dengan menghentikan container lama, mengunduh image baru, lalu menjalankannya kembali, dan selama proses itu aplikasi tidak dapat diakses. Ketersediaan CPU dan memori juga terbatas pada satu mesin, sehingga beban kerja yang membutuhkan lebih banyak sumber daya tidak dapat ditampung. Kelemahan-kelemahan ini menjadi berat justru karena sifat container yang sengaja dibuat berumur pendek, yaitu mudah dibuat, dihentikan, dan diganti dengan versi baru.

Masalah pada skala besar#

Kesulitan baru muncul ketika jumlah container bertambah dari satu atau dua menjadi puluhan, ratusan, hingga ribuan, dan ketika container tersebut tersebar di banyak mesin. Kluster, yaitu sekumpulan mesin yang bekerja sebagai satu kesatuan, menjadi cara umum menampung skala tersebut, dan setiap mesin anggota kluster disebut Node. Pada titik ini, pengelolaan manual tidak lagi realistis karena keputusan harus diambil jauh lebih sering daripada yang mampu diikuti oleh manusia. Beberapa pertanyaan yang wajib dijawab setiap hari pada skala tersebut antara lain:

  • di mesin mana container baru harus ditempatkan agar beban seimbang
  • siapa yang menyalakan ulang container yang berhenti pada malam hari ketika tidak ada operator yang berjaga
  • bagaimana sebuah aplikasi menemukan aplikasi lain apabila alamat IP container berubah setiap kali dibuat ulang
  • bagaimana memperbarui versi aplikasi pada ratusan container tanpa menghentikan layanan
  • bagaimana mendeteksi mesin yang mati dan memindahkan beban kerjanya ke mesin lain

Setiap pertanyaan di atas memiliki jawaban teknis, tetapi menjalankan semuanya secara manual untuk ribuan container berarti menyerahkan perubahan berkecepatan tinggi kepada manusia. Error pasti terjadi, baik akibat salah penempatan maupun salah ketik, dan dampaknya sulit dilacak. Kebutuhan inilah yang melahirkan platform orkestrasi, yaitu sistem yang mengambil alih keputusan operasional harian tersebut secara otomatis dan konsisten.

Peran platform orkestrasi#

Platform orkestrasi mengelola siklus hidup container pada banyak mesin secara terpusat. Kubernetes adalah platform orkestrasi open source yang menjadi pilihan umum untuk tujuan tersebut, dengan komponen inti yang mengatur penempatan, pemulihan, jaringan, dan pembaruan container. Pengguna tidak lagi memberi tahu sistem langkah demi langkah, melainkan menyatakan hasil akhir yang diinginkan, sedangkan sistem mencari cara mewujudkannya dan menjaganya. Perbandingan berikut merangkum pergeseran tugas tersebut.

AspekContainer tunggal pada satu mesinContainer di bawah orkestrasi
Penempatanditentukan manual oleh operatordipilihkan Node yang sesuai oleh penjadwal
Pemulihancontainer yang berhenti dinyalakan ulang manualcontainer yang hilang dibuat ulang otomatis
Jaringanalamat dan port diatur manual per containersetiap Pod memperoleh alamat dan nama yang stabil
Pembaruan versihentikan, ganti image, jalankan ulang satu per satudiperbarui bertahap dan dapat dikembalikan
Skalaterbatas pada kapasitas satu mesintersebar ke banyak Node dalam kluster

Dari tabel di atas, pergeseran paling mendasar terletak pada siapa yang bertanggung jawab atas operasional harian. Tugas yang sebelumnya berada di tangan operator berpindah ke sistem yang bekerja berdasarkan aturan yang sama setiap saat. Perpindahan ini membuat tim kecil dapat mengoperasikan banyak layanan dengan konsistensi yang sulit dicapai secara manual.

Model deklaratif dan manifest#

Kubernetes bekerja secara deklaratif, yakni keadaan yang diinginkan dinyatakan terlebih dahulu, kemudian sistem bertugas mencapai dan menjaga keadaan itu. Pernyataan keadaan ditulis dalam berkas manifest berformat YAML. Berkas ini memuat jenis objek yang dibuat, namanya, dan rincian perilakunya, misalnya image yang digunakan dan perintah yang dijalankan. Bentuk paling sederhana adalah manifest untuk satu Pod, yaitu satu atau beberapa container yang dijadwalkan sebagai satu kesatuan. Kunci-kunci pada contoh berikut menjadi dasar bagi semua objek Kubernetes, sehingga bentuknya muncul kembali pada berbagai jenis objek lain.

yaml pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: penghitung-kata
  labels:
    app: penghitung-kata
spec:
  containers:
    - name: penghitung-kata
      image: python:3.12
      command: ["python", "-m", "http.server", "8000"]

Kelengkapan manifest dapat diperiksa sebelum dikirim ke kluster. Skrip berikut membaca pod.yaml menggunakan PyYAML, yaitu pustaka Python untuk mengurai YAML, kemudian memeriksa kunci wajib dan menampilkan ringkasan isinya. Pemeriksaan sederhana semacam ini menangkap kesalahan penulisan jauh sebelum manifest menyentuh kluster.

python validasi-manifest.py
# Validasi sederhana manifest pod.yaml menggunakan PyYAML:
# memuat berkas, memeriksa kunci wajib, lalu menampilkan ringkasannya.

import yaml

with open("pod.yaml", encoding="utf-8") as berkas:
    manifest = yaml.safe_load(berkas)

kunci_wajib = ["apiVersion", "kind", "metadata", "spec"]
for kunci in kunci_wajib:
    if kunci not in manifest:
        raise SystemExit(f"kunci wajib tidak ada: {kunci}")

if not manifest["metadata"].get("name"):
    raise SystemExit("metadata.name wajib diisi")

containers = manifest["spec"].get("containers", [])
if not containers:
    raise SystemExit("spec.containers tidak boleh kosong")

print(f"kind      : {manifest['kind']}")
print(f"nama      : {manifest['metadata']['name']}")
print(f"container : {len(containers)}")
for c in containers:
    print(f"  - {c['name']} (image: {c['image']})")
print("manifest valid")
text Keluaran
kind      : Pod
nama      : penghitung-kata
container : 1
  - penghitung-kata (image: python:3.12)
manifest valid

Keluaran menunjukkan manifest terbaca sebagai objek Python dan seluruh kunci wajib ditemukan. Apabila satu kunci wajib dihilangkan, skrip berhenti dengan pesan yang menyebutkan kunci yang hilang. Prinsip yang sama diterapkan oleh kubectl, yang memvalidasi manifest sebelum mengirimkannya ke API server.

Siklus rekonsiliasi#

Menyatakan keadaan hanya berguna apabila ada mekanisme yang menjaganya, karena keadaan aktual di kluster terus berubah. Pod bisa berhenti karena error, mesin bisa mati, dan container bisa dihentikan paksa. Untuk menjawab perubahan itu, Kubernetes menjalankan siklus rekonsiliasi (reconciliation), yaitu perulangan yang membandingkan keadaan yang diinginkan dengan keadaan aktual, lalu melakukan tindakan apabila keduanya berbeda. Siklus ini dijalankan terus-menerus, bukan sekali jalan.

Simulasi berikut meniru pola tersebut dalam bentuk paling sederhana. Keadaan yang diinginkan berupa tiga replika, yaitu tiga salinan Pod yang sama, dan satu Pod hilang pada pertengahan pengamatan. Berkas rekonsiliasi.py di samping artikel ini dapat disalin dan diubah untuk mencoba kejadian lain.

python rekonsiliasi.py
# Simulasi siklus rekonsiliasi: keadaan yang diinginkan dibandingkan dengan
# keadaan aktual pada setiap pengamatan, dan setiap selisih diperbaiki.

diinginkan = 3  # jumlah replika yang dinyatakan pada manifest

aktual = {"app-1": "Berjalan", "app-2": "Berjalan", "app-3": "Berjalan"}

# kejadian sebelum setiap siklus pengamatan, None berarti tidak ada kejadian
kejadian = [None, "app-2 berhenti karena error", None, None]
nomor_berikutnya = 4

for siklus in range(1, 5):
    if kejadian[siklus - 1] is not None:
        nama = kejadian[siklus - 1].split()[0]
        del aktual[nama]
        print(f"kejadian : {kejadian[siklus - 1]}")
    print(f"siklus {siklus}: diinginkan {diinginkan}, aktual {len(aktual)} pod")
    if len(aktual) < diinginkan:
        nama_baru = f"app-{nomor_berikutnya}"
        nomor_berikutnya += 1
        aktual[nama_baru] = "Berjalan"
        print(f"  tindakan: membuat {nama_baru} agar jumlah pod kembali menjadi {diinginkan}")
    else:
        print("  tindakan: tidak ada, keadaan sudah sesuai")
text Keluaran
siklus 1: diinginkan 3, aktual 3 pod
  tindakan: tidak ada, keadaan sudah sesuai
kejadian : app-2 berhenti karena error
siklus 2: diinginkan 3, aktual 2 pod
  tindakan: membuat app-4 agar jumlah pod kembali menjadi 3
siklus 3: diinginkan 3, aktual 3 pod
  tindakan: tidak ada, keadaan sudah sesuai
siklus 4: diinginkan 3, aktual 3 pod
  tindakan: tidak ada, keadaan sudah sesuai

Pada keluaran di atas, kejadian di siklus kedua menghilangkan satu Pod sehingga jumlah aktual berkurang menjadi dua. Pengamatan berikutnya mendeteksi selisih tersebut, lalu tindakan koreksi berupa pembuatan Pod pengganti dijalankan. Setelah jumlahnya kembali tiga, pengamatan selanjutnya tidak menemukan selisih dan tidak ada tindakan. Pola sederhana inilah yang dijalankan oleh controller nyata pada Kubernetes, misalnya ReplicaSet yang menjaga jumlah Pod tetap sesuai keadaan yang dinyatakan.

Konteks: Google, Borg, dan CNCF#

Kubernetes tidak dimulai dari nol. Proyek ini dikembangkan oleh Google dengan mengandalkan pengalaman bertahun-tahun menjalankan sistem manajemen kluster internal bernama Borg untuk beban kerja berskala sangat besar. Pengetahuan tentang penjadwalan, pemulihan, dan deklarasi keadaan pada Borg menjadi dasar desain Kubernetes, kemudian proyek ini dibuka sebagai perangkat lunak open source pada tahun 2014. Pengembangan dan pemeliharaannya kini berada di bawah tata kelola Cloud Native Computing Foundation (CNCF), yayasan netral yang menampung banyak proyek ekosistem cloud native, sehingga arah pengembangannya tidak bergantung pada satu perusahaan saja.

Bagi pembelajar, konteks ini menjelaskan dua hal yang muncul berulang di dokumentasi Kubernetes. Pertama, banyak konsep Kubernetes berbicara pada tingkat keadaan dan tujuan, bukan pada tingkat perintah, karena desainnya mewarisi pengalaman mengoperasikan kluster berskala sangat besar. Kedua, tata kelola yang netral menjadikan Kubernetes dapat dijalankan di banyak lingkungan, mulai dari laptop untuk lab pribadi sampai layanan cloud dari berbagai penyedia. Di sekeliling inti Kubernetes juga tumbuh ekosistem alat untuk pengemasan, pemantauan, dan jaringan yang semuanya berbicara melalui API yang sama.

Ringkasan#

  • Container mengemas aplikasi beserta dependensinya, tetapi pengelolaan manual hanya masuk akal untuk jumlah kecil pada satu mesin.
  • Pada skala besar, penempatan, pemulihan, jaringan, dan pembaruan container perlu diotomatiskan, dan tugas itu diambil alih platform orkestrasi seperti Kubernetes.
  • Kubernetes bekerja secara deklaratif, yaitu keadaan yang diinginkan dinyatakan dalam manifest YAML, kemudian dijaga oleh siklus rekonsiliasi yang terus membandingkannya dengan keadaan aktual.
  • Kubernetes diturunkan dari pengalaman Google menjalankan Borg, dibuka sebagai proyek open source pada 2014, dan kini berada di bawah tata kelola CNCF.

Referensi#