Zagonimo systemd znotraj kontejnerja

Že dolgo spremljamo temo uporabe systemd v kontejnerjih. Še leta 2014 je naš inženir za varnost Daniel Walsh napisal članek Zagon systemd v Docker kontejnerju, nato pa nekaj let kasneje še en, ki se je imenoval Zagon systemd v neprivilegiranem kontejnerju, v katerem je ugotovil, da se situacija pravzaprav ni bistveno izboljšala. Natančneje je zapisal, da "žal, tudi dve leti kasneje, če poiščete 'Docker system', se na prvem mestu še vedno pojavi njegov star članek. Čas je, da nekaj spremenimo". Poleg tega smo že nekako obravnavali konflikt med razvijalci Dockerja in systemd.

Zagonimo systemd znotraj kontejnerja

V tem članku bomo pokazali, kaj se je spremenilo v preteklem času in kako nam lahko pri tem pomaga Podman.

Obstaja veliko razlogov za zagon systemd znotraj kontejnerja, kot so:

  1. Večservisni kontejnerji – mnogi želijo svoje večservisne aplikacije prenesti iz virtualnih strojev v kontejnerje. Seveda bi bilo najbolje te aplikacije razdeliti na mikrostoritve, a to znajo le redki ali pa preprosto nimajo časa. Zato ima smisel zagon takih aplikacij v obliki storitev, ki jih zažene systemd iz enotnih datotek.
  2. Enotne datoteke systemd – večina aplikacij, ki delujejo znotraj kontejnerjev, je sestavljena iz kode, ki je bila prej zagnana na virtualnih ali fizičnih strojih. Te aplikacije imajo enotno datoteko, ki je bila napisana za te aplikacije in razume, kako jih treba zagnati. Zato je bolje, da storitve zaženemo s pomočjo podprtih metod in ne da bi razdeli lastno init storitev.
  3. Systemd je upravljalec procesov. Upravlja s storitvami (ustavi, znova zažene storitve ali ubija zombie procese) bolje kot katero koli drugo orodje.

Obstajajo tudi številni razlogi, zakaj ne zagnati systemd v kontejnerjih. Glavni razlog je, da systemd/journald nadzira izhod kontejnerjev, medtem ko orodja kot Kubernetes ili OpenShift računajo na to, da bodo kontejnerji zapisovali dnevnike neposredno v stdout in stderr. Tako da, če nameravate upravljati s kontejnerji prek orodij za orkestracijo, kot so navedena zgoraj, je treba resno premisliti o uporabi kontejnerjev na osnovi systemd. Poleg tega so razvijalci Dockerja in Moby pogosto ostro nasprotovali uporabi systemd v kontejnerjih.

Prihod Podmana

Z veseljem sporočamo, da se je situacija končno premaknila z mrtve točke. Ekipa, odgovorna v Red Hatu za zagon kontejnerjev, je sklenila razviti svoj lasten kontejnerski motor. Ime je dobil Podman in ponuja enak vmesnik ukazne vrstice (CLI) kot Docker. In praktično vse Dockerjeve ukaze je mogoče uporabiti na enak način v Podmanu. Pogosto izvajamo delavnice, ki se zdaj imenujejo Zamenjamo Docker s Podmanom, prvotni diapozitiv pa poziva, naj zapišemo: alias docker=podman.

Mnogo jih to tudi stori.

Mi s svojim Podmanom v ničemer ne nasprotujemo kontejnerjem, temelječim na systemd. Saj se systemd pogosteje uporablja kot init podsystem Linuxa, in onemogočanje njegovega delovanja v kontejnerjih pomeni ignoriranje, kako tisoči ljudi navajajo zagon kontejnerjev.

Podman ve, kaj je treba narediti, da systemd normalno deluje v kontejnerju. Potrebuje stvari, kot so montaža tmpfs na /run in /tmp. Všeč ji je, ko je "kontejnersko" okolje aktivirano in čaka na pravice za zapis v svoj del imenika cgroup in v mapo /var/log/journald.

Ob zagonu kontejnerja, v katerem je prva ukazna vrstica init ali systemd, Podman samodejno nastavi tmpfs in cgroups, da se zagon systemd izvede brez težav. Da bi blokirali to samodejno zagnano modo, uporabite opcijo —systemd=false. Upoštevajte, da Podman uporablja način systemd le, ko vidi, da je treba izvesti ukaz systemd ali init.

Tukaj je izvleček iz priročnika:

man podman run
…

–systemd=true|false

Zagon kontejnerja v načinu systemd. Privzeto je vključen.

Če se znotraj kontejnerja izvede ukaz systemd ali init, bo Podman nastavil točke montaže tmpfs v naslednjih imenikih:

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

Prav tako se bo privzeto uporabil signal SIGRTMIN+3 za zaustavitev.

Vse to omogoča, da systemd deluje v zaprtem kontejnerju brez kakršnih koli modifikacij.

OPOMBA: systemd poskuša zapisovati v datotečni sistem cgroup. Vendar pa SELinux privzeto prepoveduje kontejnerjem to početi. Da bi omogočili zapis, omogočite logični parameter container_manage_cgroup:

setsebool -P container_manage_cgroup true

Zdaj si poglejmo, kako izgleda Dockerfile za zagon systemd v kontejnerju pri uporabi Podmana:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

To je to.

Zdaj zgradimo kontejner:

# podman build -t systemd .

Povejte SELinuxu, naj omogoči systemd modificirati konfiguracijo cgroups:

# setsebool -P container_manage_cgroup true

Mnogi, usput rečeno, zaboravljaju ovaj korak. Na sreću, potrebno je da ga napravite samo jednom i podešavanja će ostati sačuvana nakon ponovnog pokretanja sistema.

Sada samo pokrećemo 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.

Sve, servis je pokrenut i radi:

$ curl localhost

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

…

</html>

NAPOMENA: Ne pokušavajte ovo na Dockeru! Tamo su još uvek potrebni neki trikovi da bi se ovakvi kontejneri pokretali preko demona. (Biće potrebni dodatni parametri i paketi da bi sve to besprekorno radilo na Dockeru, ili će morati biti pokrenuto u privilegovanom kontejneru. Detalje vidite u članku.)

Još nekoliko interesantnih stvari o Podman-u i systemd-u

Podman radi bolje od Docker-a u unit fajlovima systemd-a

Ako kontejneri treba da se pokreću pri pokretanju sistema, možete jednostavno uneti odgovarajuće komande Podman-a u unit fajl systemd-a, koji će pokrenuti servis i pratiti ga. Podman koristi standardni fork-exec model pri izvršavanju. Drugim rečima, procesi kontejnera su podređeni procesu Podman-a, pa ih systemd lako može pratiti.

Docker koristi klijent-server model, a CLI komande Docker-a takođe se mogu stavljati direktno u unit fajl. Međutim, nakon što se Docker klijent poveže sa Docker demon, on (klijent) postaje samo još jedan proces koji obrađuje stdin i stdout. S druge strane, systemd nema predstavu o vezi između Docker klijenta i kontejnera koji radi pod upravom Docker demona, i zato u ovoj modelu systemd suštinski ne može pratiti servis.

Aktivacija systemd preko soketa

Podman ispravno obrađuje aktivaciju preko soketa. Pošto Podman koristi fork-exec model, može prenositi soket svojim podređenim procesima kontejnera. Docker to ne može, jer koristi klijent-server model.

Storitev varlink, ki jo Podman uporablja za interakcijo z daljinskimi odjemalci in kontejnerji, se v resnici aktivira preko vtičnice. Paket cockpit-podman, napisan v Node.js in del projekta cockpit, ljudem omogoča interakcijo s kontejnerji Podman preko spletnega vmesnika. Spletni demon, ki deluje na cockpit-podman, pošilja sporočila na varlink-vtičnico, ki jo nadzoruje systemd. Po tem systemd aktivira program Podman za sprejemanje sporočil in začetek upravljanja kontejnerjev. Aktivacija systemd preko vtičnice omogoča, da se obide potreba po stalno delujočem demonu pri implementaciji daljinskih API-jev.

Poleg tega razvijamo še enega odjemalca za Podman, imenovanega podman-remote, ki implementira isti Podman CLI, vendar kliče varlink za zagon kontejnerjev. Podman-remote lahko deluje preko SSH-sekvenc, kar omogoča varno interakcijo s kontejnerji na različnih napravah. Sčasoma načrtujemo vključitev podman-remote za podporo MacOS in Windows poleg Linuxa, da bi razvijalci na teh platformah lahko zagnali virtualni Linux stroj s funkcionalnim Podman varlinkom in imeli popoln občutek, da se kontejnerji izvajajo na lokalni napravi.

SD_NOTIFY

Systemd omogoča odložitev zagonov pomožnih storitev do trenutka, ko se zažene potreben kontejneriziran servis. Podman lahko preusmeri vtičnico SD_NOTIFY na kontejneriziran servis, da ta servis obvesti systemd o svoji pripravljenosti za delo. In ponovno, Docker, ki uporablja model odjemalec-strežnik, tega ne zmore.

Načrti

Načrtujemo dodati ukaz podman generate systemd CONTAINERID, ki bo generiral enoto systemd za upravljanje določenega kontejnerja. To naj bi delovalo tako v root- kot v rootless-načinah za neprivilegirane kontejnerje. Videli smo celo zahtevo za ustvarjanje OCI-compatibilnega okolja systemd-nspawn.

Zaključek

Zagon systemd v kontejnerju je povsem razumljiva potreba. In zahvaljujoč Podmanu imamo končno okolje za zagon kontejnerjev, ki ne nasprotuje systemd, ampak ga omogoča enostavno uporabo.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster