Startējam systemd konteinerā

Mēs jau sen sekojam tēmai par systemd izmantošanu konteineros. Vēl 2014. gadā mūsu drošības inženieris Daniel Walsh uzrakstīja rakstu Running systemd within a Docker Container, bet pāris gadus vēlāk – citu, kas saucās Running systemd in a non-privileged container, kurā viņš norādīja, ka situācija nemaz nav uzlabojusies. Proti, viņš rakstīja, ka 'diemžēl, pat divus gadus vēlāk, ja googlē «Docker system», tad pirmais, kas parādās, ir viņa vecais raksts. Tātad, ir pienācis laiks kaut ko mainīt'. Turklāt mēs jau reiz stāstījām par konfliktu starp Docker un systemd izstrādātājiem.

Startējam systemd konteinerā

Šajā rakstā mēs parādīsim, kas ir mainījies pagājušajā laikā un kā mums var palīdzēt šajā jautājumā Podman.

Ir daudz iemeslu, lai palaistu systemd iekšējos konteineros, piemēram:

  1. Multiservisa konteineri – daudzi vēlas izņemt savas multiservisa lietotnes no virtuālajām mašīnām un palaist tās konteineros. Protams, būtu labāk šādas lietotnes sadalīt mikroservisos, bet ne visi to spēj vai vienkārši nav laika. Tāpēc palaist šādas lietotnes kā pakalpojumus, ko palaidīs systemd no vienības failiem, ir pilnīgi saprātīgi.
  2. Systemd vienības faili – lielākā daļa lietotņu, kas darbojas iekšējos konteineros, ir saliktas no koda, kas iepriekš tika palaists uz virtuālajām vai fiziskām mašīnām. Šīm lietotnēm ir vienības fails, kas tika rakstīts šīm lietotnēm un saprot, kā tās jāsāk. Tādējādi, pakalpojumus ir labāk palaist, izmantojot atbalstītus risinājumus, nevis laužot savu pašu init dienestu.
  3. Systemd ir procesu vadītājs. Tas pārvalda pakalpojumus (izbeidz, restarts pakalpojumus vai iznīcina zīmobrisus) labāk nekā jebkurš cits instruments.

Tomēr ir arī daudzi iemesli, lai nepalaistu systemd konteineros. Galvenais ir tas, ka systemd/journald kontrolē konteineru izvadi, un tādas rīces kā Kubernetes vai OpenShift paredz, ka konteineri rakstīs žurnālus tieši stdout un stderr. Tāpēc, ja plānojat pārvaldīt konteinerus, izmantojot minētos orķestrācijas rīkus, tad ir nopietni jādomā par systemd pamata konteineru izmantošanu. Turklāt Docker un Moby izstrādātāji bieži ir bijuši kategoriski pret systemd izmantošanu konteineros.

Podman ienākšana

Ar prieku paziņojam, ka situācija beidzot ir pārvietojusies no mirušās punktu. Komanda, kas Red Hat ir atbildīga par konteineru palaišanu, ir nolēmusi izstrādāt savu pašu konteineru dzinēju. Tas saņēmis nosaukumu Podman un piedāvā tādu pašu komandu rindu (CLI) saskarni kā Docker. Un praktiski visas Docker komandas var izmantot arī Podman. Mēs bieži rīkojam seminārus, kas tagad saucas Mainām Docker uz Podman, un pirmajā slaidā aicina rakstīt: alias docker=podman.

Daudzi to arī dara.

Mēs ar savu Podman neesam pret konteineriem, kas balstās uz systemd. Galu galā Systemd biežāk tiek izmantots kā init-sistēma Linux, un ļaut tam normāli nedarboties konteineros nozīmē ignorēt, kā tūkstošiem cilvēku ir pieraduši palaist konteinerus.

Podman zina, ko darīt, lai systemd normāli darbotos konteinerā. Tam nepieciešamas tādas lietas kā tmpfs montēšana uz /run un /tmp. Tam patīk, kad ir aktivizēta "konteineru" vide, un tas gaida rakstīšanas tiesības savā cgroup kataloga daļā un mapē /var/log/journald.

Palaidot konteineru, kurā pirmā komanda ir init vai systemd, Podman automātiski konfigurē tmpfs un Cgroups, lai systemd palaišana noritētu bez problēmām. Lai bloķētu šo automātisko palaišanas režīmu, tiek izmantota opcija —systemd=false. Ņemiet vērā, ka Podman izmanto systemd režīmu tikai tad, kad redz, ka jāpaveic systemd vai init komanda.

Šeit ir izvilkums no rokasgrāmatas:

man podman run
…

–systemd=true|false

Konteinera palaišana systemd režīmā. Pēc noklusējuma ir ieslēgta.

Ja konteinerā tiek izpildīta systemd vai init komanda, Podman konfigurēs tmpfs montēšanas punktus šādos katalogos:

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

Arī kā apstāšanās signāls pēc noklusējuma tiks izmantots SIGRTMIN+3.

Viss tas ļauj systemd darboties slēgtā konteinerā bez jebkādām modifikācijām.

Piezīme: systemd mēģina veikt ierakstus cgroup failu sistēmā. Tomēr SELinux pēc noklusējuma aizliedz konteineriem to darīt. Lai atļautu ierakstus, ieslēdziet loģisko parametru container_manage_cgroup:

setsebool -P container_manage_cgroup true

Tagad aplūkosim, kā izskatās Dockerfile systemd palaišanai konteinerā, izmantojot Podman:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

Tas arī viss.

Tagad uzkrājam konteineru:

# podman build -t systemd .

Sakām SELinux atļaut systemd modificēt Cgroups konfigurāciju:

# setsebool -P container_manage_cgroup true

Daudzi, starp citu, aizmirst par šo soli. Par laimi, to nepieciešams izdarīt tikai vienu reizi, un iestatījumi tiek saglabāti arī pēc sistēmas restartēšanas.

Tagad vienkārši uzsākam konteineru:

# 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.

Viss, pakalpojums ir uzsācies un darbojas:

$ curl localhost

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

…

</html>

PIEZĪME: Neaizmirstiet to izmēģināt Docker’ā! Tur joprojām ir nepieciešamas dažādas manipulācijas, lai palaiž šāda veida konteinerus caur demonizēto. (Nepieciešami papildu lauki un pakotnes, lai viss bez problēmām darbotos Docker, vai arī tas būs jāpalaiž privileģētā konteinerā. Sīkāk skatiet rakstā.)

Vēl pāris interesantu lietu par Podman un systemd

Podman darbojas labāk nekā Docker systemd vienības failos

Ja konteinerus jāuzsāk pie sistēmas ielādes, var vienkārši ievietot attiecīgās Podman komandas systemd vienības failā, kas uzsāks pakalpojumu un uzraudzīs to. Podman izmanto standarta izpildes modeli (fork-exec). Citiem vārdiem sakot, konteineru procesi ir meitas procesi attiecībā pret Podman procesu, tāpēc systemd to viegli var uzraudzīt.

Docker izmanto klienta-servera modeli, un Docker CLI komandas var arī ievietot tieši vienības failā. Tomēr, kad Docker klients pieslēdzas Docker demonam, tas (klients) kļūst par vēl vienu procesu, kas apstrādā stdin un stdout. Savukārt, systemd vispār nezina par saikni starp Docker klientu un konteineru, kas darbojas Docker demona vadībā, tāpēc šajā modelī systemd principā nevar uzraudzīt pakalpojumu.

systemd aktivācija caur soketu

Podman pareizi apstrādā aktivāciju caur soketu. Tā kā Podman izmanto fork-exec modeli, tas var nodot soketu saviem meitas konteineru procesiem. Docker tā nemāk, jo izmanto klienta-servera modeli.

Varlink serviss, ko Podman izmanto, lai mijiedarbotos ar attālajiem klientiem un konteineriem, patiesībā tiek aktivizēts caur soketu. Pakotne cockpit-podman, kas ir rakstīta Node.js un ietilpst cockpit projekta sastāvā, ļauj cilvēkiem mijiedarboties ar Podman konteineriem caur tīmekļa interfeisu. Tīmekļa demons, uz kura darbojas cockpit-podman, sūta ziņojumus uz varlink soketu, kuru klausās systemd. Pēc tam systemd aktivizē Podman programmu, lai saņemtu ziņojumus un sāktu pārvaldīt konteinerus. Systemd aktivizācija caur soketu ļauj iztikt bez pastāvīga darba demona attālināto API realizācijā.

Turklāt mēs izstrādājam vēl vienu klientu Podmanam, ko sauc podman-remote, kas īsteno to pašu Podman CLI, bet izmanto varlink, lai palaistu konteinerus. Podman-remote var darboties virs SSH sesijām, ļaujot droši mijiedarboties ar konteineriem dažādās mašīnās. Laika gaitā mēs plānojam izmantot podman-remote, lai atbalstītu MacOS un Windows kopā ar Linux, lai izstrādātāji šajās platformās varētu palaist Linux virtuālo mašīnu ar darbojošos Podman varlink un iegūt pilnīgu sajūtu, ka konteineri izpildās uz vietējās mašīnas.

SD_NOTIFY

Systemd ļauj atlikt palīgservisu uzsākšanu līdz brīdim, kad ir uzsākts nepieciešamais tiem konteinerizētais serviss. Podman var nodot SD_NOTIFY soketu konteinerizētajam servisam, lai tas paziņotu systemd par savu gatavību strādāt. Un atkal, Docker, kas izmanto klienta-servera modeli, tā nedara.

Plāni

Mēs plānojam pievienot komandu podman generate systemd CONTAINERID, kas ģenerēs systemd vienības failu konkrēta noteikta konteinca pārvaldībai. Tam jādarbojas gan root-, gan rootless režīmos nepilnvarotiem konteineriem. Mēs pat esam redzējuši pieprasījumu izveidot OCI savietojamu systemd-nspawn izpildes vidi.

Secinājums

Systemd palaišana konteinerā ir pilnīgi saprotama vajadzība. Un, pateicoties Podman, mums beidzot ir konteineru palaišanas vide, kas nav naidīga pret systemd, bet ļauj to vienkārši izmantot.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster