Systém běžící v kontejneru

Téma používání systemd v kontejnerech sledujeme již delší dobu. V roce 2014 napsal náš bezpečnostní inženýr Daniel Walsh článek Spuštění systemd v kontejneru Docker, ao pár let později - další, který se jmenoval Spuštění systemd v neprivilegovaném kontejneru, ve kterém uvedl, že se situace příliš nezlepšila. Konkrétně napsal, že „bohužel, dokonce i o dva roky později, když zadáte do googlu „Docker system“, první věc, která se objeví, je jeho stejný starý článek. Je tedy čas něco změnit." Navíc jsme o tom už mluvili konflikt mezi Dockerem a vývojáři systemd.

Systém běžící v kontejneru

V tomto článku si ukážeme, co se v průběhu času změnilo a jak nám v této věci může Podman pomoci.

Existuje mnoho důvodů, proč spustit systemd uvnitř kontejneru, například:

  1. Víceúčelové kontejnery – mnoho lidí chce vytáhnout své multiservisní aplikace z virtuálních strojů a spustit je v kontejnerech. Bylo by samozřejmě lepší takové aplikace rozdělit na mikroslužby, ale ne každý to zatím umí nebo na to prostě nemá čas. Spouštění takových aplikací, jako jsou služby spouštěné systemd ze souborů jednotek, proto dává dokonalý smysl.
  2. Systemd Unit Files – Většina aplikací běžících uvnitř kontejnerů je vytvořena z kódu, který dříve běžel na virtuálních nebo fyzických počítačích. Tyto aplikace mají soubor jednotky, který byl napsán pro tyto aplikace a rozumí tomu, jak by měly být spuštěny. Stále je tedy lepší spouštět služby pomocí podporovaných metod, než hackovat vlastní init službu.
  3. Systemd je správce procesů. Spravuje služby (vypíná, restartuje služby nebo zabíjí procesy zombie) lépe než jakýkoli jiný nástroj.

To znamená, že existuje mnoho důvodů, proč nespouštět systemd v kontejnerech. Hlavní je, že systemd/journald řídí výstup kontejnerů a nástrojů jako Kubernetes nebo OpenShift očekávejte, že kontejnery budou zapisovat log přímo do stdout a stderr. Pokud tedy budete spravovat kontejnery pomocí nástrojů pro orchestraci, jako jsou ty výše uvedené, měli byste vážně zvážit použití kontejnerů založených na systemd. Navíc vývojáři Docker a Moby byli často silně proti používání systemd v kontejnerech.

Příchod Podmana

S radostí oznamujeme, že se situace konečně pohnula kupředu. Tým zodpovědný za provoz kontejnerů ve společnosti Red Hat se rozhodl vyvinout svůj vlastní kontejnerový motor. Dostal jméno Podman a nabízí stejné rozhraní příkazového řádku (CLI) jako Docker. A téměř všechny příkazy Dockeru lze v Podmanu použít stejným způsobem. Často pořádáme semináře, které se dnes nazývají Změna Dockera na Podmana hned první snímek vyžaduje zápis: alias docker=podman.

Mnoho lidí to dělá.

Můj Podman a já nejsme v žádném případě proti kontejnerům založeným na systemd. Ostatně Systemd je nejběžněji používaný linuxový init subsystém a neumožnit mu správně fungovat v kontejnerech znamená ignorovat, jak jsou tisíce lidí zvyklé spouštět kontejnery.

Podman ví, co dělat, aby systemd v kontejneru fungoval správně. Potřebuje věci jako připojení tmpfs na /run a /tmp. Ráda má povolené „kontejnerované“ prostředí a očekává oprávnění k zápisu do své části adresáře cgroup a do složky /var/log/journald.

Když spustíte kontejner, ve kterém je první příkaz init nebo systemd, Podman automaticky nakonfiguruje tmpfs a Cgroups, aby zajistil, že systemd se spustí bez problémů. Chcete-li zablokovat tento režim automatického spouštění, použijte volbu --systemd=false. Upozorňujeme, že Podman používá režim systemd pouze tehdy, když vidí, že potřebuje spustit příkaz systemd nebo init.

Zde je výňatek z manuálu:

muž podman běh
...

–systemd=true|false

Spuštění kontejneru v režimu systemd. Ve výchozím nastavení povoleno.

Pokud spustíte příkaz systemd nebo init uvnitř kontejneru, Podman nakonfiguruje přípojné body tmpfs v následujících adresářích:

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

Také výchozí signál zastavení bude SIGRTMIN+3.

To vše umožňuje systemd běžet v uzavřeném kontejneru bez jakýchkoliv úprav.

POZNÁMKA: systemd se pokouší zapisovat do souborového systému cgroup. SELinux však ve výchozím nastavení zabraňuje kontejnerům, aby to dělaly. Chcete-li povolit zápis, povolte booleovský parametr container_manage_cgroup:

setsebool -P container_manage_cgroup true

Nyní se podívejte, jak vypadá Dockerfile pro spuštění systemd v kontejneru pomocí Podman:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

To je všechno.

Nyní sestavíme kontejner:

# podman build -t systemd .

Řekneme SELinuxu, aby umožnil systemd upravit konfiguraci Cgroups:

# setsebool -P container_manage_cgroup true

Mimochodem, mnoho lidí na tento krok zapomíná. Naštěstí to stačí udělat jen jednou a po restartu systému se nastavení uloží.

Nyní spustíme kontejner:

# 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še, služba je spuštěna:

$ curl localhost

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

…

</html>

POZNÁMKA: Toto na Dockeru nezkoušejte! Stále musíte tančit s tamburínou, abyste mohli spustit tyto druhy kontejnerů prostřednictvím démona. (Aby to vše v Dockeru bezproblémově fungovalo, budou vyžadována další pole a balíčky, nebo bude nutné spustit v privilegovaném kontejneru. Podrobnosti viz článek.)

Pár dalších skvělých věcí o Podmanovi a systemd

Podman funguje lépe než Docker v souborech jednotek systemd

Pokud je potřeba při startu systému spustit kontejnery, pak můžete jednoduše vložit příslušné příkazy Podman do souboru systemd unit, čímž se služba spustí a bude ji monitorovat. Podman používá standardní model fork-exec. Jinými slovy, kontejnerové procesy jsou potomky procesu Podman, takže je systemd může snadno sledovat.

Docker používá model klient-server a příkazy CLI Dockeru lze také umístit přímo do souboru jednotky. Jakmile se však klient Docker připojí k démonu Docker, stane se (klient) pouze dalším procesem, který zpracovává stdin a stdout. Systemd zase nemá ponětí o spojení mezi klientem Docker a kontejnerem, který běží pod kontrolou démona Docker, a proto v rámci tohoto modelu systemd zásadně nemůže službu monitorovat.

Aktivace systému přes zásuvku

Podman zvládá aktivaci přes zásuvku správně. Protože Podman používá model fork-exec, může přeposílat soket svým podřízeným kontejnerovým procesům. Docker to nemůže udělat, protože používá model klient-server.

Služba varlink, kterou Podman používá ke komunikaci se vzdálenými klienty do kontejnerů, je ve skutečnosti aktivována přes soket. Balíček cockpit-podman, napsaný v Node.js a součást projektu cockpit, umožňuje lidem komunikovat s kontejnery Podman prostřednictvím webového rozhraní. Webový démon, na kterém běží cockpit-podman, posílá zprávy do varlinkového soketu, který systemd poslouchá. Systemd poté aktivuje program Podman, aby mohl přijímat zprávy a začít spravovat kontejnery. Aktivace systemd přes soket eliminuje potřebu neustále běžícího démona při implementaci vzdálených API.

Kromě toho vyvíjíme dalšího klienta Podman s názvem podman-remote, který implementuje stejné rozhraní Podman CLI, ale ke spuštění kontejnerů volá varlink. Podman-remote může běžet nad relací SSH, což vám umožní bezpečně komunikovat s kontejnery na různých počítačích. Postupem času plánujeme umožnit podman-remote podporovat MacOS a Windows spolu s Linuxem, aby vývojáři na těchto platformách mohli provozovat linuxový virtuální stroj se spuštěným Podman varlink a měli plnou zkušenost, že kontejnery běží na místním počítači.

SD_NOTIFY

Systemd vám umožňuje odložit spuštění pomocných služeb, dokud nezačne kontejnerová služba, kterou vyžadují. Podman může předat SD_NOTIFY socket kontejnerové službě, aby služba oznámila systemd, že je připravena k provozu. A opět Docker, který používá model klient-server, to neumí.

V plánech

Plánujeme přidat příkaz podman generation systemd CONTAINERID, který vygeneruje soubor systemd unit pro správu konkrétního specifikovaného kontejneru. To by mělo fungovat v režimu root i rootless pro neprivilegované kontejnery. Dokonce jsme viděli požadavek na runtime systemd-nspawn kompatibilní s OCI.

Závěr

Spuštění systemd v kontejneru je pochopitelná potřeba. A díky Podmanovi máme konečně runtime kontejneru, který není v konfliktu se systemd, ale usnadňuje jeho použití.

Zdroj: www.habr.com

Přidat komentář