Ketika kita menjalankan sebuah container, di dalamnya tampak sebuah komputer kecil yang utuh: ada proses bernomor PID 1, ada hostname sendiri, ada antarmuka jaringan sendiri. Padahal di sisi host, container itu hanyalah satu proses biasa — tanpa mesin virtual, tanpa kernel kedua. Ilusi ajaib ini dibangun oleh satu fitur kernel bernama namespace: kemampuan memberi setiap proses kacamata tersendiri dalam melihat sistem. Kombinasi namespaces dengan cgroups dari chapter sebelumnya adalah seluruh rahasia teknis container. Pada chapter ini kita bedah jenis-jenisnya, mengamatinya lewat /proc, dan mencobanya langsung tanpa root lewat unshare.
Masalah: Satu Tampilan Sistem untuk Semua Proses #
Pada sistem Linux biasa, seluruh proses melihat dunia yang sama: mereka sepakat bahwa proses systemd adalah PID 1, bahwa hostname mesin ini adalah server-kantor, dan bahwa user ber-UID 1000 adalah budi. Kesepakatan bersama itu menjadi masalah begitu satu mesin dipakai banyak pihak — server hosting tidak boleh membiarkan proses pelanggan A melihat proses pelanggan B, apalagi mengubah hostname bersama. Virtual machine menyelesaikannya dengan cara mahal: menduplikasi seluruh mesin. Namespace menyelesaikannya dengan cara murah: membuat salinan tampilan untuk sekelompok proses tertentu, sementara kernel yang berjalan tetap satu.
Konsep dan Delapan Jenis Namespace #
Satu namespace membungkus satu kategori resource sistem dan menentukan siapa yang melihat versi mana. Proses menandai keanggotaan namespace-nya pada saat lahir — dari flag clone() atau lewat perintah unshare — dan sejak saat itu setiap akses terhadap kategori tersebut diterjemahkan ke tampilan milik kelompoknya. Linux dewasa ini mengenal delapan jenis:
| Namespace | Yang diisolasi | Flag |
|---|---|---|
pid | penomoran PID; proses pertama terlihat sebagai PID 1 | CLONE_NEWPID |
net | interface, tabel routing, aturan firewall, port | CLONE_NEWNET |
mnt | daftar mount point yang terlihat | CLONE_NEWNS |
uts | hostname dan domain name | CLONE_NEWUTS |
user | pemetaan UID/GID — root di dalam bisa jadi user biasa di luar | CLONE_NEWUSER |
ipc | objek System V IPC dan POSIX message queue | CLONE_NEWIPC |
cgroup | tampilan direktori /sys/fs/cgroup | CLONE_NEWCGROUP |
time | jam monotonic dan boottime per namespace | CLONE_NEWTIME |
Rincian tiap jenis beserta syscall pembuatnya terdokumentasi di halaman manual namespaces(7)
. Daftar ini tumbuh seiring usia kernel — user hadir di 3.8 dan time baru menyusul di 5.6 — dan inilah alasan versi kernel menentukan fitur container yang tersedia.
Mengamati Namespace Sebuah Proses #
Keanggotaan namespace setiap proses bisa dilihat langsung di procfs, tepatnya di direktori /proc/<pid>/ns/ — satu symlink per jenis namespace. Menggunakan trik /proc/self dari chapter procfs dan sysfs
, kita bisa mengintip milik proses pembacanya sendiri:
ls /proc/self/ns/Output yang Dihasilkan:
cgroup
ipc
mnt
net
pid
pid_for_children
time
time_for_children
user
utsSepuluh nama pada output di atas adalah jenis-jenis namespace yang kita bahas plus dua varian *_for_children — penanda namespace yang akan diwarisi proses anak yang diciptakan nanti. Setiap symlink menunjuk ke nama berformat uts:[4026532242]: angka dalam kurung adalah identitas objek namespace di kernel. Dua proses berada di namespace yang sama persis bila symlink mereka menunjuk angka yang sama — itulah cara alat monitoring mengecek siapa-menggunakan-namespace-siapa. Angka identitas berbeda di setiap boot, jadi bandingkan dua nilai dengan test, jangan hafalkan angkanya.
User Namespace: unshare Tanpa Root #
Perintah unshare(1)
menjalankan program di namespace baru; nsenter adalah kebalikannya — masuk ke namespace proses yang sudah ada. Umumnya membuat namespace butuh privilege root, kecuali satu: user namespace. Di dalamnya, kernel memetakan ulang UID: proses kita yang biasa dianggap UID 0 (root) di dalam namespace, tanpa kehilangan status user biasa di luar. Flag -U meminta user namespace dan -r memetakan diri kita sebagai root:
unshare -Ur bash -c 'id -un'Output yang Dihasilkan:
rootMari kita bedah perintah tadi:
unshare -Ur:unsharemembuat user namespace baru, flag-Umemintanya dan-rmemetakan UID/GID kita ke 0 di dalam.bash -c '...': shell baru lahir sepenuhnya di dalam namespace tersebut.id -un: mencetak nama user efektif — hasilnyaroot, meski di luar namespace kita tetap user biasa tanpa hak administratif apa pun.
Inilah “kacamata ajaib” container: proses merasa menjadi root, tetapi privilege-nya cuma berlaku di dalam kaca. Fitur ini jugalah yang membuat demo-demo di bawah bisa kita jalankan tanpa root di lingkungan latihan.
PID Namespace: Dunia dengan PID 1 Sendiri #
Namespace PID memberi kelompok proses sistem penomoran sendiri yang dimulai dari 1. Flag -f membuat unshare mem-fork dulu, dan -p meminta PID namespace; kombinasi -Urfp berarti: buat user namespace agar tak butuh root, fork, lalu pid namespace:
unshare -Urfp bash -c 'echo "bash ini berjalan sebagai PID $$"'Output yang Dihasilkan:
bash ini berjalan sebagai PID 1Variabel $$ dievaluasi bash di dalam namespace, dan hasilnya 1 — bash tersebut adalah proses pertama dunianya sendiri. Dengan --mount-proc, /proc bisa dipasang ulang di dalamnya sehingga ps hanya menampilkan penghuni namespace itu; memang begitulah container menjalankan nginx sebagai PID 1, padahal di host ia mungkin PID 30217. Penomoran ganda ini murni urusan tampilan — kernel tetap memakai PID asli untuk penjadwalan.
Mount Namespace: Isolasi Daftar Mount #
Namespace mount memberi proses daftar mount point sendiri — begitulah container mendapatkan filesystem yang tampak steril. Kita bisa membuktikan isolasinya dengan memasang tmpfs di dalam namespace lalu memeriksa isi direktorinya dari luar:
unshare -Urm bash -c 'mkdir -p latihan-mnt && mount -t tmpfs tmpfs latihan-mnt && touch latihan-mnt/tersembunyi && ls latihan-mnt'
ls latihan-mnt | wc -lOutput yang Dihasilkan:
tersembunyi
0Bedah blok di atas baris-per-baris:
unshare -Urm: user namespace (-U,-r) membuka izin, flag-mmeminta mount namespace untuk shell di dalamnya.mkdir ... && mount -t tmpfs ...: di dalam namespace,mountdiminta menempel tmpfs dilatihan-mnt— operasi yang biasanya hanya boleh root, sah karena kita root di user namespace tadi.touch latihan-mnt/tersembunyi && ls latihan-mnt: file dibuat di tmpfs itu dan tampak oleh proses dalam namespace.ls latihan-mnt | wc -l(baris kedua blok): dijalankan setelahunshareselesai — direktorinya masih ada, tetapi tmpfs-nya ikut lenyap bersama namespace, sehingga hitungannya0.
Dari dalam namespace, file tersembunyi tampak berdiri di latihan-mnt; dari luar, tmpfs beserta isinya seolah tak pernah terpasang. File itu bukan disembunyikan dengan flag khusus — mount point-nya memang tidak terdaftar pada tampilan sistem luar. Persis mekanisme inilah yang dipakai overlayfs container untuk menyusun layer image menjadi root filesystem yang tampak utuh.
Namespace Lainnya dan Peran Docker #
Tiga jenis sisanya melengkapi panggung. Namespace net memberi container interface lo plus pasangan kabel virtual (veth) yang menjembatani ke bridge host — sehingga port 80 milik satu container tidak berbenturan dengan milik yang lain, sebagaimana dibedah pada chapter container networking
. Namespace uts mengisolasi hostname — mengubah hostname di dalamnya tidak pernah menyentuh hostname asli sistem; ipc memisahkan antrian pesan antar-proses; dan cgroup menyembunyikan hierarki cgroup di luar miliknya.
Docker dan Podman tidak memakai unshare dari shell — runtime container memanggil clone() dengan seluruh flag sekaligus saat membuat container, lalu menggabungkannya dengan cgroups untuk pembatasan resource; peta lengkap kombinasi itu ada pada chapter container concepts
. Perintah docker exec pun tak lain daripada nsenter ke namespace container yang sedang berjalan.
Ada satu simpul yang belum terurai: di dalam container kita “root”, tetapi jelas tidak bisa memformat disk host. Antara ilusi root penuh dan user biasa, kernel memecah privilege root menjadi satuan kecil bernama capability — dan itulah topik chapter berikutnya.