Dumb-init adalah penyelia proses sederhana dan sistem init yang dirancang untuk berjalan sebagai PID 1 di dalam lingkungan wadah minimal (seperti Docker). Ini digunakan sebagai biner kecil yang terkait secara statis yang ditulis dalam C.
Wadah ringan telah mempopulerkan gagasan menjalankan proses atau layanan tunggal tanpa sistem init normal seperti SystemD atau Sysvinit. Namun, menghilangkan sistem init sering menyebabkan penanganan proses dan sinyal yang salah, dan dapat mengakibatkan masalah seperti wadah yang tidak dapat dihentikan dengan anggun, atau wadah bocor yang seharusnya dihancurkan.
dumb-init memungkinkan Anda untuk hanya mengawali perintah Anda dengan dumb-init . Ini bertindak sebagai PID 1 dan segera memunculkan perintah Anda sebagai proses anak, berhati -hati untuk menangani dan meneruskan sinyal saat diterima.
Biasanya, ketika Anda meluncurkan wadah Docker, proses yang Anda jalankan menjadi PID 1, memberikan keanehan dan tanggung jawab yang datang dengan menjadi sistem init untuk wadah.
Ada dua masalah umum yang disajikan ini:
Dalam kebanyakan kasus, sinyal tidak akan ditangani dengan benar.
Kernel Linux menerapkan penanganan sinyal khusus untuk proses yang berjalan sebagai PID 1.
Ketika proses dikirim sinyal pada sistem Linux normal, kernel pertama -tama akan memeriksa penangan khusus yang telah didaftarkan oleh proses untuk sinyal itu, dan sebaliknya kembali ke perilaku default (misalnya, membunuh proses pada SIGTERM ).
Namun, jika proses yang menerima sinyal adalah PID 1, ia mendapat perlakuan khusus oleh kernel; Jika belum mendaftarkan penangan untuk sinyal, kernel tidak akan kembali ke perilaku default, dan tidak ada yang terjadi. Dengan kata lain, jika proses Anda tidak secara eksplisit menangani sinyal -sinyal ini, mengirimkannya SIGTERM tidak akan berpengaruh sama sekali.
Contoh umum adalah pekerjaan CI yang melakukan docker run my-container script : Mengirim SIGTERM ke proses docker run biasanya akan membunuh perintah docker run , tetapi membiarkan wadah berjalan di latar belakang.
Proses zombie yatim piatu tidak dituai dengan benar.
Suatu proses menjadi zombie saat keluar, dan tetap menjadi zombie sampai orang tuanya memanggil beberapa variasi dari sistem wait() memanggilnya. Tetap dalam tabel proses sebagai proses "mati". Biasanya, proses induk akan menelepon wait() segera dan menghindari zombie yang lama hidup.
Jika orang tua keluar di hadapan anaknya, anak itu "yatim", dan diarahkan kembali di bawah PID 1. Sistem init dengan demikian bertanggung jawab untuk wait() -ing pada proses zombie yatim.
Tentu saja, sebagian besar proses tidak akan wait() pada proses acak yang kebetulan melekat padanya, sehingga wadah sering berakhir dengan lusinan zombie yang berakar pada PID 1.
dumb-init lakukan dumb-init berjalan sebagai PID 1, bertindak seperti sistem init sederhana. Ini meluncurkan satu proses dan kemudian proxy semuanya menerima sinyal untuk sesi yang berakar pada proses anak itu.
Karena proses Anda yang sebenarnya tidak lagi PID 1, ketika menerima sinyal dari dumb-init , penangan sinyal default akan diterapkan, dan proses Anda akan berperilaku seperti yang Anda harapkan. Jika proses Anda mati, dumb-init juga akan mati, berhati-hati untuk membersihkan proses lain yang mungkin masih ada.
Dalam mode defaultnya, dumb-init membuat sesi yang berakar pada anak, dan mengirimkan sinyal ke seluruh kelompok proses. Ini berguna jika Anda memiliki anak yang tidak memiliki pertimbangan buruk (seperti skrip shell) yang biasanya tidak memberi sinyal anak-anaknya sebelum meninggal.
Ini sebenarnya dapat berguna di luar wadah Docker dalam pengawas proses reguler seperti Daemontools atau Supervisord untuk mengawasi skrip shell. Biasanya, sinyal seperti SIGTERM yang diterima oleh shell tidak diteruskan ke subproses; Sebaliknya, hanya proses shell mati. Dengan Dumb-Init, Anda bisa menulis skrip shell dengan Init Dumb di Shebang:
#!/usr/bin/dumb-init /bin/sh
my-web-server & # launch a process in the background
my-other-server # launch another process in the foreground
Biasanya, SIGTERM yang dikirim ke shell akan membunuh cangkang tetapi membiarkan proses -proses itu berjalan (baik latar belakang maupun latar depan!). Dengan Init Dumb, subproses Anda akan menerima sinyal yang sama dengan shell Anda.
Jika Anda ingin sinyal hanya dikirim ke anak langsung, Anda dapat menjalankan dengan argumen --single-child , atau mengatur variabel lingkungan DUMB_INIT_SETSID=0 saat menjalankan dumb-init . Dalam mode ini, init bodoh benar-benar transparan; Anda bahkan dapat merangkai beberapa bersama-sama (seperti dumb-init dumb-init echo 'oh, hi' ).
Dumb-init memungkinkan penulisan ulang sinyal yang masuk sebelum memproksikannya. Ini berguna dalam kasus di mana Anda memiliki pengawas Docker (seperti MESO atau Kubernetes) yang selalu mengirimkan sinyal standar (misalnya SIGTERM). Beberapa aplikasi memerlukan sinyal berhenti yang berbeda untuk melakukan pembersihan yang anggun.
Misalnya, untuk menulis ulang sinyal sigterm (angka 15) ke sigquit (angka 3), cukup tambahkan --rewrite 15:3 pada baris perintah.
Untuk menjatuhkan sinyal sepenuhnya, Anda dapat menulis ulang ke nomor khusus 0 .
Saat berjalan dalam mode setSID, tidak cukup untuk meneruskan SIGTSTP / SIGTTIN / SIGTTOU dalam banyak kasus, karena jika prosesnya belum menambahkan penangan sinyal khusus untuk sinyal -sinyal ini, maka kernel tidak akan menerapkan perilaku penanganan sinyal default (yang akan menangguhkan proses) karena merupakan anggota kelompok proses pidato. Untuk alasan ini, kami menetapkan penulisan ulang default ke SIGSTOP dari ketiga sinyal tersebut. Anda dapat memilih keluar dari perilaku ini dengan menulis ulang sinyal kembali ke nilai -nilai aslinya, jika diinginkan.
Satu peringatan dengan fitur ini: untuk sinyal kontrol pekerjaan ( SIGTSTP , SIGTTIN , SIGTTOU ), DUMB-INIT akan selalu menangguhkan dirinya setelah menerima sinyal, bahkan jika Anda menulis ulang ke sesuatu yang lain.
Anda memiliki beberapa opsi untuk menggunakan dumb-init :
Banyak distribusi Linux yang populer (termasuk Debian (sejak stretch ) dan turunan Debian seperti Ubuntu (karena bionic )) sekarang berisi paket-paket bodoh-init dalam repositori resmi mereka.
Pada distribusi berbasis Debian, Anda dapat menjalankan apt install dumb-init untuk menginstal Dumb-Init, sama seperti Anda akan menginstal paket lainnya.
CATATAN: Sebagian besar versi yang distro-distro dari dumb-init tidak terkait secara statis, tidak seperti versi yang kami berikan (lihat opsi lain di bawah). Ini biasanya baik-baik saja, tetapi berarti bahwa versi-versi bodoh-init ini umumnya tidak akan berfungsi ketika disalin ke distro Linux lainnya, tidak seperti versi yang terkait secara statis yang kami berikan.
Jika Anda memiliki server APT internal, mengunggah .deb ke server Anda adalah cara yang disarankan untuk menggunakan dumb-init . Di DockerFiles Anda, Anda dapat apt install dumb-init dan itu akan tersedia.
Paket Debian tersedia dari tab Rilis GitHub, atau Anda dapat menjalankan make builddeb sendiri.
.deb secara manual (Debian/Ubuntu) Jika Anda tidak memiliki server APT internal, Anda dapat menggunakan dpkg -i untuk menginstal paket .deb . Anda dapat memilih bagaimana Anda mendapatkan .deb ke wadah Anda (memasang direktori atau wget -ing itu adalah beberapa opsi).
Satu kemungkinan dengan perintah berikut di DockerFile Anda:
RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_amd64.deb
RUN dpkg -i dumb-init_*.debKarena Dumb-Init dirilis sebagai biner yang terkait secara statis, Anda biasanya dapat memasukkannya ke dalam gambar Anda. Berikut adalah contoh melakukan itu di dockerfile:
RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64
RUN chmod +x /usr/local/bin/dumb-init Meskipun dumb-init ditulis sepenuhnya di C, kami juga menyediakan paket Python yang mengkompilasi dan menginstal biner. Ini dapat diinstal dari PYPI menggunakan pip . Anda akan terlebih dahulu menginstal kompiler C (di Debian/Ubuntu, apt-get install gcc sudah cukup), maka cukup pip install dumb-init .
Pada 1.2.0, paket di PYPI tersedia sebagai arsip roda yang sudah dibangun dan tidak perlu dikompilasi pada distribusi Linux yang umum.
Setelah diinstal di dalam wadah Docker Anda, cukup awalkan perintah Anda dengan dumb-init (dan pastikan Anda menggunakan sintaks JSON yang disarankan).
Dalam dockerfile, ini adalah praktik yang baik untuk menggunakan dumb-init sebagai titik masuk wadah Anda. "Entrypoint" adalah perintah parsial yang mendapat prepended untuk instruksi CMD Anda, menjadikannya sangat cocok untuk init bodoh:
# Runs "/usr/bin/dumb-init -- /my/script --with --args"
ENTRYPOINT [ "/usr/bin/dumb-init" , "--" ]
# or if you use --rewrite or other cli flags
# ENTRYPOINT ["dumb-init", "--rewrite", "2:3", "--"]
CMD [ "/my/script" , "--with" , "--args" ] Jika Anda mendeklarasikan titik entri dalam gambar dasar, gambar apa pun yang turun darinya tidak perlu juga mendeklarasikan dumb-init. Mereka hanya bisa mengatur CMD seperti biasa.
Untuk penggunaan satu kali interaktif, Anda hanya dapat mempersiapkannya secara manual:
$ docker run my_container dumb-init python -c 'while True: pass'
Menjalankan perintah yang sama ini tanpa dumb-init akan mengakibatkan tidak dapat menghentikan wadah tanpa SIGKILL , tetapi dengan dumb-init , Anda dapat mengirimkannya lebih banyak sinyal yang manusiawi seperti SIGTERM .
Penting bagi Anda untuk menggunakan sintaks JSON untuk CMD dan ENTRYPOINT . Jika tidak, Docker memanggil shell untuk menjalankan perintah Anda, menghasilkan shell sebagai PID 1, bukannya bodoh.
Seringkali wadah ingin melakukan pekerjaan pra-awal yang tidak dapat dilakukan selama waktu pembangunan. Misalnya, Anda mungkin ingin melakukan templat beberapa file konfigurasi berdasarkan variabel lingkungan.
Cara terbaik untuk mengintegrasikannya dengan dumb-init adalah seperti ini:
ENTRYPOINT [ "/usr/bin/dumb-init" , "--" ]
CMD [ "bash" , "-c" , "do-some-pre-start-thing && exec my-server" ]Dengan masih menggunakan dumb-init sebagai titik masuk, Anda selalu memiliki sistem init yang tepat.
Bagian exec dari perintah bash adalah penting karena menggantikan proses bash dengan server Anda, sehingga shell hanya ada sejenak di awal.
Membangun biner-init dumb membutuhkan compiler yang berfungsi dan header LIBC dan default ke GLIBC.
$ make
Dumb-init yang dikompilasi secara statis lebih dari 700kB karena glibc, tetapi MUSL sekarang menjadi pilihan. Di debian/ubuntu apt-get install musl-tools untuk menginstal sumber dan pembungkus, lalu hanya:
$ CC=musl-gcc make
Ketika secara statis dikompilasi dengan Musl, ukuran biner sekitar 20kb.
Kami menggunakan konvensi standar Debian untuk menentukan dependensi build (lihat di debian/control ). Cara mudah untuk memulai adalah dengan apt-get install build-essential devscripts equivs , dan kemudian sudo mk-build-deps -i --remove untuk menginstal semua dependensi build yang hilang secara otomatis. Anda kemudian dapat menggunakan make builddeb untuk membangun paket Debian yang dumb-init.
Jika Anda lebih suka paket Debian otomatis menggunakan Docker, cukup jalankan make builddeb-docker . Ini lebih mudah, tetapi mengharuskan Anda untuk menjalankan Docker di mesin Anda.