Topik ini membandingkan container, yaitu paket aplikasi terisolasi yang dikelola Docker, dengan mesin virtual (virtual machine, disingkat VM). Perbandingan difokuskan pada sisi yang paling menentukan, yaitu siapa yang memiliki kernel pada host, yakni mesin induk tempat semuanya berjalan. Pembahasan dimulai dari cara kerja mesin virtual, berlanjut ke cara container berbagi kernel host, lalu mengenal dua fitur kernel Linux yang menopang isolasi container, yaitu namespace dan cgroup. Bagian akhir merangkum perbedaan keduanya dalam satu tabel perbandingan beserta konsekuensi praktisnya.
Mesin virtual membawa kernel sendiri#
Mesin virtual adalah tiruan lengkap sebuah komputer yang dijalankan di atas perangkat keras nyata. Lapisan penyedianya disebut hypervisor, yaitu perangkat lunak yang membagi CPU, memori, dan penyimpanan host menjadi beberapa lingkungan yang terisolasi. Di atas hypervisor itulah setiap mesin virtual memasang sistem operasi (OS) tamu sendiri, lengkap dengan kernel masing-masing, sehingga satu mesin fisik dapat menaungi banyak sistem operasi yang tidak saling mengenal.
Kelengkapan tersebut menjadi sumber kekuatan sekaligus bebannya. Karena setiap mesin virtual membawa OS penuh, ukurannya dihitung dalam gigabyte dan proses memulainya memakan waktu belasan detik hingga menit. Sebagai imbalannya, isolasinya kuat, karena kernel tamu yang terpisah membuat gangguan pada satu mesin virtual tidak menyentuh mesin virtual lainnya. Sistem operasi yang berbeda pun dapat berjalan berdampingan pada host yang sama, misalnya Linux dan Windows.
Container berbagi kernel host#
Container mengambil jalan yang jauh lebih hemat. Container tidak membawa OS tamu, dan seluruh container pada satu host berbagi kernel milik host melalui container engine, yaitu perangkat lunak pengelola siklus hidup container. Pada Docker, peran tersebut diisi daemon bernama dockerd, yakni proses layanan yang berjalan terus-menerus.
Aplikasi beserta dependensinya tersimpan dalam image, yaitu cetakan siap jalankan yang menjadi dasar container. Isi image tersebut berada di ruang pengguna (user space), yakni lapisan sistem operasi tempat aplikasi berjalan. Kernel tidak termasuk isi image dan tetap satu milik bersama. Bagi aplikasi di dalamnya, container tampak seperti sistem yang berdiri sendiri, padahal prosesnya tetap proses biasa pada host, dengan pandangan dan sumber daya yang dipisahkan oleh kernel.
Fakta berbagi kernel ini dapat diverifikasi dengan perintah sederhana. Perintah uname dengan opsi -r menampilkan nomor versi kernel yang sedang dipakai oleh sistem tempat perintah itu dijalankan.
# menampilkan versi kernel yang sedang dipakai
uname -r5.10.134-013.15.kangaroo.al8.x86_64Angka pada keluaran di atas adalah versi kernel dari mesin tempat perintah dijalankan. Bila perintah yang sama dijalankan di dalam container pada mesin itu, keluarannya identik karena container berbagi kernel host yang sama. Sebaliknya, mesin virtual pada host yang sama akan menampilkan nomor versi milik kernel tamunya, yang bisa saja berbeda dari kernel host. Perbedaan kecil ini adalah penanda paling langsung dari dua model pembagian perangkat keras.
Diagram berikut membandingkan tumpukan lapisan kedua pendekatan tersebut dari atas ke bawah.
Pada sisi mesin virtual, setiap kotak aplikasi membawa OS tamu sendiri sebelum menyentuh hypervisor, sedangkan pada sisi container, kotak-kotak aplikasi langsung bertumpu pada container engine dan berbagi satu kernel milik OS host. Selisih satu lapisan sistem operasi penuh inilah yang membuat container jauh lebih ramping. Diagram juga memperlihatkan bahwa container tidak menghapus isolasi sepenuhnya, melainkan memindahkan tanggung jawabnya dari hypervisor ke mekanisme kernel yang dibahas pada bagian berikutnya.
Namespace dan cgroup#
Dua fitur kernel Linux membuat model berbagi kernel tersebut mungkin. Fitur pertama adalah namespace, yaitu mekanisme yang membatasi pandangan sebuah proses terhadap sistem, sehingga proses tersebut hanya melihat pohon proses, antarmuka jaringan, dan sistem berkas miliknya sendiri. Jenis namespace yang paling sering disebut adalah pid untuk pohon proses, net untuk jaringan, dan mnt untuk pengaitan sistem berkas (mount).
Fitur kedua adalah cgroup, singkatan dari control group, yaitu mekanisme yang membatasi dan mengukur pemakaian sumber daya oleh sekumpulan proses, seperti jatah CPU, batas memori, dan laju masukan/keluaran (I/O). Container engine menggabungkan keduanya untuk setiap container yang dibuat. Namespace memberi container pandangan sistemnya sendiri, sedangkan cgroup memastikan satu container tidak melahap seluruh sumber daya host. Kombinasi keduanya membuat sebuah proses biasa terasa seolah berjalan pada sistem terpisah tanpa perlu kernel kedua.
Perbandingan dan konsekuensi praktis#
| Aspek | Mesin virtual | Container |
|---|---|---|
| Ukuran bawaan | Umumnya beberapa GB karena membawa OS tamu penuh | Umumnya puluhan MB karena hanya memuat aplikasi dan dependensinya |
| Waktu mulai | Belasan detik hingga menit karena mengikuti proses memulai OS tamu | Hitungan detik karena hanya menjalankan satu proses |
| Isolasi | Kuat, karena kernel tamu terpisah dari host | Lebih tipis, karena bergantung pada namespace dan cgroup di atas kernel yang sama |
| Kecocokan | Sistem operasi yang berbeda dan beban yang menuntut pemisahan ketat | Layanan aplikasi yang perlu dibungkus, digandakan, dan digantikan dengan cepat |
Tabel di atas bermuara pada satu konsekuensi praktis. Container menawarkan kecepatan dan kepadatan, yaitu banyak container dapat berjalan pada satu host dengan sisa sumber daya yang masih besar dan setiap container baru siap dalam hitungan detik. Kedua sifat itu membuat container cocok untuk pengembangan, pengujian, dan penskalaan layanan. Mesin virtual menawarkan batas yang lebih tegas, sehingga tetap dipilih apabila yang dibutuhkan adalah sistem operasi yang berbeda atau pemisahan yang ketat antara beban-beban yang berbeda. Keduanya bukan pesaing yang saling menggantikan, karena banyak infrastruktur justru memakai mesin virtual sebagai host tempat container-container dijalankan.
Sisi yang perlu digarisbawahi adalah batas isolasi container. Karena kernel dibagi, kerentanan pada kernel host berpotensi memengaruhi seluruh container yang berjalan di atasnya, dan container juga tidak dapat menjalankan sistem yang menuntut kernel berbeda. Untuk beban yang menuntut jaminan pemisahan mutlak, misalnya menjalankan perangkat lunak dari pihak lain, pemisahan pada tingkat mesin virtual tetap menjadi pilihan yang lebih aman. Untuk kebutuhan sehari-hari dalam mengemas aplikasi, isolasi container sudah memadai dengan biaya yang jauh lebih murah.
Ringkasan#
- Mesin virtual membawa OS tamu lengkap dengan kernel sendiri di atas hypervisor, sedangkan container berbagi kernel host melalui container engine.
- Namespace memisahkan pandangan sebuah proses, misalnya pohon proses, jaringan, dan sistem berkas, sedangkan cgroup membatasi pemakaian CPU, memori, dan I/O.
- Container umumnya berukuran puluhan MB dan siap dalam hitungan detik, sedangkan mesin virtual berukuran beberapa GB dan memulai dalam hitungan belasan detik atau lebih.
- Batas isolasi container adalah kernel host, sehingga pemisahan mutlak antara beban yang berbeda tetap menjadi ranah mesin virtual.
Referensi#
- What is a container? — Docker Docs — Perbandingan resmi antara container dan mesin virtual beserta alasan perbedaan ukuran dan waktunya.
- Docker overview — Docker Docs — Penjelasan arsitektur Docker yang menempatkan container engine dan kernel host dalam tumpukan yang sama.