Már régóta figyeljük a systemd konténerben való használatának témáját. Már 2014-ben a biztonsági mérnökünk, Daniel Walsh, írt egy cikket , majd néhány évvel később egy másikat, amelynek címe volt , amelyben megállapította, hogy a helyzet nem sokat javult. Különösen azt írta, hogy "sajnos, két évvel később, ha rákeresünk a 'Docker system' kifejezésre, az első, ami felbukkan, az a régi cikk. Azt jelenti, hogy itt az ideje valamit változtatni". Ezen kívül már beszéltünk a .
Ezért a cikkben megmutatjuk, mi változott azóta és hogyan segíthet nekünk ebben a kérdésben a Podman.
Rengeteg oka van annak, hogy a systemd-t konténerben futtassuk, ilyenek például:
- Több szolgáltatású konténerek – sokan szeretnék a több szolgáltatásból álló alkalmazásaikat virtuális gépekből eltávolítani és konténerekben futtatni. Természetesen jobb lenne, ha ilyen alkalmazásokat mikroszolgáltatásokra bontanánk, de ezt még nem mindenki tudja, vagy egyszerűen nincs rá ideje. Ezért ezeknek az alkalmazásoknak a systemd révén egységfájlokból való futtatása teljesen értelmes.
- Systemd egységfájlok – a konténerben futó legtöbb alkalmazás kódja olyan programokból áll, amelyeket korábban virtuális vagy fizikai gépeken futtattak. Ezeknek az alkalmazásoknak van egy egységfájlja, amelyet ezekhez az alkalmazásokhoz írtak és tudja, hogyan kell azokat elindítani. Ezért a szolgáltatásokat jobb támogatott módszerekkel elindítani, nem pedig saját init-rendszerük feltörésével.
- A systemd egy folyamatszabályozó. Jobban kezeli a szolgáltatásokat (leállítja, újraindítja a szolgáltatásokat vagy megöli a zombiként működő folyamatokat), mint bármely más eszköz.
Ugyanakkor számos ok van arra is, hogy ne futtassuk a systemd-t konténerekben. A fő ok az, hogy a systemd/journald ellenőrzi a konténerek kimenetét, míg olyan eszközök, mint a vagy arra számítanak, hogy a konténerek közvetlenül a stdout és stderr-ba írnak naplózást. Ezért, ha a konténereket a fent említett orchestration eszközök révén szeretnék kezelni, komolyan el kell gondolkodni a systemd alapú konténerek használatán. Ezen kívül a Docker és Moby fejlesztői gyakran ellenezték a systemd használatát a konténerekben.
A Podman megjelenése
Örömmel értesítjük, hogy a helyzet végre elmozdult a holtpontról. A Red Hat csapata, amely a konténerek indításáért felel, úgy döntött, hogy kifejleszti . A neve , és ugyanazt a parancssori felületet (CLI) kínálja, mint a Docker. Szinte minden Docker parancsot pontosan ugyanúgy lehet használni a Podman-nal. Gyakran tartunk workshopokat, amelyek mostantól a következő nevet viselik: , és az első diája arra buzdít, hogy írja be: alias docker=podman.
Sokan ezt meg is teszik.
A Podman esetében semmilyen ellenséges érzésünk sincs a systemd alapú konténerekkel szemben. A Systemd gyakran a Linux init-alrendszereként működik, és ha nem hagyjuk, hogy normálisan működjön a konténereken belül, az figyelmen kívül hagyja, ahogyan ezrek szokták indítani a konténereket.
A Podman tudja, mit kell tenni annak érdekében, hogy a systemd normálisan működjön a konténerben. Számára szükséges dolgok például a tmpfs csatolása a /run és /tmp mappákhoz. Szereti, ha a "konténeres" környezet be van kapcsolva, és várja a írási jogokat a cgroup mappájában és a /var/log/journald mappában.
Amikor olyan konténert indítunk, amelyben az első parancs az init vagy a systemd, a Podman automatikusan beállítja a tmpfs-t és a Cgroups-ot, hogy a systemd indítása problémamentes legyen. Ezt az automatikus indítást a —systemd=false opcióval lehet letiltani. Vegye figyelembe, hogy a Podman csak akkor használja a systemd módot, ha arra látja, hogy systemd vagy init parancsot kell végrehajtani.
Íme egy részlet a kézikönyvből:
man podman run
…–systemd=true|false
Konténer indítása systemd módban. Alapértelmezés szerint engedélyezve van.
Ha a konténerben systemd vagy init parancs fut, a Podman beállítja a tmpfs csatolási pontjait a következő mappákban:
/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal
A leállítási jelzéshez alapértelmezésként a SIGRTMIN+3 jelzés használható.
Mindez lehetővé teszi a systemd működését egy zárt konténerben bármilyen módosítás nélkül.
MEGJEGYZÉS: a systemd megpróbál írni a cgroup fájlrendszerbe. Azonban az SELinux alapértelmezés szerint megtiltja a konténerek számára ezt. A írás engedélyezéséhez kapcsolja be a container_manage_cgroup logikai paramétert:
setsebool -P container_manage_cgroup true
Most nézzük meg, hogyan néz ki a Dockerfile a systemd konténerben történő indításához a Podman használatával:
# cat Dockerfile
FROM fedora
RUN dnf -y install httpd; dnf clean all; systemctl enable httpd
EXPOSE 80
CMD [ "/sbin/init" ]
Ennyi.
Most összegyűjtjük a konténert:
# podman build -t systemd .
Kérjük, engedélyezze az SELinux-t, hogy a systemd módosíthassa a Cgroups konfigurációját:
# setsebool -P container_manage_cgroup true
Sokan elfelejtik ezt a lépést. Szerencsére ezt csupán egyszer kell elvégezni, és a beállítások megmaradnak a rendszer újraindítása után.
Most egyszerűen elindítjuk a konténert:
# 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.
Kész, a szolgáltatás elindult és működik:
$ curl localhost
<html xml_lang="en" lang="en">
…
</html>
MEGJEGYZÉS: Ne próbálja meg ezt Docker-en! Ott továbbra is szükség van némi „bábozásra”, hogy ilyen típusú konténereket futtasson a démonon keresztül. (További mezőkre és csomagokra lesz szükség ahhoz, hogy mindez zökkenőmentesen működjön Docker alatt, vagy privilegizált konténerben kell futtatni. Részletekért lásd: .)
Még pár érdekes dolog a Podman-ről és a systemd-ről
A Podman jobban működik a Docker-nél a systemd egységfájlokban
Ha a konténereket a rendszer indításakor kell futtatni, egyszerűen be lehet illeszteni a megfelelő Podman parancsokat a systemd egységfájlba, amely elindítja a szolgáltatást és figyelemmel kíséri azt. A Podman a standard fork-exec végrehajtási modellt használja. Más szóval, a konténerfolyamatok alfolyamatok a Podman folyamatához képest, így a systemd egyszerűen figyelemmel tudja kísérni őket.
A Docker kliens-szerver modellt használ, és a Docker CLI parancsokat közvetlenül a egységfájlban is elhelyezheti. Azonban amikor a Docker kliens csatlakozik a Docker démonhoz, az (a kliens) egyszerűen csak egy újabb folyamat lesz, amely a stdin-t és stdout-t kezeli. A systemd viszont nem tud a Docker kliens és a Docker démon alá tartozó konténer közötti kapcsolatról, és ezért ebben a modellben a systemd alapvetően nem tudja figyelemmel kísérni a szolgáltatást.
A systemd aktiválása socket-en keresztül
A Podman megfelelően kezeli a socket alapú aktiválást. Mivel a Podman fork-exec modellt alkalmaz, képes a socketet átkonvertálni a gyermek konténerfolyataihoz. A Docker nem tudja ezt, mert kliens-szerver modellt használ.
A varlink szolgáltatás, amelyet a Podman használ a távoli kliensek kommunikációjához a tartályokkal, valójában socketen keresztül aktiválódik. A cockpit-podman csomag, amely Node.js-ben készült és a cockpit projekt része, lehetővé teszi, hogy az emberek a Podman konténerekkel webes felületen keresztül lépjenek kapcsolatba. A webdémon, amelyen a cockpit-podman fut, üzeneteket küld a varlink socketre, amelyet a systemd figyel. Ezt követően a systemd aktiválja a Podman programot az üzenetek fogadására és a konténerek kezelésének megkezdésére. A systemd socket általi aktiválása lehetővé teszi, hogy elkerüljük egy állandóan futó démon telepítését a távoli API-k implementálásakor.
Ezen kívül egy másik klienst is fejlesztünk a Podman számára, amelyet podman-remote-nak hívnak. Ez ugyanazt a Podman CLI-t valósítja meg, de varlinket hív a tartályok indításához. A podman-remote SSH-szekciók felett képes működni, lehetővé téve a biztonságos interakciót a különböző gépeken található tartályokkal. Idővel a podman-remote támogatást kap MacOS és Windows operációs rendszerekhez a Linux mellett, hogy a fejlesztők ezeken a platformokon Linux virtuális gépet tudjanak indítani a működő Podman varlink-kel, és teljes illúziójuk legyen arról, hogy a konténerek helyben futnak.
SD_NOTIFY
A Systemd lehetővé teszi, hogy a segédszolgáltatások indítását elhalasszuk addig, amíg nem indul el a szükséges tartályozott szolgáltatás. A Podman képes átadni az SD_NOTIFY socketet a tartályozott szolgáltatásnak, hogy értesítse a systemd-t a működőképességéről. Ismételten a Docker, amely kliens-szerver modellt használ, ezt nem tudja megvalósítani.
Tervekben
Tervezünk egy podman generate systemd CONTAINERID parancsot, amely systemd egységfájlt generál egy adott tartály kezeléséhez. Ennek a funkciónak mind a root, mind a rootless üzemmódban működnie kell a nem privilégizált konténerekhez. Még láttunk egy kérdést az OCI-kompatibilis systemd-nspawn futtatási környezet létrehozására.
Zárás
A systemd futtatása egy konténerben teljesen érthető igény. A Podman segítségével végre van egy olyan indító környezetünk, amely nem áll ellentétben a systemd-vel, hanem megkönnyíti annak használatát.
Forrás: habr.com
