Pokretanje systemd-a u spremniku

Već duže vrijeme pratimo temu korištenja systemd-a u kontejnerima. Još 2014. naš sigurnosni inženjer Daniel Walsh napisao je članak Pokretanje systemd-a unutar Docker kontejnera, a nekoliko godina kasnije - još jedan, koji se zvao Pokretanje systemd-a u neprivilegiranom spremniku, u kojem je ustvrdio da se situacija nije puno popravila. Konkretno, napisao je da “nažalost, čak i dvije godine kasnije, ako guglate “Docker sustav”, prva stvar koja dolazi je njegov isti stari članak. Dakle, vrijeme je da se nešto promijeni.” Osim toga, već smo razgovarali o sukob između programera Dockera i systemd-a.

Pokretanje systemd-a u spremniku

U ovom ćemo članku pokazati što se promijenilo tijekom vremena i kako nam Podman može pomoći u tome.

Postoje mnogi razlozi za pokretanje systemd unutar spremnika, kao što su:

  1. Multiservisni spremnici – mnogi ljudi žele izvući svoje višeuslužne aplikacije iz virtualnih strojeva i pokrenuti ih u spremnicima. Bilo bi bolje, naravno, razbiti takve aplikacije u mikroservise, ali ne znaju svi još kako to učiniti ili jednostavno nemaju vremena. Stoga, pokretanje takvih aplikacija kao što su usluge koje pokreće systemd iz jediničnih datoteka ima savršenog smisla.
  2. Datoteke jedinica Systemd – Većina aplikacija koje se izvode unutar spremnika izgrađene su od koda koji se prethodno izvodio na virtualnim ili fizičkim strojevima. Ove aplikacije imaju jediničnu datoteku koja je napisana za te aplikacije i razumije kako ih treba pokrenuti. Stoga je još uvijek bolje pokretati usluge pomoću podržanih metoda, umjesto hakiranja vlastite init usluge.
  3. Systemd je upravitelj procesa. Upravlja uslugama (isključuje, ponovno pokreće usluge ili ubija zombi procese) bolje od bilo kojeg drugog alata.

Uz to, postoji mnogo razloga zašto ne pokretati systemd u spremnicima. Glavna je da systemd/journald kontrolira izlaz spremnika i sličnih alata Kubernetes ili otvorena smjena očekujte da će spremnici pisati dnevnik izravno u stdout i stderr. Stoga, ako namjeravate upravljati spremnicima putem alata za orkestraciju poput gore spomenutih, trebali biste ozbiljno razmisliti o korištenju spremnika temeljenih na systemd-u. Osim toga, programeri Dockera i Mobyja često su se snažno protivili korištenju systemd-a u spremnicima.

Dolazak Podmana

Sretni smo što možemo izvijestiti da se situacija konačno pomakla naprijed. Tim odgovoran za upravljanje kontejnerima u Red Hatu odlučio je razviti vlastiti kontejnerski motor. Dobio je ime podman i nudi isto sučelje naredbenog retka (CLI) kao Docker. I gotovo sve Docker naredbe mogu se koristiti u Podmanu na isti način. Često održavamo seminare, koji se sada zovu Promjena Dockera u Podman, a prvi slajd poziva na pisanje: alias docker=podman.

Mnogi ljudi to rade.

Moj Podman i ja nismo ni na koji način protiv spremnika temeljenih na systemd-u. Uostalom, Systemd je najčešće korišten Linux init podsustav, a ne dopustiti mu da ispravno radi u spremnicima znači ignorirati kako su tisuće ljudi navikle na pokretanje spremnika.

Podman zna što treba učiniti da bi systemd ispravno radio u spremniku. Potrebne su stvari poput montiranja tmpfs na /run i /tmp. Ona voli imati omogućeno "kontejnerizirano" okruženje i očekuje dozvole za pisanje u svoj dio direktorija cgroup i mapu /var/log/journald.

Kada pokrenete spremnik u kojem je prva naredba init ili systemd, Podman automatski konfigurira tmpfs i Cgroups kako bi osigurao da se systemd pokreće bez problema. Za blokiranje ovog načina automatskog pokretanja koristite opciju --systemd=false. Imajte na umu da Podman koristi način rada systemd samo kada vidi da treba pokrenuti naredbu systemd ili init.

Evo izvatka iz priručnika:

čovjek podman trčati
...

–systemd=true|false

Pokretanje spremnika u načinu rada systemd. Omogućeno prema zadanim postavkama.

Ako pokrenete systemd ili init naredbu unutar spremnika, Podman će konfigurirati tmpfs točke montiranja u sljedećim direktorijima:

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

Također će zadani signal za zaustavljanje biti SIGRTMIN+3.

Sve to omogućuje da systemd radi u zatvorenom spremniku bez ikakvih izmjena.

NAPOMENA: systemd pokušava pisati u cgroup datotečni sustav. Međutim, SELinux sprječava spremnike da to rade prema zadanim postavkama. Da biste omogućili pisanje, omogućite booleov parametar container_manage_cgroup:

setsebool -P container_manage_cgroup true

Sada pogledajte kako izgleda Dockerfile za pokretanje systemd-a u spremniku pomoću Podmana:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

To je sve.

Sada sastavljamo spremnik:

# podman build -t systemd .

Kažemo SELinuxu da dopusti systemd-u da modificira konfiguraciju Cgroups:

# setsebool -P container_manage_cgroup true

Usput, mnogi ljudi zaborave na ovaj korak. Srećom, to je potrebno učiniti samo jednom i postavka se sprema nakon ponovnog pokretanja sustava.

Sada samo pokrećemo spremnik:

# 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, usluga je pokrenuta i radi:

$ curl localhost

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

…

</html>

NAPOMENA: Ne pokušavajte ovo na Dockeru! Tu još trebate plesati s tamburinom da biste pokrenuli ovakve kontejnere kroz daemona. (Bit će potrebna dodatna polja i paketi kako bi sve ovo radilo besprijekorno u Dockeru ili će se morati pokrenuti u privilegiranom spremniku. Za detalje pogledajte članak.)

Još par cool stvari o Podmanu i systemdu

Podman radi bolje od Dockera u datotekama sistemske jedinice

Ako se spremnici trebaju pokrenuti prilikom dizanja sustava, tada možete jednostavno umetnuti odgovarajuće Podman naredbe u datoteku jedinice systemd, koja će pokrenuti uslugu i nadzirati je. Podman koristi standardni model fork-exec. Drugim riječima, kontejnerski procesi su djeca Podman procesa, tako da ih systemd može lako nadzirati.

Docker koristi model klijent-poslužitelj, a Docker CLI naredbe također se mogu postaviti izravno u jediničnu datoteku. Međutim, kada se Docker klijent poveže s Docker demonom, on (klijent) postaje samo još jedan proces koji rukuje stdin i stdout. S druge strane, systemd nema pojma o vezi između Docker klijenta i spremnika koji radi pod kontrolom Docker demona, te stoga unutar ovog modela systemd u osnovi ne može nadzirati uslugu.

Aktiviranje systemd putem utičnice

Podman ispravno rješava aktivaciju putem utičnice. Budući da Podman koristi model fork-exec, može proslijediti utičnicu svojim podređenim procesima spremnika. Docker to ne može jer koristi model klijent-poslužitelj.

Servis varlink koji Podman koristi za komunikaciju s udaljenim klijentima do kontejnera zapravo se aktivira preko socketa. Paket cockpit-podman, napisan u Node.js i dio je projekta kokpita, omogućuje ljudima interakciju s Podman kontejnerima putem web sučelja. Web demon koji pokreće cockpit-podman šalje poruke u varlink utičnicu koju systemd sluša. Systemd zatim aktivira program Podman za primanje poruka i početak upravljanja spremnicima. Aktiviranje systemd-a preko utičnice eliminira potrebu za stalno pokrenutim demonom prilikom implementacije udaljenih API-ja.

Osim toga, razvijamo još jedan Podman klijent pod nazivom podman-remote, koji implementira isti Podman CLI, ali poziva varlink za pokretanje spremnika. Podman-remote može raditi povrh SSH sesija, omogućujući vam sigurnu interakciju sa spremnicima na različitim strojevima. S vremenom planiramo omogućiti podman-remote da podržava MacOS i Windows uz Linux, tako da razvojni programeri na tim platformama mogu pokrenuti Linux virtualni stroj s pokrenutim Podman varlinkom i imati potpuno iskustvo rada spremnika na lokalnom računalu.

SD_OBAVIJESTI

Systemd vam omogućuje da odgodite pokretanje pomoćnih usluga dok se ne pokrene usluga u kontejnerima koja im je potrebna. Podman može proslijediti SD_NOTIFY utičnicu kontejnerskoj usluzi tako da usluga obavijesti systemd da je spremna za rad. I opet, Docker, koji koristi model klijent-poslužitelj, to ne može učiniti.

U planovima

Planiramo dodati naredbu podman generate systemd CONTAINERID, koja će generirati datoteku jedinice systemd za upravljanje određenim spremnikom. Ovo bi trebalo raditi u root i root načinu rada za neprivilegirane spremnike. Čak smo vidjeli zahtjev za OCI-kompatibilnim runtimeom systemd-nspawn.

Zaključak

Pokretanje systemd-a u kontejneru je razumljiva potreba. I zahvaljujući Podmanu, konačno imamo runtime spremnika koji nije u sukobu sa systemd-om, ali ga čini jednostavnim za korištenje.

Izvor: www.habr.com

Dodajte komentar