Executeu systemd en un contenidor

Fa temps que seguim el tema de l'ús de systemd als contenidors. L'any 2014, el nostre enginyer de seguretat Daniel Walsh va escriure un article S'està executant systemd dins d'un contenidor Docker, i un parell d'anys més tard - un altre, que es deia S'executa systemd en un contenidor no privilegiat, en què va afirmar que la situació no havia millorat gaire. En particular, va escriure que "malauradament, fins i tot dos anys més tard, si busqueu a Google "Sistema Docker", el primer que apareix és el seu mateix article antic. Així que és hora de canviar alguna cosa". A més, ja n'hem parlat conflicte entre Docker i desenvolupadors de systemd.

Executeu systemd en un contenidor

En aquest article mostrarem què ha canviat al llarg del temps i com Podman ens pot ajudar en aquesta qüestió.

Hi ha moltes raons per executar systemd dins d'un contenidor, com ara:

  1. Contenidors multiservei – Moltes persones volen treure les seves aplicacions multiservei de les màquines virtuals i executar-les en contenidors. Per descomptat, seria millor dividir aquestes aplicacions en microserveis, però encara no tothom sap com fer-ho o simplement no té temps. Per tant, executar aplicacions com ara serveis llançats per systemd des de fitxers unitaris té tot el sentit.
  2. Fitxers d'unitats de sistema – La majoria de les aplicacions que s'executen dins dels contenidors es creen a partir de codi que s'executava anteriorment en màquines virtuals o físiques. Aquestes aplicacions tenen un fitxer d'unitat que s'ha escrit per a aquestes aplicacions i entén com s'han de llançar. Per tant, encara és millor iniciar els serveis amb mètodes compatibles, en lloc de piratejar el vostre propi servei d'inici.
  3. Systemd és un gestor de processos. Gestiona els serveis (apaga, reinicia serveis o mata processos zombis) millor que qualsevol altra eina.

Dit això, hi ha moltes raons per no executar systemd als contenidors. El principal és que systemd/journald controla la sortida dels contenidors i eines com Kubernetes o torn obert espereu que els contenidors escriguin el registre directament a stdout i stderr. Per tant, si voleu gestionar contenidors mitjançant eines d'orquestració com les esmentades anteriorment, hauríeu de considerar seriosament l'ús de contenidors basats en systemd. A més, els desenvolupadors de Docker i Moby sovint s'han oposat fermament a utilitzar systemd als contenidors.

L'arribada de Podman

Ens complau informar que la situació finalment ha avançat. L'equip responsable del funcionament dels contenidors de Red Hat va decidir desenvolupar-se el teu propi motor de contenidors. Va tenir un nom Podman i ofereix la mateixa interfície de línia d'ordres (CLI) que Docker. I gairebé totes les ordres de Docker es poden utilitzar a Podman de la mateixa manera. Sovint fem seminaris, que ara s'anomenen Canvi de Docker a Podman, i la primera diapositiva demana escriure: àlies docker=podman.

Molta gent ho fa.

El meu Podman i jo no estem de cap manera en contra dels contenidors basats en systemd. Després de tot, Systemd és el subsistema d'inici de Linux més utilitzat, i no permetre que funcioni correctament als contenidors significa ignorar com milers de persones estan acostumades a executar contenidors.

Podman sap què ha de fer perquè systemd funcioni correctament en un contenidor. Necessita coses com muntar tmpfs a /run i /tmp. Li agrada tenir l'entorn "contenidor" habilitat i espera permisos d'escriptura a la seva part del directori cgroup i a la carpeta /var/log/journald.

Quan inicieu un contenidor en què la primera ordre és init o systemd, Podman configura automàticament tmpfs i Cgroups per garantir que systemd s'iniciï sense problemes. Per bloquejar aquest mode d'inici automàtic, utilitzeu l'opció --systemd=false. Tingueu en compte que Podman només utilitza el mode systemd quan veu que necessita executar una ordre systemd o init.

Aquí teniu un extracte del manual:

home podman córrer
...

–systemd=true|false

Execució d'un contenidor en mode systemd. Habilitat per defecte.

Si executeu una ordre systemd o init dins d'un contenidor, Podman configurarà els punts de muntatge tmpfs als directoris següents:

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

També el senyal de parada predeterminat serà SIGRTMIN+3.

Tot això permet que systemd funcioni en un contenidor tancat sense cap modificació.

NOTA: systemd intenta escriure al sistema de fitxers cgroup. Tanmateix, SELinux impedeix que els contenidors ho facin per defecte. Per habilitar l'escriptura, activeu el paràmetre booleà container_manage_cgroup:

setsebool -P container_manage_cgroup true

Ara mireu com es veu el Dockerfile per executar systemd en un contenidor amb Podman:

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

Això és tot.

Ara muntem el contenidor:

# podman build -t systemd .

Li diem a SELinux que permeti a systemd modificar la configuració de Cgroups:

# setsebool -P container_manage_cgroup true

Per cert, molta gent s'oblida d'aquest pas. Afortunadament, això només s'ha de fer una vegada i la configuració es desa després de reiniciar el sistema.

Ara només comencem el contenidor:

# 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.

Això és tot, el servei està en funcionament:

$ curl localhost

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

…

</html>

NOTA: No ho proveu a Docker! Allà encara cal ballar amb un tamborí per llançar aquest tipus de contenidors a través del dimoni. (Seran necessaris camps i paquets addicionals perquè tot això funcioni perfectament a Docker, o s'haurà d'executar en un contenidor privilegiat. Per obtenir més informació, consulteu article.)

Un parell de coses més interessants sobre Podman i systemd

Podman funciona millor que Docker als fitxers d'unitats systemd

Si els contenidors s'han d'iniciar quan s'engega el sistema, simplement podeu inserir les ordres Podman adequades al fitxer d'unitat systemd, que iniciarà el servei i el controlarà. Podman utilitza el model fork-exec estàndard. En altres paraules, els processos de contenidors són fills del procés Podman, de manera que systemd els pot controlar fàcilment.

Docker utilitza un model client-servidor i les ordres CLI de Docker també es poden col·locar directament en un fitxer d'unitat. Tanmateix, un cop el client Docker es connecta al dimoni Docker, (el client) es converteix en un altre procés que processa stdin i stdout. Al seu torn, systemd no té ni idea de la connexió entre el client Docker i el contenidor que s'executa sota el control del dimoni Docker i, per tant, dins d'aquest model, systemd fonamentalment no pot supervisar el servei.

S'està activant el sistema a través del sòcol

Podman gestiona l'activació a través del sòcol correctament. Com que Podman utilitza el model fork-exec, pot reenviar el sòcol als seus processos de contenidor fill. Docker no pot fer-ho perquè utilitza un model client-servidor.

El servei varlink que el Podman utilitza per comunicar-se amb clients remots als contenidors s'activa realment mitjançant un sòcol. El paquet cockpit-podman, escrit en Node.js i part del projecte cockpit, permet a la gent interactuar amb contenidors Podman mitjançant una interfície web. El dimoni web que executa cockpit-podman envia missatges a un sòcol varlink que el sistema escolta. A continuació, Systemd activa el programa Podman per rebre missatges i començar a gestionar els contenidors. L'activació de systemd a través d'un sòcol elimina la necessitat d'un dimoni en execució constant quan s'implementa API remotes.

A més, estem desenvolupant un altre client Podman anomenat podman-remote, que implementa la mateixa CLI de Podman però crida a varlink per executar contenidors. Podman-remote es pot executar a sobre de les sessions SSH, cosa que us permet interactuar de manera segura amb els contenidors de diferents màquines. Amb el temps, tenim previst habilitar podman-remote per admetre MacOS i Windows juntament amb Linux, de manera que els desenvolupadors d'aquestes plataformes puguin executar una màquina virtual Linux amb Podman varlink en execució i tenir l'experiència completa que els contenidors s'executen a la màquina local.

SD_NOTIFY

Systemd permet ajornar el llançament dels serveis auxiliars fins que s'iniciï el servei en contenidors que requereixen. Podman pot reenviar el sòcol SD_NOTIFY al servei en contenidors perquè el servei notifiqui a systemd que està llest per funcionar. I de nou, Docker, que utilitza un model client-servidor, no pot fer-ho.

En els plànols

Tenim previst afegir l'ordre podman generate systemd CONTAINERID, que generarà un fitxer d'unitat systemd per gestionar un contenidor específic especificat. Això hauria de funcionar tant en mode arrel com sense arrel per a contenidors sense privilegis. Fins i tot hem vist una sol·licitud per a un temps d'execució systemd-nspawn compatible amb OCI.

Conclusió

Executar systemd en un contenidor és una necessitat comprensible. I gràcies a Podman, finalment tenim un temps d'execució del contenidor que no entra en conflicte amb systemd, però que el fa fàcil d'utilitzar.

Font: www.habr.com

Afegeix comentari