Systém beží v kontajneri

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 Spustený systemd v rámci kontajnera Dockera o pár rokov neskôr - ďalší, ktorý sa nazýval Systém beží v neprivilegovanom kontajneri, v ktorom uviedol, že situácia sa príliš nezlepšila. Najmä napísal, že „bohužiaľ, aj o dva roky neskôr, ak zadáte do googlu „Docker system“, prvá vec, ktorá sa objaví, je jeho rovnaký starý článok. Takže je čas niečo zmeniť." Okrem toho sme už hovorili o konflikt medzi Dockerom a vývojármi systemd.

Systém beží v kontajneri

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:

  1. 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.
  2. 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.
  3. 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 Kubernetes alebo openshift očakávajte, že kontajnery budú zapisovať protokol priamo do stdout a stderr. Preto, ak sa chystáte spravovať kontajnery pomocou nástrojov na orchestráciu, ako sú uvedené vyššie, mali by ste vážne zvážiť použitie kontajnerov založených na systemd. Okrem toho vývojári Docker a Moby boli často silne proti používaniu systemd v kontajneroch.

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úť svoj vlastný kontajnerový motor. Dostal meno podmaní a ponúka rovnaké rozhranie príkazového riadka (CLI) ako Docker. A takmer všetky príkazy Dockera možno v Podmane použiť rovnakým spôsobom. Často robíme semináre, ktoré sú dnes tzv Zmena Dockera na Podmanaa hneď prvá snímka vyžaduje napísanie: alias docker=podman.

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 článok.)

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

Pridať komentár