Di Red Hat kami ingin mengatakan, "Container adalah Linux—Linux adalah Container." Inilah artinya. Wadah tradisional adalah proses pada sistem yang biasanya memiliki tiga karakteristik berikut:
1. Kendala sumber daya
Wadah Linux
- Apa itu container Linux?
- Pengantar terminologi wadah
- Unduh:Containers Primer
- Operator Kubernetes:Mengotomatiskan platform orkestrasi container
- eBook:Pola Kubernetes untuk mendesain aplikasi cloud-native
- Apa itu Kubernetes?
Ketika Anda menjalankan banyak kontainer pada suatu sistem, Anda tidak ingin ada kontainer yang memonopoli sistem operasi, jadi kami menggunakan batasan sumber daya untuk mengontrol hal-hal seperti CPU, memori, bandwidth jaringan, dll. Kernel Linux menyediakan fitur cgroups, yang dapat dikonfigurasi untuk mengontrol sumber daya proses kontainer.
2. Kendala keamanan
Biasanya, Anda tidak ingin wadah Anda dapat saling menyerang atau menyerang sistem host. Kami memanfaatkan beberapa fitur kernel Linux untuk mengatur pemisahan keamanan, seperti SELinux, seccomp, kemampuan, dll.
3. Pemisahan virtual
Proses kontainer tidak boleh memiliki pandangan proses apa pun di luar kontainer. Mereka harus berada di jaringan mereka sendiri. Proses kontainer harus dapat mengikat ke port 80 dalam kontainer yang berbeda. Setiap wadah membutuhkan tampilan gambar yang berbeda, membutuhkan sistem file root sendiri (rootfs). Di Linux kami menggunakan ruang nama kernel untuk menyediakan pemisahan virtual.
Oleh karena itu, proses yang berjalan di cgroup, memiliki pengaturan keamanan, dan berjalan di ruang nama dapat disebut wadah. Melihat PID 1, systemd, pada sistem Red Hat Enterprise Linux 7, Anda melihat bahwa systemd berjalan dalam cgroup.
# tail -1 /proc/1/cgroup
1:name=systemd:/
ps
perintah menunjukkan kepada Anda bahwa proses sistem memiliki label SELinux ...
# ps -eZ | grep systemd
system_u:system_r:init_t:s0 1 ? 00:00:48 systemd
dan kemampuan.
# grep Cap /proc/1/status
...
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
CapBnd: 0000003fffffffff
Terakhir, jika Anda melihat /proc/1/ns
subdir, Anda akan melihat namespace tempat systemd berjalan.
ls -l /proc/1/ns
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 net -> net:[4026532009]
lrwxrwxrwx. 1 root root 0 Jan 11 11:46 pid -> pid:[4026531836]
...
Jika PID 1 (dan benar-benar setiap proses lain pada sistem) memiliki batasan sumber daya, pengaturan keamanan, dan ruang nama, saya berpendapat bahwa setiap proses pada sistem ada dalam wadah.
Alat runtime container hanya memodifikasi batasan sumber daya, pengaturan keamanan, dan ruang nama ini. Kemudian kernel Linux menjalankan proses. Setelah container diluncurkan, container runtime dapat memantau PID 1 di dalam container atau stdin
container /stdout
—runtime container mengelola siklus proses ini.
Waktu proses penampung
Anda mungkin berkata pada diri sendiri, systemd terdengar sangat mirip dengan runtime kontainer. Nah, setelah beberapa diskusi email tentang mengapa runtime container tidak menggunakan systemd-nspawn
sebagai alat untuk meluncurkan container, saya memutuskan untuk mendiskusikan runtime container dan memberikan beberapa konteks historis.
Docker sering disebut runtime container, tetapi "runtime container" adalah istilah yang kelebihan beban. Ketika orang berbicara tentang "runtime container", mereka sebenarnya berbicara tentang alat tingkat tinggi seperti Docker, CRI-O, dan RKT yang datang dengan fungsionalitas pengembang. Mereka didorong oleh API. Mereka mencakup konsep seperti menarik gambar kontainer dari registri kontainer, menyiapkan penyimpanan, dan akhirnya meluncurkan kontainer. Meluncurkan container sering kali melibatkan menjalankan alat khusus yang mengonfigurasi kernel untuk menjalankan container, dan ini juga disebut sebagai "runtime container." Saya akan menyebutnya sebagai "runtime container tingkat rendah". Daemon seperti Docker dan CRI-O, serta alat baris perintah seperti Podman dan Buildah, mungkin sebaiknya disebut "manajer penampung".
Ketika Docker awalnya ditulis, ia meluncurkan kontainer menggunakan lxc
toolset, yang mendahului systemd-nspawn
. Pekerjaan asli Red Hat dengan Docker adalah mencoba mengintegrasikan libvirt
(libvirt-lxc
) ke Docker sebagai alternatif dari lxc
alat, yang tidak didukung di RHEL. libvirt-lxc
juga tidak menggunakan systemd-nspawn
. Saat itu, tim systemd mengatakan bahwa systemd-nspawn
hanya alat untuk pengujian, bukan untuk produksi.
Pada saat yang sama, pengembang Docker upstream, termasuk beberapa anggota tim Red Hat saya, memutuskan bahwa mereka menginginkan cara asli-golang untuk meluncurkan container, daripada meluncurkan aplikasi terpisah. Pekerjaan dimulai pada libcontainer, sebagai library golang asli untuk meluncurkan container. Rekayasa Red Hat memutuskan bahwa ini adalah jalan terbaik ke depan dan menjatuhkan libvirt-lxc
.
Kemudian, Open Container Initiative (OCI) dibentuk, karena orang ingin dapat meluncurkan kontainer dengan cara tambahan. Wadah tradisional yang dipisahkan namespace sangat populer, tetapi orang-orang juga memiliki keinginan untuk isolasi tingkat mesin virtual. Intel dan Hyper.sh sedang mengerjakan container yang dipisahkan KVM, dan Microsoft sedang mengerjakan container berbasis Windows. OCI menginginkan spesifikasi standar yang mendefinisikan apa itu container, sehingga lahirlah Spesifikasi Waktu Proses OCI.
Spesifikasi Waktu Proses OCI mendefinisikan format file JSON yang menjelaskan biner apa yang harus dijalankan, cara penyimpanannya, dan lokasi rootf wadah. Alat dapat menghasilkan file JSON ini. Kemudian alat lain dapat membaca file JSON ini dan menjalankan wadah di rootfs. Bagian libcontainer dari Docker dipecah dan disumbangkan ke OCI. Insinyur Docker upstream dan teknisi kami membantu membuat alat frontend baru untuk membaca file JSON Spesifikasi Runtime OCI dan berinteraksi dengan libcontainer untuk menjalankan container. Alat ini, disebut runc
, juga disumbangkan ke OCI. Saat runc
dapat membaca file OCI JSON, pengguna dibiarkan membuatnya sendiri. runc
sejak itu menjadi runtime container tingkat rendah yang paling populer. Hampir semua alat pengelolaan kontainer mendukung runc
, termasuk CRI-O, Docker, Buildah, Podman, dan Cloud Foundry Garden. Sejak itu, alat lain juga telah mengimplementasikan OCI Runtime Spec untuk menjalankan container yang sesuai dengan OCI.
Baik Clear Containers maupun runV
Hyper.sh alat dibuat untuk menggunakan Spesifikasi Waktu Proses OCI untuk menjalankan wadah berbasis KVM, dan mereka menggabungkan upaya mereka dalam proyek baru yang disebut Kata. Tahun lalu, Oracle membuat versi demonstrasi alat runtime OCI yang disebut RailCar, yang ditulis dalam Rust. Sudah dua bulan sejak proyek GitHub diperbarui, jadi tidak jelas apakah masih dalam pengembangan. Beberapa tahun yang lalu, Vincent Batts bekerja untuk menambahkan alat, nspawn-oci
, yang menafsirkan file Spesifikasi Waktu Proses OCI dan meluncurkan systemd-nspawn
, tetapi tidak ada yang benar-benar memahaminya, dan itu bukan implementasi asli.
Jika seseorang ingin mengimplementasikan systemd-nspawn --oci OCI-SPEC.json
asli dan membuatnya diterima oleh tim systemd untuk mendapatkan dukungan, kemudian CRI-O, Docker, dan akhirnya Podman akan dapat menggunakannya selain runc
dan Clear Container/runV (Kata). (Tidak ada seorang pun di tim saya yang mengerjakan ini.)
Intinya adalah, tiga atau empat tahun yang lalu, pengembang hulu ingin menulis alat golang tingkat rendah untuk meluncurkan wadah, dan alat ini akhirnya menjadi runc
. Pengembang tersebut pada saat itu memiliki alat berbasis C untuk melakukan ini yang disebut lxc
dan menjauh darinya. Saya cukup yakin bahwa pada saat mereka membuat keputusan untuk membangun libcontainer, mereka tidak akan tertarik dengan systemd-nspawn
atau cara non-asli (golang) lainnya untuk menjalankan wadah terpisah "namespace".