Menjalankan systemd dalam sebuah wadah

Kami telah lama mengikuti topik penggunaan systemd dalam container. Pada tahun 2014, teknisi keamanan kami Daniel Walsh menulis sebuah artikel Menjalankan systemd dalam Docker Container, dan beberapa tahun kemudian - yang lain, yang dipanggil Menjalankan systemd dalam wadah yang tidak memiliki hak istimewa, di mana dia menyatakan bahwa situasinya tidak banyak membaik. Secara khusus, dia menulis bahwa β€œsayangnya, bahkan dua tahun kemudian, jika Anda mencari β€œsistem Docker” di Google, hal pertama yang muncul adalah artikel lamanya yang sama. Jadi inilah waktunya untuk mengubah sesuatu.” Selain itu, kami telah membicarakannya konflik antara Docker dan pengembang systemd.

Menjalankan systemd dalam sebuah wadah

Pada artikel ini kami akan menunjukkan apa yang berubah dari waktu ke waktu dan bagaimana Podman dapat membantu kami dalam hal ini.

Ada banyak alasan untuk menjalankan systemd di dalam container, seperti:

  1. Kontainer multilayanan – banyak orang ingin mengeluarkan aplikasi multi-layanan dari mesin virtual dan menjalankannya dalam container. Tentu saja akan lebih baik jika aplikasi tersebut dipecah menjadi layanan-layanan mikro, namun belum semua orang mengetahui cara melakukannya atau tidak punya waktu. Oleh karena itu, menjalankan aplikasi seperti layanan yang diluncurkan oleh systemd dari file unit sangat masuk akal.
  2. File Unit Sistemd – Sebagian besar aplikasi yang berjalan di dalam container dibuat dari kode yang sebelumnya dijalankan pada mesin virtual atau fisik. Aplikasi ini memiliki file unit yang ditulis untuk aplikasi ini dan memahami cara meluncurkannya. Jadi lebih baik memulai layanan menggunakan metode yang didukung, daripada meretas layanan init Anda sendiri.
  3. Systemd adalah manajer proses. Ia mengelola layanan (mematikan, memulai ulang layanan, atau mematikan proses zombie) lebih baik daripada alat lainnya.

Meskipun demikian, ada banyak alasan untuk tidak menjalankan systemd dalam container. Yang utama adalah systemd/jurnal mengontrol keluaran wadah, dan alat-alat sejenisnya Kubernetes ΠΈΠ»ΠΈ Pergeseran Terbuka mengharapkan kontainer untuk menulis log langsung ke stdout dan stderr. Oleh karena itu, jika Anda ingin mengelola container melalui alat orkestrasi seperti yang disebutkan di atas, Anda harus secara serius mempertimbangkan untuk menggunakan container berbasis systemd. Selain itu, pengembang Docker dan Moby sering kali sangat menentang penggunaan systemd dalam container.

Kedatangan Podman

Kami dengan senang hati melaporkan bahwa situasinya akhirnya bergerak maju. Tim yang bertanggung jawab menjalankan kontainer di Red Hat memutuskan untuk mengembangkannya mesin kontainer Anda sendiri. Dia mendapat nama tukang pod dan menawarkan antarmuka baris perintah (CLI) yang sama dengan Docker. Dan hampir semua perintah Docker dapat digunakan di Podman dengan cara yang sama. Kami sering mengadakan seminar, yang sekarang disebut Mengubah Docker menjadi Podman, dan slide pertama memerlukan penulisan: alias docker=podman.

Banyak orang melakukan hal itu.

Podman saya dan saya sama sekali tidak menentang container berbasis systemd. Bagaimanapun, Systemd adalah subsistem init Linux yang paling umum digunakan, dan tidak mengizinkannya bekerja dengan baik di container berarti mengabaikan kebiasaan ribuan orang menjalankan container.

Podman tahu apa yang harus dilakukan agar systemd berfungsi dengan baik di dalam container. Dibutuhkan hal-hal seperti memasang tmpfs di/run dan/tmp. Dia suka mengaktifkan lingkungan "containerized" dan mengharapkan izin menulis ke bagiannya di direktori cgroup dan ke folder /var/log/journald.

Saat Anda memulai sebuah container yang perintah pertamanya adalah init atau systemd, Podman secara otomatis mengonfigurasi tmpfs dan Cgroups untuk memastikan bahwa systemd dimulai tanpa masalah. Untuk memblokir mode peluncuran otomatis ini, gunakan opsi --systemd=false. Harap dicatat bahwa Podman hanya menggunakan mode systemd ketika ia merasa perlu menjalankan perintah systemd atau init.

Berikut ini kutipan dari manualnya:

man podman lari
...

–sistemd=benar|salah

Menjalankan container dalam mode systemd. Diaktifkan secara default.

Jika Anda menjalankan perintah systemd atau init di dalam container, Podman akan mengonfigurasi titik pemasangan tmpfs di direktori berikut:

/jalankan, /jalankan/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/jurnal

Juga sinyal berhenti default adalah SIGRTMIN+3.

Semua ini memungkinkan systemd untuk berjalan dalam wadah tertutup tanpa modifikasi apa pun.

CATATAN: systemd mencoba menulis ke sistem file cgroup. Namun, SELinux mencegah container melakukan hal ini secara default. Untuk mengaktifkan penulisan, aktifkan parameter boolean container_manage_cgroup:

setsebool -P container_manage_cgroup benar

Sekarang lihat seperti apa Dockerfile untuk menjalankan systemd dalam sebuah container menggunakan Podman:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

Itu saja.

Sekarang kita merakit wadahnya:

# podman build -t systemd .

Kami memberi tahu SELinux untuk mengizinkan systemd mengubah konfigurasi Cgroups:

# setsebool -P container_manage_cgroup true

Ngomong-ngomong, banyak orang yang melupakan langkah ini. Untungnya, ini hanya perlu dilakukan sekali dan pengaturan disimpan setelah sistem di-boot ulang.

Sekarang kita tinggal memulai containernya:

# 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 saja, layanan sudah aktif dan berjalan:

$ curl localhost

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

…

</html>

CATATAN: Jangan coba ini di Docker! Di sana Anda masih perlu menari dengan rebana untuk meluncurkan wadah semacam ini melalui daemon. (Bidang dan paket tambahan akan diperlukan agar semua ini berfungsi dengan lancar di Docker, atau harus dijalankan dalam wadah yang memiliki hak istimewa. Untuk detailnya, lihat Artikel.)

Beberapa hal keren lainnya tentang Podman dan systemd

Podman bekerja lebih baik daripada Docker di file unit systemd

Jika container perlu dijalankan saat sistem melakukan booting, Anda cukup memasukkan perintah Podman yang sesuai ke dalam file unit systemd, yang akan memulai layanan dan memantaunya. Podman menggunakan model fork-exec standar. Dengan kata lain, proses container adalah turunan dari proses Podman, sehingga systemd dapat dengan mudah memantaunya.

Docker menggunakan model client-server, dan perintah Docker CLI juga dapat ditempatkan langsung di file unit. Namun, setelah klien Docker terhubung ke daemon Docker, itu (klien) hanya menjadi proses lain yang memproses stdin dan stdout. Pada gilirannya, systemd tidak tahu tentang koneksi antara klien Docker dan kontainer yang berjalan di bawah kendali daemon Docker, dan oleh karena itu, dalam model ini, systemd pada dasarnya tidak dapat memantau layanan.

Mengaktifkan systemd melalui soket

Podman menangani aktivasi melalui soket dengan benar. Karena Podman menggunakan model fork-exec, Podman dapat meneruskan soket ke proses container turunannya. Docker tidak dapat melakukan ini karena menggunakan model klien-server.

Layanan varlink yang digunakan Podman untuk berkomunikasi dengan klien jarak jauh ke container sebenarnya diaktifkan melalui soket. Paket cockpit-podman, yang ditulis dalam Node.js dan merupakan bagian dari proyek kokpit, memungkinkan orang berinteraksi dengan container Podman melalui antarmuka web. Daemon web yang menjalankan cockpit-podman mengirimkan pesan ke soket varlink yang didengarkan oleh systemd. Systemd kemudian mengaktifkan program Podman untuk menerima pesan dan mulai mengelola container. Mengaktifkan systemd melalui soket menghilangkan kebutuhan akan daemon yang terus berjalan saat mengimplementasikan API jarak jauh.

Selain itu, kami sedang mengembangkan klien Podman lain yang disebut podman-remote, yang mengimplementasikan CLI Podman yang sama tetapi memanggil varlink untuk menjalankan container. Podman-remote dapat berjalan di atas sesi SSH, memungkinkan Anda berinteraksi secara aman dengan container di mesin yang berbeda. Seiring waktu, kami berencana untuk mengaktifkan podman-remote untuk mendukung MacOS dan Windows bersama dengan Linux, sehingga pengembang pada platform tersebut dapat menjalankan mesin virtual Linux dengan menjalankan Podman varlink dan mendapatkan pengalaman penuh bahwa container berjalan di mesin lokal.

SD_NOTIFY

Systemd memungkinkan Anda untuk menunda peluncuran layanan tambahan hingga layanan dalam container yang diperlukan dimulai. Podman dapat meneruskan soket SD_NOTIFY ke layanan dalam container sehingga layanan memberi tahu systemd bahwa layanan tersebut siap dioperasikan. Dan lagi, Docker, yang menggunakan model client-server, tidak bisa melakukan ini.

Dalam rencana

Kami berencana menambahkan perintah podman generate systemd CONTAINERID, yang akan menghasilkan file unit systemd untuk mengelola container tertentu yang ditentukan. Ini harus bekerja dalam mode root dan tanpa root untuk wadah yang tidak memiliki hak istimewa. Kami bahkan telah melihat permintaan untuk runtime systemd-nspawn yang kompatibel dengan OCI.

Kesimpulan

Menjalankan systemd dalam sebuah container adalah kebutuhan yang dapat dimengerti. Dan berkat Podman, kami akhirnya memiliki runtime container yang tidak bertentangan dengan systemd, namun membuatnya mudah digunakan.

Sumber: www.habr.com

Tambah komentar