Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Dimulai pada 10 Agustus di Slurm Kursus video Docker, di mana kami menganalisisnya secara lengkap - mulai dari abstraksi dasar hingga parameter jaringan.

Pada artikel ini kita akan membahas tentang sejarah Docker dan abstraksi utamanya: Image, Cli, Dockerfile. Kuliah ini ditujukan untuk pemula, sehingga tidak mungkin menarik bagi pengguna berpengalaman. Tidak akan ada darah, usus buntu atau perendaman yang dalam. Hal yang paling mendasar.

Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Apa itu Docker

Mari kita lihat definisi Docker dari Wikipedia.

Docker adalah perangkat lunak untuk mengotomatiskan penerapan dan pengelolaan aplikasi di lingkungan dalam container.

Tidak ada yang jelas dari definisi ini. Sangat tidak jelas apa yang dimaksud dengan “dalam lingkungan yang mendukung containerisasi”. Untuk mengetahuinya, mari kita kembali ke masa lalu. Mari kita mulai dengan era yang biasa saya sebut sebagai “Era Monolitik”.

Era monolitik

Era monolitik adalah awal tahun 2000-an, ketika semua aplikasi bersifat monolitik, dengan banyak ketergantungan. Pembangunan memakan waktu lama. Pada saat yang sama, servernya tidak banyak; kami semua mengetahui namanya dan memantaunya. Ada perbandingan yang lucu:

Hewan peliharaan adalah hewan peliharaan. Di era monolitik, kami memperlakukan server kami seperti hewan peliharaan, dirawat dan disayangi, menghilangkan setitik debu. Dan untuk pengelolaan sumber daya yang lebih baik, kami menggunakan virtualisasi: kami mengambil server dan membaginya menjadi beberapa mesin virtual, sehingga memastikan isolasi lingkungan.

Sistem virtualisasi berbasis hypervisor

Semua orang mungkin pernah mendengar tentang sistem virtualisasi: VMware, VirtualBox, Hyper-V, Qemu KVM, dll. Mereka menyediakan isolasi aplikasi dan manajemen sumber daya, tetapi mereka juga memiliki kelemahan. Untuk melakukan virtualisasi, Anda memerlukan hypervisor. Dan hypervisor adalah sumber daya tambahan. Dan mesin virtual itu sendiri biasanya berbentuk raksasa - gambar berat yang berisi sistem operasi, Nginx, Apache, dan mungkin MySQL. Gambarnya besar dan mesin virtual tidak nyaman untuk dioperasikan. Akibatnya, bekerja dengan mesin virtual bisa menjadi lambat. Untuk mengatasi masalah ini, sistem virtualisasi dibuat di tingkat kernel.

Sistem virtualisasi tingkat kernel

Virtualisasi tingkat kernel didukung oleh sistem OpenVZ, Systemd-nspawn, LXC. Contoh mencolok dari virtualisasi tersebut adalah LXC (Linux Containers).

LXC adalah sistem virtualisasi tingkat sistem operasi untuk menjalankan beberapa instance sistem operasi Linux yang terisolasi pada satu node. LXC tidak menggunakan mesin virtual, tetapi menciptakan lingkungan virtual dengan ruang proses dan tumpukan jaringannya sendiri.

Pada dasarnya LXC membuat container. Apa perbedaan antara mesin virtual dan container?

Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Kontainer tidak cocok untuk mengisolasi proses: kerentanan ditemukan dalam sistem virtualisasi di tingkat kernel yang memungkinkan proses tersebut keluar dari kontainer ke host. Oleh karena itu, jika Anda perlu mengisolasi sesuatu, lebih baik menggunakan mesin virtual.

Perbedaan antara virtualisasi dan containerisasi dapat dilihat pada diagram.
Ada hypervisor perangkat keras, hypervisor di atas OS, dan container.

Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Hypervisor perangkat keras bagus jika Anda benar-benar ingin mengisolasi sesuatu. Karena dimungkinkan untuk mengisolasi pada tingkat halaman memori dan prosesor.

Ada hypervisor sebagai program, dan ada container, dan kita akan membicarakannya lebih lanjut. Sistem kontainerisasi tidak memiliki hypervisor, tetapi terdapat Mesin Kontainer yang membuat dan mengelola kontainer. Benda ini lebih ringan, jadi karena bekerja dengan inti, overhead lebih sedikit atau tidak ada sama sekali.

Apa yang digunakan untuk containerisasi di tingkat kernel

Teknologi utama yang memungkinkan Anda membuat wadah yang diisolasi dari proses lain adalah Namespace dan Grup Kontrol.

Ruang Nama: PID, Jaringan, Pemasangan, dan Pengguna. Masih banyak lagi, namun untuk memudahkan pemahaman kami akan fokus pada hal ini.

Namespace PID membatasi proses. Ketika misalnya kita membuat Namespace PID dan menempatkan proses di sana, maka menjadi dengan PID 1. Biasanya dalam sistem PID 1 adalah systemd atau init. Oleh karena itu, ketika kita menempatkan suatu proses di namespace baru, proses tersebut juga menerima PID 1.

Networking Namespace memungkinkan Anda membatasi/mengisolasi jaringan dan menempatkan antarmuka Anda sendiri di dalamnya. Mount adalah batasan sistem file. Pengguna—pembatasan terhadap pengguna.

Grup Kontrol: Memori, CPU, IOPS, Jaringan - total sekitar 12 pengaturan. Jika tidak, mereka juga disebut Cgroups (“C-group”).

Grup Kontrol mengelola sumber daya untuk sebuah kontainer. Melalui Grup Kontrol kita dapat mengatakan bahwa container tidak boleh mengonsumsi lebih dari sejumlah sumber daya tertentu.

Agar containerisasi berfungsi sepenuhnya, teknologi tambahan digunakan: Kemampuan, Copy-on-write, dan lainnya.

Kapabilitas adalah ketika kita memberi tahu suatu proses apa yang bisa dan tidak bisa dilakukannya. Pada tingkat kernel, ini hanyalah bitmap dengan banyak parameter. Misalnya, pengguna root memiliki hak penuh dan dapat melakukan apa saja. Server waktu dapat mengubah waktu sistem: ia memiliki kemampuan pada Time Capsule, dan hanya itu. Dengan menggunakan hak istimewa, Anda dapat secara fleksibel mengonfigurasi pembatasan proses, dan dengan demikian melindungi diri Anda sendiri.

Sistem Copy-on-write memungkinkan kita bekerja dengan image Docker dan menggunakannya dengan lebih efisien.

Docker saat ini memiliki masalah kompatibilitas dengan Cgroups v2, jadi artikel ini berfokus secara khusus pada Cgroups v1.

Tapi mari kita kembali ke sejarah.

Ketika sistem virtualisasi muncul di tingkat kernel, mereka mulai digunakan secara aktif. Overhead pada hypervisor hilang, namun beberapa masalah tetap ada:

  • gambar besar: mereka memasukkan sistem operasi, perpustakaan, sekumpulan perangkat lunak yang berbeda ke dalam OpenVZ yang sama, dan pada akhirnya gambar tersebut tetap menjadi cukup besar;
  • Tidak ada standar normal untuk pengemasan dan pengiriman, sehingga masalah ketergantungan tetap ada. Ada situasi ketika dua bagian kode menggunakan perpustakaan yang sama, tetapi dengan versi yang berbeda. Mungkin ada konflik di antara mereka.

Untuk mengatasi semua masalah ini, era berikutnya telah tiba.

Era kontainer

Ketika Era Kontainer tiba, filosofi bekerja dengan Kontainer berubah:

  • Satu proses - satu wadah.
  • Kami mengirimkan semua dependensi yang dibutuhkan proses ke containernya. Hal ini memerlukan pemotongan monolit menjadi layanan mikro.
  • Semakin kecil gambarnya, semakin baik - kemungkinan kerentanannya lebih sedikit, gambarnya diluncurkan lebih cepat, dan seterusnya.
  • Contoh menjadi fana.

Ingat apa yang saya katakan tentang hewan peliharaan vs sapi? Dahulu hewan ibarat hewan peliharaan, namun kini menjadi seperti hewan ternak. Sebelumnya, ada monolit - satu aplikasi. Sekarang ada 100 layanan mikro, 100 kontainer. Beberapa kontainer mungkin memiliki 2-3 replika. Menjadi kurang penting bagi kami untuk mengontrol setiap kontainer. Yang lebih penting bagi kami adalah ketersediaan layanan itu sendiri: apa yang dilakukan oleh kumpulan kontainer ini. Hal ini mengubah pendekatan terhadap pemantauan.

Pada 2014-2015, Docker mengalami masa kejayaan - teknologi yang akan kita bicarakan sekarang.

Docker mengubah filosofi dan standarisasi pengemasan aplikasi. Dengan menggunakan Docker, kita dapat mengemas aplikasi, mengirimkannya ke repositori, mendownloadnya dari sana, dan menyebarkannya.

Kami memasukkan semua yang kami butuhkan ke dalam wadah Docker, sehingga masalah ketergantungan terpecahkan. Docker menjamin reproduktifitas. Saya rasa banyak orang mengalami hal yang tidak dapat direproduksi: semuanya berjalan sesuai keinginan Anda, Anda mendorongnya ke tahap produksi, dan di sanalah semuanya berhenti berfungsi. Dengan Docker, masalah ini hilang. Jika container Docker Anda mulai dan melakukan apa yang perlu dilakukan, kemungkinan besar container tersebut akan mulai berproduksi dan melakukan hal yang sama di sana.

Penyimpangan tentang overhead

Selalu ada perselisihan mengenai overhead. Beberapa orang percaya bahwa Docker tidak membawa beban tambahan, karena ia menggunakan kernel Linux dan semua prosesnya yang diperlukan untuk containerisasi. Seperti, “jika Anda mengatakan bahwa Docker berada di atas kepala, maka kernel Linux berada di atas kepala.”

Di sisi lain, jika ditelusuri lebih dalam, memang ada beberapa hal di Docker yang, secara garis besar, bisa dikatakan overhead.

Yang pertama adalah namespace PID. Ketika kita menempatkan suatu proses dalam namespace, ia diberi PID 1. Pada saat yang sama, proses ini memiliki PID lain, yang terletak di namespace host, di luar container. Misalnya kita meluncurkan Nginx dalam sebuah container, menjadi PID 1 (proses master). Dan pada hostnya memiliki PID 12623. Dan sulit untuk mengatakan berapa besar overhead-nya.

Hal kedua adalah Cgroups. Mari kita ambil Cgroups berdasarkan memori, yaitu kemampuan untuk membatasi memori suatu wadah. Ketika diaktifkan, penghitung dan penghitungan memori diaktifkan: kernel perlu memahami berapa banyak halaman yang telah dialokasikan dan berapa banyak yang masih kosong untuk wadah ini. Ini mungkin merupakan biaya tambahan, tetapi saya belum melihat penelitian pasti tentang pengaruhnya terhadap kinerja. Dan saya sendiri tidak menyadari bahwa aplikasi yang berjalan di Docker tiba-tiba mengalami penurunan performa yang tajam.

Dan satu catatan lagi tentang performa. Beberapa parameter kernel diteruskan dari host ke container. Khususnya, beberapa parameter jaringan. Oleh karena itu, jika Anda ingin menjalankan sesuatu yang berkinerja tinggi di Docker, misalnya, sesuatu yang akan menggunakan jaringan secara aktif, maka Anda setidaknya perlu menyesuaikan parameter ini. Beberapa nf_conntrack, misalnya.

Tentang konsep Docker

Docker terdiri dari beberapa komponen:

  1. Docker Daemon adalah Mesin Kontainer yang sama; meluncurkan kontainer.
  2. Docker CII adalah utilitas manajemen Docker.
  3. Dockerfile - instruksi tentang cara membuat image.
  4. Gambar — gambar tempat wadah diluncurkan.
  5. Wadah.
  6. Registri Docker adalah repositori gambar.

Secara skematis terlihat seperti ini:

Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Daemon Docker berjalan di Docker_host dan meluncurkan container. Ada Klien yang mengirimkan perintah: membuat image, mendownload image, meluncurkan container. Daemon Docker masuk ke registri dan menjalankannya. Klien Docker dapat mengakses secara lokal (ke soket Unix) dan melalui TCP dari host jarak jauh.

Mari kita bahas setiap komponennya.

Daemon buruh pelabuhan - ini adalah bagian server, ia bekerja pada mesin host: mengunduh gambar dan meluncurkan container darinya, membuat jaringan antar container, mengumpulkan log. Saat kita mengatakan “buat sebuah gambar”, iblis juga melakukan hal yang sama.

CLI buruh pelabuhan — Bagian klien Docker, utilitas konsol untuk bekerja dengan daemon. Saya ulangi, ini dapat bekerja tidak hanya secara lokal, tetapi juga melalui jaringan.

Perintah dasar:

docker ps - menampilkan container yang sedang berjalan di host Docker.
gambar buruh pelabuhan - menampilkan gambar yang diunduh secara lokal.
pencarian buruh pelabuhan <> - mencari gambar di registri.
docker pull <> - mengunduh gambar dari registri ke mesin.
pembangunan buruh pelabuhan < > - kumpulkan gambarnya.
docker run <> - meluncurkan wadah.
docker rm <> - hapus wadahnya.
log buruh pelabuhan <> - log kontainer
docker start/stop/restart <> - bekerja dengan container

Jika Anda menguasai perintah-perintah ini dan yakin dalam menggunakannya, anggap diri Anda 70% mahir dalam Docker di tingkat pengguna.

Dockerfile - instruksi untuk membuat gambar. Hampir setiap perintah instruksi adalah lapisan baru. Mari kita lihat sebuah contoh.

Apa itu Docker: penjelasan singkat tentang sejarah dan abstraksi dasar

Seperti inilah tampilan Dockerfile: perintah di sebelah kiri, argumen di sebelah kanan. Setiap perintah yang ada di sini (dan umumnya ditulis di Dockerfile) membuat layer baru di Image.

Bahkan dengan melihat ke sisi kiri, Anda secara kasar dapat memahami apa yang sedang terjadi. Kami mengatakan: "buat folder untuk kami" - ini adalah satu lapisan. “Jadikan folder berfungsi” adalah lapisan lain, dan seterusnya. Kue lapis membuat hidup lebih mudah. Jika saya membuat Dockerfile lain dan mengubah sesuatu di baris terakhir - saya menjalankan sesuatu selain "python" "main.py", atau menginstal dependensi dari file lain - maka lapisan sebelumnya akan digunakan kembali sebagai cache.

Gambar - ini adalah kemasan wadah; wadah diluncurkan dari gambar. Jika kita melihat Docker dari sudut pandang manajer paket (seolah-olah kita bekerja dengan paket deb atau rpm), maka image pada dasarnya adalah paket rpm. Melalui yum install kita dapat menginstal aplikasi, menghapusnya, menemukannya di repositori, dan mendownloadnya. Di sini hampir sama: container diluncurkan dari image, disimpan di registri Docker (mirip dengan yum, di repositori), dan setiap image memiliki hash SHA-256, nama, dan tag.

Gambar dibuat sesuai dengan instruksi dari Dockerfile. Setiap instruksi dari Dockerfile membuat layer baru. Lapisan dapat digunakan kembali.

Registri buruh pelabuhan adalah repositori gambar Docker. Mirip dengan OS, Docker memiliki registri standar publik - dockerhub. Tapi Anda bisa membangun repositori Anda sendiri, registri Docker Anda sendiri.

Wadah - apa yang diluncurkan dari gambar. Kami membuat image sesuai dengan instruksi dari Dockerfile, lalu kami meluncurkannya dari image ini. Penampung ini diisolasi dari penampung lain dan harus berisi semua yang diperlukan agar aplikasi dapat berfungsi. Dalam hal ini, satu wadah - satu proses. Kebetulan Anda harus melakukan dua proses, tetapi ini agak bertentangan dengan ideologi Docker.

Persyaratan "satu kontainer, satu proses" terkait dengan Namespace PID. Ketika proses dengan PID 1 dimulai di Namespace, jika tiba-tiba mati, maka seluruh container juga akan mati. Jika ada dua proses yang berjalan di sana: yang satu hidup dan yang lainnya mati, maka container akan tetap terus hidup. Tapi ini adalah pertanyaan tentang Praktik Terbaik, kita akan membicarakannya di materi lain.

Untuk mempelajari fitur-fitur dan program lengkap kursus secara lebih rinci, silakan ikuti tautan: “Kursus video Docker'.

Penulis: Marcel Ibraev, administrator Kubernetes bersertifikat, insinyur praktik di Southbridge, pembicara dan pengembang kursus Slurm.

Sumber: www.habr.com

Tambah komentar