Menjalankan systemd dalam bekas

Kami telah mengikuti topik menggunakan systemd dalam bekas untuk masa yang lama. Pada tahun 2014, jurutera keselamatan kami Daniel Walsh menulis artikel Menjalankan systemd dalam Kontena Docker, dan beberapa tahun kemudian - satu lagi, yang dipanggil Menjalankan systemd dalam bekas bukan istimewa, di mana beliau menyatakan bahawa keadaan tidak banyak bertambah baik. Khususnya, dia menulis bahawa "malangnya, walaupun dua tahun kemudian, jika anda google "sistem Docker", perkara pertama yang muncul ialah artikel lamanya yang sama. Jadi sudah tiba masanya untuk mengubah sesuatu." Di samping itu, kita telah pun bercakap tentang konflik antara Docker dan pembangun systemd.

Menjalankan systemd dalam bekas

Dalam artikel ini kami akan menunjukkan perkara yang telah berubah dari semasa ke semasa dan cara Podman boleh membantu kami dalam perkara ini.

Terdapat banyak sebab untuk menjalankan systemd di dalam bekas, seperti:

  1. Bekas pelbagai perkhidmatan – ramai orang ingin mengeluarkan aplikasi berbilang perkhidmatan mereka daripada mesin maya dan menjalankannya dalam bekas. Adalah lebih baik, sudah tentu, untuk memecahkan aplikasi sedemikian ke dalam perkhidmatan mikro, tetapi tidak semua orang tahu bagaimana untuk melakukan ini atau hanya tidak mempunyai masa. Oleh itu, menjalankan aplikasi seperti perkhidmatan yang dilancarkan oleh systemd dari fail unit sangat masuk akal.
  2. Fail Unit Systemd – Kebanyakan aplikasi yang berjalan di dalam bekas dibina daripada kod yang sebelum ini dijalankan pada mesin maya atau fizikal. Aplikasi ini mempunyai fail unit yang ditulis untuk aplikasi ini dan memahami cara ia harus dilancarkan. Jadi adalah lebih baik untuk memulakan perkhidmatan menggunakan kaedah yang disokong, daripada menggodam perkhidmatan init anda sendiri.
  3. Systemd ialah pengurus proses. Ia mengurus perkhidmatan (menutup, memulakan semula perkhidmatan, atau membunuh proses zombi) lebih baik daripada alat lain.

Yang berkata, terdapat banyak sebab untuk tidak menjalankan systemd dalam bekas. Yang utama ialah systemd/journald mengawal output bekas, dan alat seperti Kubernetes atau anjakan terbuka mengharapkan bekas untuk menulis log terus ke stdout dan stderr. Oleh itu, jika anda akan menguruskan bekas melalui alat orkestrasi seperti yang dinyatakan di atas, anda harus serius mempertimbangkan untuk menggunakan bekas berasaskan systemd. Selain itu, pembangun Docker dan Moby sering menentang keras menggunakan systemd dalam bekas.

Kedatangan Podman

Kami gembira untuk melaporkan bahawa keadaan akhirnya bergerak ke hadapan. Pasukan yang bertanggungjawab untuk menjalankan kontena di Red Hat memutuskan untuk membangunkan enjin kontena anda sendiri. Dia mendapat nama podman dan menawarkan antara muka baris arahan (CLI) yang sama seperti Docker. Dan hampir semua arahan Docker boleh digunakan dalam Podman dengan cara yang sama. Kami sering mengadakan seminar, yang kini dipanggil Menukar Docker kepada Podman, dan slaid pertama memerlukan penulisan: alias docker=podman.

Ramai orang melakukan ini.

Podman saya dan saya sama sekali tidak menentang bekas berasaskan systemd. Lagipun, Systemd ialah subsistem init Linux yang paling biasa digunakan, dan tidak membenarkannya berfungsi dengan betul dalam bekas bermakna mengabaikan bagaimana beribu-ribu orang biasa menjalankan kontena.

Podman tahu apa yang perlu dilakukan untuk menjadikan systemd berfungsi dengan betul dalam bekas. Ia memerlukan perkara seperti memasang tmpfs pada /run dan /tmp. Dia suka persekitaran "bekas" didayakan dan mengharapkan kebenaran menulis ke bahagian direktori cgroupnya dan ke folder /var/log/journald.

Apabila anda memulakan bekas di mana perintah pertama adalah init atau systemd, Podman secara automatik mengkonfigurasi tmpfs dan Cgroups untuk memastikan systemd bermula tanpa masalah. Untuk menyekat mod pelancaran automatik ini, gunakan pilihan --systemd=false. Sila ambil perhatian bahawa Podman hanya menggunakan mod systemd apabila ia melihat bahawa ia perlu menjalankan perintah systemd atau init.

Berikut adalah petikan daripada manual:

lelaki podman lari
...

–systemd=true|false

Menjalankan bekas dalam mod systemd. Didayakan secara lalai.

Jika anda menjalankan perintah systemd atau init di dalam bekas, Podman akan mengkonfigurasi titik pelekap tmpfs dalam direktori berikut:

/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal

Juga isyarat berhenti lalai ialah SIGRTMIN+3.

Semua ini membolehkan systemd berjalan dalam bekas tertutup tanpa sebarang pengubahsuaian.

NOTA: systemd cuba menulis ke sistem fail cgroup. Walau bagaimanapun, SELinux menghalang bekas daripada melakukan ini secara lalai. Untuk mendayakan penulisan, dayakan parameter boolean container_manage_cgroup:

setsebool -P container_manage_cgroup true

Sekarang lihat rupa Dockerfile untuk menjalankan systemd dalam bekas menggunakan Podman:

# cat Dockerfile

FROM fedora

RUN dnf -y install httpd; dnf clean all; systemctl enable httpd

EXPOSE 80

CMD [ "/sbin/init" ]

Itu sahaja.

Sekarang kami memasang bekas:

# podman build -t systemd .

Kami memberitahu SELinux untuk membenarkan systemd mengubah suai konfigurasi Cgroups:

# setsebool -P container_manage_cgroup true

By the way, ramai orang lupa tentang langkah ini. Nasib baik, ini hanya perlu dilakukan sekali dan tetapan disimpan selepas but semula sistem.

Sekarang kita hanya memulakan bekas:

# podman run -ti -p 80:80 systemd

systemd 239 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid)

Detected virtualization container-other.

Detected architecture x86-64.

Welcome to Fedora 29 (Container Image)!

Set hostname to <1b51b684bc99>.

Failed to install release agent, ignoring: Read-only file system

File /usr/lib/systemd/system/systemd-journald.service:26 configures an IP firewall (IPAddressDeny=any), but the local system does not support BPF/cgroup based firewalling.

Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)

[  OK ] Listening on initctl Compatibility Named Pipe.

[  OK ] Listening on Journal Socket (/dev/log).

[  OK ] Started Forward Password Requests to Wall Directory Watch.

[  OK ] Started Dispatch Password Requests to Console Directory Watch.

[  OK ] Reached target Slices.

…

[  OK ] Started The Apache HTTP Server.

Itu sahaja, perkhidmatan sedang berjalan dan berjalan:

$ curl localhost

<html  xml_lang="en" lang="en">

…

</html>

NOTA: Jangan cuba ini di Docker! Di sana anda masih perlu menari dengan tamborin untuk melancarkan bekas jenis ini melalui daemon. (Medan dan pakej tambahan diperlukan untuk menjadikan ini semua berfungsi dengan lancar dalam Docker, atau ia perlu dijalankan dalam bekas istimewa. Untuk butiran, lihat artikel.)

Beberapa lagi perkara menarik tentang Podman dan systemd

Podman berfungsi lebih baik daripada Docker dalam fail unit systemd

Jika bekas perlu dimulakan apabila sistem but, maka anda hanya boleh memasukkan arahan Podman yang sesuai ke dalam fail unit systemd, yang akan memulakan perkhidmatan dan memantaunya. Podman menggunakan model fork-exec standard. Dalam erti kata lain, proses kontena adalah anak kepada proses Podman, jadi systemd boleh memantaunya dengan mudah.

Docker menggunakan model pelayan pelanggan, dan arahan CLI Docker juga boleh diletakkan terus dalam fail unit. Walau bagaimanapun, apabila klien Docker menyambung kepada daemon Docker, ia (pelanggan) menjadi satu lagi proses pengendalian stdin dan stdout. Sebaliknya, systemd tidak tahu tentang sambungan antara klien Docker dan bekas yang berjalan di bawah kawalan daemon Docker, dan oleh itu, dalam model ini, systemd pada asasnya tidak dapat memantau perkhidmatan.

Mengaktifkan systemd melalui soket

Podman mengendalikan pengaktifan melalui soket dengan betul. Oleh kerana Podman menggunakan model fork-exec, ia boleh memajukan soket ke proses bekas anaknya. Docker tidak boleh melakukan ini kerana ia menggunakan model pelayan pelanggan.

Perkhidmatan varlink yang Podman gunakan untuk berkomunikasi dengan pelanggan jauh ke bekas sebenarnya diaktifkan melalui soket. Pakej cockpit-podman, yang ditulis dalam Node.js dan sebahagian daripada projek cockpit, membolehkan orang ramai berinteraksi dengan bekas Podman melalui antara muka web. Daemon web yang menjalankan cockpit-podman menghantar mesej ke soket varlink yang systemd mendengar. Systemd kemudian mengaktifkan program Podman untuk menerima mesej dan mula menguruskan bekas. Mengaktifkan systemd melalui soket menghapuskan keperluan untuk daemon yang sentiasa berjalan apabila melaksanakan API jauh.

Selain itu, kami sedang membangunkan pelanggan Podman lain yang dipanggil podman-remote, yang melaksanakan CLI Podman yang sama tetapi memanggil varlink untuk menjalankan bekas. Podman-remote boleh berjalan di atas sesi SSH, membolehkan anda berinteraksi dengan selamat dengan bekas pada mesin yang berbeza. Dari masa ke masa, kami merancang untuk mendayakan podman-remote untuk menyokong MacOS dan Windows bersama-sama Linux, supaya pembangun pada platform tersebut boleh menjalankan mesin maya Linux dengan Podman varlink berjalan dan mempunyai pengalaman penuh bahawa bekas dijalankan pada mesin tempatan.

SD_NOTIFY

Systemd membenarkan anda menangguhkan pelancaran perkhidmatan tambahan sehingga perkhidmatan kontena yang mereka perlukan bermula. Podman boleh memajukan soket SD_NOTIFY ke perkhidmatan kontena supaya perkhidmatan memberitahu systemd bahawa ia sedia untuk beroperasi. Dan sekali lagi, Docker, yang menggunakan model pelayan pelanggan, tidak boleh melakukan ini.

Dalam rancangan

Kami merancang untuk menambah perintah podman generate systemd CONTAINERID, yang akan menjana fail unit systemd untuk mengurus bekas tertentu yang ditentukan. Ini sepatutnya berfungsi dalam kedua-dua mod akar dan tanpa akar untuk bekas yang tidak mempunyai hak istimewa. Kami juga telah melihat permintaan untuk masa jalan systemd-nspawn yang serasi dengan OCI.

Kesimpulan

Menjalankan systemd dalam bekas adalah keperluan yang boleh difahami. Dan terima kasih kepada Podman, kami akhirnya mempunyai masa jalan kontena yang tidak bercanggah dengan systemd, tetapi menjadikannya mudah untuk digunakan.

Sumber: www.habr.com

Tambah komen