Swarm dan Kubernetes sama-sama pandai mengambil keputusan — tapi tidak satu pun dari keduanya menjalankan container dengan tangannya sendiri. Swarm mendelegasikannya ke daemon Engine di tiap node, dan kubelet mendelegasikannya ke sebuah container runtime yang berdiri sendiri. Menariknya, kedua jalur itu bertemu di nama yang sama: containerd — komponen yang sejak Chapter Arsitektur Docker kita lihat selalu berbaris di output docker version di bawah Engine. Chapter ini menenggelamkan kita ke lapisan tersebut: apa sebenarnya pekerjaan sebuah container runtime, dua standar OCI yang menjahit image dan runtime menjadi ekosistem yang utuh, bagaimana jawaban jujur atas mitos “Docker tidak didukung Kubernetes”, dan bagaimana enam runtime berbeda membagi pekerjaan dengan cara isolasi yang berbeda pula.
Apa itu Container Runtime #
Istilah “runtime” kita pakai longgar sepanjang Course, dan saatnya mengernyitkannya menjadi definisi yang tepat. Sebuah container runtime adalah program yang mengerjakan pekerjaan teknis berikut, berurutan: menarik image dari registry, membongkar layer-layer image menjadi rootfs, menyiapkan isolasi berupa namespace dan cgroups, lalu menjalankan siklus hidup container — create, start, stop — persis daftar state yang akan kita temui pada spesifikasi OCI di bawah. Ketika docker run nginx berakhir dengan proses nginx yang hidup, seluruh daftar pekerjaan itu telah dikerjakan oleh rantai komponen di bawah perintah yang singkat itu.
Definisi ini menjelaskan mengapa kata “runtime” muncul di dua tempat yang tampak berbeda. containerd dan runc sama-sama disebut runtime, padahal keduanya jelas tidak sama besar — dan pemecahan rahasianya adalah pembagian dua lapisan pekerjaan.
Runtime High-Level dan Low-Level #
Runtime high-level — containerd dan CRI-O — mengelola gambaran besar: menarik image, menyimpan dan membongkarnya, mengawasi siklus hidup container dari lahir sampai mati, dan menawarkan antarmuka API bagi klien seperti dockerd atau kubelet. Runtime low-level — runc dan crun — mengerjakan satu bagian yang sangat dalam: diberi rootfs yang sudah siap beserta konfigurasi proses, runtime ini membentuk namespace dan cgroups, menghidupkan satu proses container, lalu selesai dan mundur. Satu container, sekali jalan — runtime low-level tidak mengawasi apa pun setelah proses hidup.
Pembagian ini bukan gaya arsitektur belaka, melainkan konsekuensi langsung dari standar yang menaungi keduanya.
Dua Standar OCI #
Open Container Initiative (OCI) menulis dua spesifikasi yang menjadi jahitan seluruh ekosistem: satu untuk image, satu untuk runtime. Keduanya adalah alasan image yang kita bangun dengan docker build dapat dijalankan di mana pun — termasuk di cluster Kubernetes.
image-spec #
Spesifikasi image mendefinisikan format yang sudah kita bedah dari sisi konsep di Chapter Konsep Image Layer: sebuah manifest yang menunjuk kumpulan layer terkompresi plus sebuah config yang memuat perintah dan environment. Semua blob content-addressed dengan digest — mekanisme yang kita pakai untuk memin versi rilis di Chapter Image Digest. Image Docker sejak lama mengikuti bentuk ini, dan para runtime lain membacanya dengan format yang kompatibel.
Di sinilah mitos yang paling sering beredar perlu dijawab tuntas: “Docker tidak didukung Kubernetes, katanya?” Yang benar jauh lebih membosankan dan jauh lebih baik: image yang dibangun docker build adalah image OCI, dan Kubernetes tidak pernah menjalankan image dengan cara lain. Yang dihapus Kubernetes pada versi 1.24 adalah dockershim — lapisan adapter yang dulu membuat kubelet bisa berbicara dengan dockerd sebagai runtime. Setelah penghapusan itu, kubelet berbicara langsung ke containerd atau CRI-O lewat CRI, dan image hasil Docker tetap diminum dengan sempurna — karena yang dihapus adalah jalur percakapan ke daemon, bukan format image yang tidak pernah menjadi milik eksklusif Docker.
runtime-spec #
Spesifikasi runtime mendefinisikan konfigurasi, environment, dan siklus hidup yang harus dihormati runtime low-level. Siklus hidupnya empat state, dan tabel berikut memetakannya:
| State | Yang terjadi | Pemicu |
|---|---|---|
creating | runtime menyiapkan rootfs, namespace, dan cgroups | create |
created | container siap, tetapi proses utama belum berjalan | persiapan selesai |
running | proses utama container hidup dan mulai diawasi | start |
stopped | proses keluar dan sumber daya container dibersihkan | exit atau kill |
Empat state ini bukan teori yang jauh: docker create lalu docker start yang kita jalankan di Section Konfigurasi Container adalah pintu API menuju state created dan running yang sama, dan docker stop yang mengirim SIGTERM lalu SIGKILL setelah masa tenggang adalah jalan menuju stopped. runc sendiri menyediakan perintah yang persis menamai state-state ini — runc create, runc start, runc kill, runc delete.
Rantai di Bawah Engine 29.9.0 #
Kedua standar itu bekerja di dalam mesin kita hari ini, dan docker version memotretnya:
$ docker versionOutput yang Dihasilkan (dipotong):
Server: Docker Engine - Community
Engine:
Version: 29.9.0
API version: 1.52
OS/Arch: linux/amd64
containerd:
Version: 2.1.4
runc:
Version: 1.3.2Output ini adalah foto keluarga yang sama dengan Chapter Arsitektur Docker, dan kini kita bisa membacanya dengan kosakata baru: Engine 29.9.0 adalah dockerd — daemon pintu API sekaligus manajer umum; containerd 2.1.4 adalah runtime high-level yang mengawasi siklus hidup container di bawahnya; runc 1.3.2 adalah runtime low-level pembentuk isolasi.
CRI: Bahasa Bersama kubelet #
Bagaimana kubelet berbicara ke runtime? Lewat CRI — Container Runtime Interface, sebuah kontrak gRPC yang didefinisikan Kubernetes. kubelet sebagai klien memanggil method gRPC untuk menarik image, membuat dan menjalankan sandbox, memeriksa status — dan containerd atau CRI-O sebagai server menjalankannya. Kontrak inilah yang membuat penggantian runtime menjadi perkara konfigurasi, bukan penulisan ulang kubelet; dan inilah pula yang membuat dockershim bisa dihapus dengan damai: dockerd bukan server CRI yang native, sementara containerd menyediakan plugin CRI resmi.
Desain ini punya konsekuensi yang elegan bagi kita: mesin yang menjalankan Kubernetes dan mesin yang menjalankan Docker Engine dapat memakai containerd yang sama. Pada instalasi Engine 29 baru, containerd bahkan menjadi penyimpan image utama (containerd image store dengan snapshotter overlayfs) — semakin sedikit alasan memperlakukan Docker dan Kubernetes sebagai dua dunia berbeda.
Peta Enam Runtime #
Enam nama berikut menutup peta runtime yang perlu kita kenal:
| Runtime | Lapisan | Keunikan dan model isolasinya |
|---|---|---|
| containerd | high-level | runtime bawaan Docker dan pilihan utama Kubernetes; mengelola image dan seluruh siklus hidup container |
| CRI-O | high-level | runtime yang lahir khusus untuk kubelet — hanya mengerjakan yang dibutuhkan pod, tidak lebih |
| runc | low-level | implementasi referensi runtime-spec dalam Go; membentuk namespace dan cgroups lalu mundur |
| crun | low-level | implementasi runtime-spec dalam C — waktu start lebih cepat dan jejak memori lebih kecil untuk cluster padat |
| Kata Containers | low-level | setiap pod hidup di dalam micro-VM ringan — batas isolasinya perangkat keras, bukan sekadar namespace kernel |
| gVisor | low-level | kernel di ruang pengguna mencegat syscall container — lapisan sandbox untuk menjalankan kode yang tidak dipercaya |
Dua baris terakhir menjawab pertanyaan yang muncul begitu kita mulai menjalankan kode pihak lain: namespace dan cgroups berbagi kernel yang sama dengan host, dan sebagian beban kerja — kode pelanggan yang tidak dikenal, pemrosesan berkas yang mencurigakan — menuntut batas yang lebih tebal. Batas yang lebih tebal selalu lebih mahal: micro-VM dan sandbox userspace membayar dengan waktu start dan throughput syscall yang lebih lambat, sehingga pilihan runtime menjadi keputusan per beban kerja, bukan peserta lomba kecepatan umum.
Peta ini menutup satu pertanyaan dan membuka satu lagi. Kita tahu sekarang bahwa containerd dan runc adalah dua runtime berlapis yang bekerja di bawah dockerd — tetapi bagaimana persisnya keduanya bekerja sama saat satu perintah docker run diketik? Chapter containerd dan runc menelusuri rantai itu perhentian demi perhentian, sampai terlihat proses echo paling sederhana lahir dari tangan runc.
Referensi #
- Open Container Initiative — naskah spesifikasi image-spec dan runtime-spec yang mengikat seluruh ekosistem.
- Docker Overview — arsitektur Docker dan posisi containerd serta runc di dalamnya.
- Container Runtime Interface (CRI) — kontrak gRPC antara kubelet dan container runtime.