Sledujeme tému využívania systemd v kontajneroch už dávno. Ešte v roku 2014 náš bezpečnostný inžinier Daniel Walsh napísal článok , a o pár rokov neskôr napísal ďalší, ktorý bol nazvaný , v ktorom konštatoval, že situácia sa veľmi nezlepšila. Konkrétne napísal, že „bohužiaľ, aj dva roky neskôr, ak si vyhľadáte „Docker system“, ako prvé sa objaví jeho starý článok. Znamená to, že je na čase niečo zmeniť“. Okrem toho sme už spomínali .
V tomto článku ukážeme, čo sa za uplynulý čas zmenilo a ako nám v tomto prípade môže pomôcť Podman.
Existuje mnoho dôvodov na spúšťanie systemd v kontajneri, ako sú:
- Multiservisné kontajnery – mnohí chcú preniesť svoje multiservisné aplikácie z virtuálnych strojov a spúšťať ich v kontajneroch. Určite by bolo lepšie tieto aplikácie rozdeliť na mikroslužby, ale nie každý to zatiaľ zvláda alebo jednoducho nemá čas. Preto má zmysel spúšťať také aplikácie ako služby, ktoré sú spúšťané systemd z jednotkových súborov.
- Jednotkové súbory Systemd – väčšina aplikácií bežiacich v kontajneroch je zostavená z kódu, ktorý bol predtým spúšťaný na virtuálnych alebo fyzických strojoch. Tieto aplikácie majú jednotkový súbor, ktorý bol napísaný pre tieto aplikácie a vie, ako ich spustiť. Preto by sa služby mali predsa len spúšťať pomocou podporovaných metód, a nie hackovaním vlastnej init služby.
- Systemd je správca procesov. Zvláda správu služieb (ukončuje, reštartuje služby alebo sa zbavuje zombie procesov) lepšie ako akýkoľvek iný nástroj.
Zároveň existencia mnohých dôvodov na to, aby sa systemd v kontajneroch nespúšťal. Hlavný spočíva v tom, že systemd/journald kontroluje výstupy kontajnerov, a nástroje ako alebo predpokladajú, že kontajnery budú zapisovať logy priamo do stdout a stderr. Preto, ak plánujete spravovať kontajnery prostredníctvom nástrojov na orchestráciu, ako sú uvedené vyššie, mali by ste dôkladne zvážiť otázku využívania kontajnerov založených na systemd. Okrem toho boli vývojári Docker a Moby často dôrazne proti používaniu systemd v kontajneroch.
Príchod Podman’a
S radosťou oznamujeme, že situácia sa konečne posunula z mŕtveho bodu. Tím zodpovedný za spúšťanie kontajnerov v Red Hat sa rozhodol vyvinúť . Dostal názov a ponúka rovnaké rozhranie príkazového riadku (CLI) ako Docker. A takmer všetky príkazy Dockeru je možné použiť aj v Podman. Často organizujeme semináre, ktoré sa teraz nazývajú , a prvý snímok vyzýva na to, aby ste napísali: alias docker=podman.
Mnohí to naozaj robia.
My s naším Podmanom nie sme proti kontajnrom založeným na systemd. Veď systemd je najčastejšie používaný ako init-subsystem v Linuxe, a nedať mu možnosť normálne fungovať v kontajneroch znamená ignorovať spôsob, akým tisícky ľudí zvyknú spúšťať kontajnery.
Podman vie, čo robiť, aby systemd normálne fungoval v kontajneri. Potrebuje veci ako montovanie tmpfs na /run a /tmp. Má rád, keď je zapnuté „kontajnerové“ prostredie, a očakáva zápisové práva do svojej časti adresára cgroup a do priečinka /var/log/journald.
Pri spustení kontajnera, v ktorom je prvou príkazom init alebo systemd, Podman automaticky nastavuje tmpfs a Cgroups, aby spustenie systemd prebehlo bez problémov. Aby sa taký automatický režim spúšťania zakázal, používa sa voľba --systemd=false. Majte na pamäti, že Podman používa režim systemd iba vtedy, keď vidí, že sa má vykonať príkaz systemd alebo init.
Tu je ukážka z manuálu:
man podman run
…--systemd=true|false
Spúšťanie kontajnera v režime systemd. Predvolene je zapnuté.
Ak sa v kontajneri vykonáva príkaz systemd alebo init, Podman nastaví montážne body tmpfs v nasledujúcich adresároch:
/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal
Taktiež ako signál na zastavenie sa predvolene použije SIGRTMIN+3.
To všetko umožňuje systemd fungovať v uzavretom kontajneri bez akýchkoľvek úprav.
POZNÁMKA: systemd sa pokúša vykonať zápis do súborového systému cgroup. Avšak SELinux predvolene neumožňuje kontajnerom to robiť. Aby ste umožnili zápis, zapnite logickú voľbu container_manage_cgroup:
setsebool -P container_manage_cgroup true
Teraz sa pozrime, ako vyzerá Dockerfile na spustenie systemd v kontajneri pri použití Podman:
# cat Dockerfile
FROM fedora
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd
EXPOSE 80
CMD [ "/sbin/init" ]
A to je všetko.
Teraz skladáme kontajner:
# podman build -t systemd .
Povieme SELinux, aby dovolil systemd modifikovať konfiguráciu Cgroups:
# setsebool -P container_manage_cgroup true
Mnohí, mimochodom, zabúdajú na tento krok. Našťastie je potrebné to urobiť len raz a nastavenie sa zachová aj po reštartovaní systému.
Teraz jednoducho spustíme kontajner:
# 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.
Hotovo, služba sa spustila a funguje:
$ curl localhost
<html xml_lang="en" lang="en">
…
</html>
POZNÁMKA: Nepokúšajte sa to zopakovať na Dockeri! Tam sú stále potrebné akrobatické kúsky, aby ste spustili takýto druh kontajnerov cez démona. (Bude potrebné ďalšie pole a balíky, aby to všetko bezproblémovo fungovalo v Dockeri, alebo budete musieť spustiť v privilegovanom kontajneri. Podrobnosti nájdete v .)
Ešte pár skvelých vecí o Podman a systemd
Podman funguje lepšie ako Docker v jednotkových súboroch systemd
Ak je potrebné spustiť kontajnery pri spustení systému, stačí vložiť príslušné príkazy Podman do jednotkového súboru systemd, ten spustí službu a bude ju monitorovať. Podman používa štandardný model vetvenia pri vykonávaní (fork-exec). Inými slovami, kontajnerové procesy sú potomkami procesu Podman, takže systemd ich môže ľahko monitorovať.
Docker používa model klient-server, a príkazy CLI Dockeru je tiež možné umiestniť priamo do jednotkového súboru. Avšak po tom, čo sa klient Docker pripojí k démona Docker, stáva sa (klient) len ďalším procesom, ktorý spracováva stdin a stdout. Systemd na druhej strane nemá tušenia o spojení medzi klientom Docker a kontajnerom, ktorý beží pod správou démona Docker, a preto v rámci tohto modelu systemd nemôže zásadne monitorovať službu.
Aktivácia systemd cez socket
Podman správne spracováva aktiváciu cez socket. Keďže Podman používa model fork-exec, dokáže prenášať socket svojim podradeným kontajnerovým procesom. Docker to nedokáže, pretože používa model klient-server.
Služba varlink, ktorú Podman využíva na interakciu vzdialených klientov s kontajnermi, sa v skutočnosti aktivuje cez socket. Balík cockpit-podman, napísaný v Node.js a súčasť projektu cockpit, umožňuje používateľom interagovať s kontajnermi Podman prostredníctvom webového rozhrania. Webový démon, na ktorom sa spúšta cockpit-podman, posiela správy na varlink-socket, ktorý počúva systemd. Následne systemd aktivuje program Podman na prijímanie správ a začiatok správy kontajnerov. Aktivácia systemd prostredníctvom socketu umožňuje obísť neustále bežiaci démon pri realizácii vzdialených API.
Okrem toho vyvíjame ďalšieho klienta pre Podman s názvom podman-remote, ktorý implementuje rovnaké Podman CLI, ale vyvoláva varlink na spustenie kontajnerov. Podman-remote môže pracovať na SSH reláciách, čo umožňuje bezpečne interagovať s kontajnermi na rôznych strojoch. V priebehu času plánujeme využiť podman-remote na podporu MacOS a Windows spolu s Linuxom, aby vývojári na týchto platformách mohli spustiť virtuálny počítač Linux so spusteným Podman varlink a mali kompletný pocit, že kontajnery bežia na lokálnom stroji.
SD_NOTIFY
Systemd umožňuje odložiť spustenie pomocných služieb až do momentu, keď sa spustí potrebná kontajnerizovaná služba. Podman môže preniesť socket SD_NOTIFY do kontajnerizovanej služby, aby táto služba upozornila systemd na svoju pripravenosť na prácu. A opäť Docker, ktorý používa model klient-server, to takto nedokáže.
Plány
Plánujeme pridať príkaz podman generate systemd CONTAINERID, ktorý vygeneruje unit súbor systemd na správu konkrétneho zadaného kontajnera. To by malo fungovať ako v root-, tak aj v rootless režimoch pre neprivilegované kontajnery. Dokonca sme videli požiadavku na vytvorenie OCI-kompatibilného prostredia spúšťania systemd-nspawn.
Záver
Spúšťanie systemd v kontajneri je vcelku pochopiteľná potreba. A vďaka Podman máme konečne prostredie na spúšťanie kontajnerov, ktoré nie je v konflikte so systemd, ale umožňuje jeho jednoduché využívanie.
Zdroj: habr.com
