Tému používania systemd v kontajneroch sledujeme už dlhšie. V roku 2014 náš bezpečnostný inžinier Daniel Walsh napísal článok
V tomto článku si ukážeme, čo sa časom zmenilo a ako nám v tejto veci môže pomôcť Podman.
Existuje mnoho dôvodov, prečo spustiť systemd v kontajneri, ako napríklad:
- Viacúčelové kontajnery – veľa ľudí chce stiahnuť svoje multiservisné aplikácie z virtuálnych strojov a spustiť ich v kontajneroch. Samozrejme, bolo by lepšie rozdeliť takéto aplikácie do mikroslužieb, ale nie každý vie, ako to urobiť, alebo jednoducho nemá čas. Preto má spustenie takýchto aplikácií, ako sú služby spúšťané systémom systemd zo súborov jednotiek, dokonalý zmysel.
- Systemd Unit Files – Väčšina aplikácií spustených v kontajneroch je vytvorená z kódu, ktorý predtým bežal na virtuálnych alebo fyzických počítačoch. Tieto aplikácie majú jednotkový súbor, ktorý bol napísaný pre tieto aplikácie a rozumie tomu, ako by sa mali spúšťať. Stále je teda lepšie spúšťať služby pomocou podporovaných metód, než hackovať vlastnú init službu.
- Systemd je manažér procesov. Spravuje služby (vypína, reštartuje služby alebo zabíja procesy zombie) lepšie ako ktorýkoľvek iný nástroj.
To znamená, že existuje veľa dôvodov, prečo nespúšťať systemd v kontajneroch. Hlavným je, že systemd/journald riadi výstup kontajnerov a podobných nástrojov
Príchod Podmana
S radosťou vám oznamujeme, že situácia sa konečne pohla. Tím zodpovedný za prevádzku kontajnerov v Red Hat sa rozhodol vyvinúť
Mnoho ľudí to robí.
Môj Podman a ja nie sme v žiadnom prípade proti kontajnerom založeným na systemd. Koniec koncov, Systemd je najbežnejšie používaný linuxový init subsystém a neumožniť mu správne fungovať v kontajneroch znamená ignorovať, ako sú tisíce ľudí zvyknuté na spúšťanie kontajnerov.
Podman vie, čo robiť, aby systemd v kontajneri správne fungoval. Potrebuje veci ako pripojenie tmpfs na /run a /tmp. Má rada povolené „kontajnerované“ prostredie a očakáva oprávnenia na zápis do svojej časti adresára cgroup a do priečinka /var/log/journald.
Keď spustíte kontajner, v ktorom je prvý príkaz init alebo systemd, Podman automaticky nakonfiguruje tmpfs a Cgroups, aby sa zabezpečilo, že systemd sa spustí bez problémov. Ak chcete zablokovať tento režim automatického spustenia, použite možnosť --systemd=false. Upozorňujeme, že Podman používa režim systemd iba vtedy, keď vidí, že potrebuje spustiť príkaz systemd alebo init.
Tu je úryvok z manuálu:
muž podman beh
...–systemd=true|false
Spustenie kontajnera v režime systemd. Predvolene povolené.
Ak spustíte príkaz systemd alebo init v kontajneri, Podman nakonfiguruje body pripojenia tmpfs v nasledujúcich adresároch:
/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal
Predvolený signál zastavenia bude tiež SIGRTMIN+3.
To všetko umožňuje systemd bežať v uzavretom kontajneri bez akýchkoľvek úprav.
POZNÁMKA: systemd sa pokúša zapisovať do súborového systému cgroup. SELinux však v predvolenom nastavení bráni kontajnerom. Ak chcete povoliť zápis, povoľte boolovský parameter container_manage_cgroup:
setsebool -P container_manage_cgroup true
Teraz sa pozrite, ako Dockerfile vyzerá pri spustení systemd v kontajneri pomocou Podman:
# cat Dockerfile
FROM fedora
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd
EXPOSE 80
CMD [ "/sbin/init" ]
To je všetko.
Teraz zostavíme kontajner:
# podman build -t systemd .
Hovoríme SELinuxu, aby umožnil systemd upraviť konfiguráciu Cgroups:
# setsebool -P container_manage_cgroup true
Mimochodom, veľa ľudí na tento krok zabúda. Našťastie to stačí urobiť len raz a nastavenie sa uloží po reštarte systému.
Teraz len 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.
To je všetko, služba je spustená:
$ curl localhost
<html xml_lang="en" lang="en">
…
</html>
POZNÁMKA: Neskúšajte to na Docker! Stále musíte tancovať s tamburínou, aby ste mohli spustiť tento druh kontajnerov cez démona. (Na bezproblémové fungovanie v Dockeri budú potrebné ďalšie polia a balíky. Podrobnosti nájdete v časti
Pár ďalších skvelých vecí o Podmanovi a systemd
Podman funguje lepšie ako Docker v súboroch jednotiek systemd
Ak je potrebné spustiť kontajnery pri zavádzaní systému, potom môžete jednoducho vložiť príslušné príkazy Podman do súboru systemd unit, čím sa služba spustí a bude ju monitorovať. Podman používa štandardný model 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 Docker je možné umiestniť aj priamo do súboru jednotky. Akonáhle sa však klient Docker pripojí k démonovi Docker, stane sa (klient) len ďalším procesom, ktorý spracováva štandardy stdin a stdout. Systemd zase netuší o prepojení medzi klientom Docker a kontajnerom, ktorý beží pod kontrolou démona Docker, a preto v rámci tohto modelu systemd zásadne nemôže službu monitorovať.
Aktivácia systému cez zásuvku
Podman zvláda aktiváciu cez zásuvku správne. Pretože Podman používa model fork-exec, môže preposlať soket svojim podriadeným kontajnerovým procesom. Docker to nedokáže, pretože používa model klient-server.
Služba varlink, ktorú Podman používa na komunikáciu so vzdialenými klientmi do kontajnerov, je v skutočnosti aktivovaná cez soket. Balík kokpit-podman napísaný v Node.js a súčasť projektu kokpitu umožňuje ľuďom interakciu s kontajnermi Podman prostredníctvom webového rozhrania. Webový démon, na ktorom beží cockpit-podman, posiela správy do varlink socketu, ktorý systemd počúva. Systemd potom aktivuje program Podman, aby mohol prijímať správy a začať spravovať kontajnery. Aktivácia systemd cez soket eliminuje potrebu neustále spusteného démona pri implementácii vzdialených API.
Okrem toho vyvíjame ďalšieho klienta Podman s názvom podman-remote, ktorý implementuje rovnaké CLI Podman, ale na spustenie kontajnerov volá varlink. Podman-remote môže bežať nad reláciami SSH, čo vám umožňuje bezpečne interagovať s kontajnermi na rôznych počítačoch. Postupom času plánujeme umožniť podman-remote podporovať MacOS a Windows spolu s Linuxom, aby vývojári na týchto platformách mohli spustiť linuxový virtuálny stroj so spusteným Podman varlink a mali plnú skúsenosť, že kontajnery bežia na lokálnom počítači.
SD_NOTIFY
Systemd vám umožňuje odložiť spustenie pomocných služieb, kým sa nezačne kontajnerová služba, ktorú vyžadujú. Podman môže odovzdať zásuvku SD_NOTIFY kontajnerovej službe, aby služba oznámila systemd, že je pripravená na prevádzku. A opäť, Docker, ktorý používa model klient-server, to nedokáže.
V plánoch
Plánujeme pridať príkaz podman generovať systemd CONTAINERID, ktorý vygeneruje súbor systemd unit na správu konkrétneho špecifikovaného kontajnera. Toto by malo fungovať v režime root aj bez koreňov pre neprivilegované kontajnery. Dokonca sme videli požiadavku na runtime systemd-nspawn kompatibilné s OCI.
Záver
Spustenie systemd v kontajneri je pochopiteľná potreba. A vďaka Podmanovi máme konečne runtime kontajnera, ktorý nie je v konflikte so systemd, ale uľahčuje jeho používanie.
Zdroj: hab.com