Izvajanje systemd v vsebniku

Že dolgo časa spremljamo temo uporabe systemd v kontejnerjih. Leta 2014 je naš varnostni inženir Daniel Walsh napisal članek Izvajanje systemd znotraj vsebnika Docker, in nekaj let kasneje - drugo, ki se je imenovalo Izvajanje systemd v vsebniku brez pravic, v katerem je ugotovil, da se stanje ni veliko izboljšalo. Zlasti je zapisal, da »na žalost, celo dve leti kasneje, če poguglate »Docker system«, je prva stvar, ki se prikaže, njegov isti stari članek. Torej je čas, da nekaj spremenimo.” Poleg tega smo že govorili o konflikt med razvijalci Docker in systemd.

Izvajanje systemd v vsebniku

V tem članku bomo pokazali, kaj se je skozi čas spremenilo in kako nam lahko Podman pri tem pomaga.

Obstaja veliko razlogov za zagon systemd znotraj vsebnika, na primer:

  1. Večnamenski kontejnerji – veliko ljudi želi svoje večstoritvene aplikacije potegniti iz virtualnih strojev in jih izvajati v vsebnikih. Seveda bi bilo bolje, če bi takšne aplikacije razdelili na mikrostoritve, vendar vsi še ne vedo, kako to storiti, ali preprosto nimajo časa. Zato je izvajanje takšnih aplikacij kot storitev, ki jih zažene systemd iz datotek enote, popolnoma smiselno.
  2. Datoteke enot Systemd – Večina aplikacij, ki se izvajajo znotraj vsebnikov, je zgrajenih iz kode, ki se je prej izvajala na virtualnih ali fizičnih strojih. Te aplikacije imajo datoteko enote, ki je bila napisana za te aplikacije in razume, kako jih je treba zagnati. Zato je še vedno bolje zagnati storitve s podprtimi metodami, namesto da vdrete v lastno init storitev.
  3. Systemd je upravitelj procesov. Upravlja storitve (izklopi, znova zažene storitve ali ubije zombi procese) bolje kot katero koli drugo orodje.

Kljub temu obstaja veliko razlogov, da ne izvajate systemd v vsebnikih. Glavna je ta, da systemd/journald nadzoruje izpis vsebnikov in podobnih orodij Kubernetes ali openshift pričakujte, da bodo vsebniki zapisovali dnevnik neposredno v stdout in stderr. Če boste torej vsebnike upravljali z orodji za orkestracijo, kot so zgoraj omenjena, morate resno razmisliti o uporabi vsebnikov, ki temeljijo na systemd. Poleg tega so razvijalci Dockerja in Mobyja pogosto močno nasprotovali uporabi systemd v vsebnikih.

Prihod Podmana

Z veseljem poročamo, da se je stanje končno premaknilo. Ekipa, odgovorna za vodenje kontejnerjev pri Red Hatu, se je odločila za razvoj lasten kontejnerski motor. Dobil je ime podman in ponuja enak vmesnik ukazne vrstice (CLI) kot Docker. In skoraj vse ukaze Docker lahko uporabite v Podmanu na enak način. Pogosto izvajamo seminarje, ki se zdaj imenujejo Spreminjanje Dockerja v Podmana, in že prvi diapozitiv zahteva pisanje: alias docker=podman.

Veliko ljudi to počne.

Moj Podman in jaz nikakor nisva proti vsebnikom, ki temeljijo na systemd. Navsezadnje je Systemd najpogosteje uporabljen zagonski podsistem Linuxa in če mu ne dovolimo, da pravilno deluje v vsebnikih, pomeni ignorirati, kako je na tisoče ljudi navajenih izvajati vsebnike.

Podman ve, kaj storiti, da sistem pravilno deluje v vsebniku. Potrebuje stvari, kot je namestitev tmpfs na /run in /tmp. Rada ima omogočeno "kontejnerizirano" okolje in pričakuje dovoljenja za pisanje v svoj del imenika cgroup in v mapo /var/log/journald.

Ko zaženete vsebnik, v katerem je prvi ukaz init ali systemd, Podman samodejno konfigurira tmpfs in Cgroups, da zagotovi, da se systemd zažene brez težav. Če želite blokirati ta način samodejnega zagona, uporabite možnost --systemd=false. Upoštevajte, da Podman uporablja način systemd le, ko vidi, da mora zagnati ukaz systemd ali init.

Tukaj je izvleček iz priročnika:

človek podman teči
...

–systemd=true|false

Izvajanje vsebnika v načinu systemd. Privzeto omogočeno.

Če zaženete ukaz systemd ali init znotraj vsebnika, bo Podman konfiguriral točke pritrditve tmpfs v naslednjih imenikih:

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

Tudi privzeti stop signal bo SIGRTMIN+3.

Vse to omogoča, da sistem deluje v zaprtem vsebniku brez kakršnih koli sprememb.

OPOMBA: systemd poskuša pisati v datotečni sistem cgroup. Vendar SELinux vsebnikom privzeto preprečuje, da bi to storili. Če želite omogočiti pisanje, omogočite logični parameter container_manage_cgroup:

setsebool -P container_manage_cgroup true

Zdaj pa poglejte, kako izgleda datoteka Dockerfile za zagon systemd v vsebniku z uporabo Podmana:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

To je vse.

Zdaj sestavimo posodo:

# podman build -t systemd .

SELinuxu povemo, naj sistemd dovoli spreminjanje konfiguracije Cgroups:

# setsebool -P container_manage_cgroup true

Mimogrede, mnogi pozabijo na ta korak. Na srečo je to treba storiti samo enkrat in nastavitev se shrani po ponovnem zagonu sistema.

Zdaj samo zaženemo posodo:

# 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 to, storitev je pripravljena in deluje:

$ curl localhost

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

…

</html>

OPOMBA: tega ne poskušajte na Dockerju! Tam morate še vedno plesati s tamburinom, da zaženete tovrstne vsebnike skozi demona. (Potrebna bodo dodatna polja in paketi, da bo vse to brezhibno delovalo v Dockerju, ali pa ga bo treba izvajati v privilegiranem vsebniku. Za podrobnosti glejte članek.)

Še nekaj kul stvari o Podmanu in systemd

Podman deluje bolje kot Docker v datotekah sistemske enote

Če je treba vsebnike zagnati ob zagonu sistema, lahko preprosto vstavite ustrezne ukaze Podman v datoteko enote systemd, ki bo zagnala storitev in jo nadzirala. Podman uporablja standardni model fork-exec. Z drugimi besedami, vsebniški procesi so otroci procesa Podman, zato jih lahko systemd enostavno nadzira.

Docker uporablja model odjemalec-strežnik, ukaze Docker CLI pa lahko postavite tudi neposredno v datoteko enote. Ko pa se odjemalec Docker poveže z demonom Docker, (odjemalec) postane le še en proces, ki obdeluje stdin in stdout. Systemd pa nima pojma o povezavi med odjemalcem Docker in vsebnikom, ki teče pod nadzorom demona Docker, zato znotraj tega modela systemd načeloma ne more spremljati storitve.

Aktivacija systemd prek vtičnice

Podman pravilno obravnava aktivacijo prek vtičnice. Ker Podman uporablja model fork-exec, lahko posreduje vtičnico svojim podrejenim vsebniškim procesom. Docker tega ne more narediti, ker uporablja model odjemalec-strežnik.

Storitev varlink, ki jo Podman uporablja za komunikacijo z oddaljenimi odjemalci do vsebnikov, se dejansko aktivira prek vtičnice. Paket cockpit-podman, napisan v Node.js in del projekta cockpit, ljudem omogoča interakcijo s kontejnerji Podman prek spletnega vmesnika. Spletni demon, ki izvaja cockpit-podman, pošilja sporočila v vtičnico varlink, ki jo posluša systemd. Systemd nato aktivira program Podman za prejemanje sporočil in začne upravljati vsebnike. Aktiviranje systemd prek vtičnice odpravi potrebo po nenehno delujočem demonu pri izvajanju oddaljenih API-jev.

Poleg tega razvijamo drugega odjemalca Podman, imenovanega podman-remote, ki izvaja isti Podman CLI, vendar kliče varlink za zagon vsebnikov. Podman-remote lahko deluje na vrhu sej SSH, kar vam omogoča varno interakcijo z vsebniki na različnih strojih. Sčasoma nameravamo omogočiti podman-remote za podporo MacOS in Windows poleg Linuxa, tako da lahko razvijalci na teh platformah poganjajo navidezni stroj Linux z zagonom Podman varlink in imajo popolno izkušnjo, da se vsebniki izvajajo na lokalnem računalniku.

SD_NOTIFY

Systemd vam omogoča, da odložite zagon pomožnih storitev, dokler se ne zažene storitev v vsebnikih, ki jo potrebujejo. Podman lahko posreduje vtičnico SD_NOTIFY storitvi v vsebniku, tako da storitev obvesti systemd, da je pripravljena za delovanje. In spet Docker, ki uporablja model odjemalec-strežnik, tega ne more storiti.

V načrtih

Načrtujemo dodati ukaz podman generate systemd CONTAINERID, ki bo ustvaril datoteko enote systemd za upravljanje določenega vsebnika. To bi moralo delovati v korenskem in brezkoreninskem načinu za vsebnike brez pravic. Videli smo celo zahtevo za izvajalno okolje systemd-nspawn, združljivo z OCI.

Zaključek

Zagon systemd v vsebniku je razumljiva potreba. In zahvaljujoč Podmanu, imamo končno runtime vsebnika, ki ni v nasprotju s systemd, ampak omogoča preprosto uporabo.

Vir: www.habr.com

Dodaj komentar