Lancer systemd dans un conteneur

Nous suivons depuis longtemps le sujet de l'utilisation de systemd dans les conteneurs. Déjà en 2014, notre ingénieur en sécurité Daniel Walsh a écrit un article Exécution de systemd dans un conteneur Docker, et quelques années plus tard, un autre article intitulé Exécution de systemd dans un conteneur non privilégié, dans lequel il a constaté que la situation n'avait pas beaucoup évolué. En particulier, il écrivait que « malheureusement, deux ans plus tard, si vous recherchez « Docker system », le premier résultat est toujours son ancien article. Il est donc temps d'apporter des changements ». De plus, nous avons déjà abordé le conflit entre les développeurs de Docker et systemd.

Lancer systemd dans un conteneur

Dans cet article, nous montrerons ce qui a changé depuis et comment Podman peut nous aider à ce sujet.

Il existe de nombreuses raisons d'exécuter systemd à l'intérieur d'un conteneur, telles que :

  1. Conteneurs multiservices – beaucoup veulent extraire leurs applications multiservices des machines virtuelles et les exĂ©cuter dans des conteneurs. Il vaudrait mieux, bien sĂ»r, dĂ©composer ces applications en microservices, mais tout le monde ne sait pas encore le faire ou n'a tout simplement pas le temps. Par consĂ©quent, exĂ©cuter ces applications en tant que services gĂ©rĂ©s par systemd Ă  partir de fichiers d'unitĂ© a tout son sens.
  2. Fichiers d'unitĂ© Systemd – la plupart des applications fonctionnant Ă  l'intĂ©rieur des conteneurs sont issues de code qui Ă©tait auparavant exĂ©cutĂ© sur des machines virtuelles ou physiques. Ces applications ont un fichier d'unitĂ©, qui a Ă©tĂ© Ă©crit pour ces applications et sait comment les lancer. Il est donc prĂ©fĂ©rable de lancer les services en utilisant des mĂ©thodes prises en charge, plutĂŽt que de pirater son propre service init.
  3. Systemd est un gestionnaire de processus. Il gĂšre les services (arrĂȘte, redĂ©marre les services ou nettoie les processus zombies) mieux que tout autre outil.

Cela dit, il y a aussi beaucoup de raisons de ne pas exécuter systemd dans des conteneurs. La principale étant que systemd/journald contrÎle la sortie des conteneurs, tandis que des outils comme Kubernetes ou OpenShift s'attendent à ce que les conteneurs écrivent des journaux directement dans stdout et stderr. Donc, si vous prévoyez de gérer les conteneurs via des outils d'orchestration comme ceux mentionnés ci-dessus, vous devez réfléchir sérieusement à l'utilisation de conteneurs basés sur systemd. De plus, les développeurs de Docker et Moby ont souvent été fermement opposés à l'utilisation de systemd dans des conteneurs.

L'avĂšnement de Podman

Nous avons le plaisir d'annoncer que la situation a enfin Ă©voluĂ©. L'Ă©quipe responsable du lancement des conteneurs chez Red Hat a dĂ©cidĂ© de dĂ©velopper son propre moteur de conteneurs. Il s'appelle Podman et propose la mĂȘme interface de ligne de commande (CLI) que Docker. Pratiquement toutes les commandes Docker peuvent Ă©galement ĂȘtre utilisĂ©es dans Podman. Nous organisons souvent des ateliers qui s'appellent maintenant Remplacer Docker par Podman, et la premiĂšre diapositive invite Ă  inscrire : alias docker=podman.

Beaucoup le font.

Nous, avec notre Podman, ne sommes en aucun cas opposés aux conteneurs basés sur systemd. En effet, Systemd est souvent utilisé comme sous-systÚme d'initialisation de Linux, et ne pas lui permettre de fonctionner correctement dans les conteneurs signifie ignorer comment des milliers de personnes ont l'habitude de lancer des conteneurs.

Podman sait ce qu'il faut faire pour que systemd fonctionne correctement dans un conteneur. Il a besoin de choses comme le montage de tmpfs sur /run et /tmp. Il aime quand l'environnement « conteneur » est activé, et il attend des droits d'écriture dans sa partie du répertoire cgroup et dans le dossier /var/log/journald.

Lors du lancement d'un conteneur avec init ou systemd comme premiĂšre commande, Podman configure automatiquement tmpfs et Cgroups pour que le dĂ©marrage de systemd se passe sans problĂšmes. Pour dĂ©sactiver ce mode de dĂ©marrage automatique, l'option —systemd=false est utilisĂ©e. Notez que Podman utilise le mode systemd uniquement lorsqu'il voit qu'il doit exĂ©cuter une commande systemd ou init.

Voici un extrait du manuel :

man podman run



–systemd=true|false

Lancement d'un conteneur en mode systemd. Activé par défaut.

Si une commande systemd ou init est exécutée à l'intérieur du conteneur, Podman configurera les points de montage tmpfs dans les répertoires suivants :

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

De plus, le signal d'arrĂȘt par dĂ©faut sera SIGRTMIN+3.

Tout cela permet à systemd de fonctionner dans un conteneur isolé sans aucune modification.

REMARQUE : systemd essaie d'écrire dans le systÚme de fichiers cgroup. Cependant, SELinux interdit par défaut cela aux conteneurs. Pour autoriser l'écriture, activez l'option logique container_manage_cgroup :

setsebool -P container_manage_cgroup true

Voyons maintenant à quoi ressemble le Dockerfile pour exécuter systemd dans un conteneur en utilisant Podman :

# cat Dockerfile

FROM fedora

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

EXPOSE 80

CMD [ "/sbin/init" ]

Et voilĂ .

Nous construisons maintenant le conteneur :

# podman build -t systemd .

Dites Ă  SELinux d'autoriser systemd Ă  modifier la configuration des Cgroups :

# setsebool -P container_manage_cgroup true

Beaucoup, d'ailleurs, oublient cette étape. Heureusement, il suffit de le faire une seule fois et la configuration est sauvegardée aprÚs le redémarrage du systÚme.

Nous allons maintenant simplement démarrer le conteneur :

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

Voilà, le service est lancé et fonctionne :

$ curl localhost

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

…

</html>

REMARQUE : Ne tentez pas de le reproduire sur Docker ! Il faut encore des astuces pour démarrer ce type de conteneurs via le démon. (Des champs et des paquets supplémentaires seront nécessaires pour que tout cela fonctionne sans couture sur Docker, ou il faudra lancer dans un conteneur privilégié. Pour plus de détails, voir article.)

Encore quelques fonctionnalités intéressantes sur Podman et systemd

Podman fonctionne mieux que Docker dans les fichiers d'unité systemd

Si les conteneurs doivent ĂȘtre lancĂ©s au dĂ©marrage du systĂšme, vous pouvez simplement insĂ©rer les commandes Podman correspondantes dans le fichier d'unitĂ© systemd, celui-ci lancera le service et le surveillera. Podman utilise le modĂšle d'exĂ©cution standard fork-exec. En d'autres termes, les processus des conteneurs sont des enfants du processus de Podman, donc systemd peut facilement les surveiller.

Docker utilise le modĂšle client-serveur, et les commandes CLI de Docker peuvent Ă©galement ĂȘtre directement placĂ©es dans le fichier d'unitĂ©. Cependant, une fois que le client Docker se connecte au dĂ©mon Docker, il (le client) devient simplement un autre processus traitant stdin et stdout. En revanche, systemd n'a aucune idĂ©e de la connexion entre le client Docker et le conteneur qui fonctionne sous le contrĂŽle du dĂ©mon Docker, et donc dans ce modĂšle, systemd ne peut fondamentalement pas surveiller le service.

Activation de systemd via socket

Podman gĂšre correctement l'activation via socket. Étant donnĂ© que Podman utilise le modĂšle fork-exec, il peut transmettre le socket Ă  ses processus conteneurs enfants. Docker ne peut pas faire cela, car il utilise le modĂšle client-serveur.

Le service varlink utilisĂ© par Podman pour permettre l'interaction entre les clients distants et les conteneurs est en fait activĂ© via un socket. Le package cockpit-podman, Ă©crit en Node.js et faisant partie du projet cockpit, permet aux utilisateurs d'interagir avec les conteneurs Podman via une interface web. Le dĂ©mon web sur lequel fonctionne cockpit-podman envoie des messages au socket varlink, qui est surveillĂ© par systemd. Ensuite, systemd active le programme Podman pour recevoir les messages et commencer Ă  gĂ©rer les conteneurs. L'activation de systemd via le socket permet d'Ă©viter d'avoir un dĂ©mon toujours actif lors de la mise en Ɠuvre d'API distantes.

De plus, nous dĂ©veloppons un autre client pour Podman nommĂ© podman-remote, qui implĂ©mente le mĂȘme CLI Podman, mais appelle varlink pour dĂ©marrer des conteneurs. Podman-remote peut fonctionner sur des sessions SSH, ce qui permet une interaction sĂ©curisĂ©e avec des conteneurs sur diverses machines. Avec le temps, nous prĂ©voyons d'Ă©tendre podman-remote pour prendre en charge MacOS et Windows en plus de Linux, afin que les dĂ©veloppeurs sur ces plateformes puissent lancer une machine virtuelle Linux avec Podman varlink en cours d'exĂ©cution et avoir la sensation complĂšte que les conteneurs s'exĂ©cutent sur leur machine locale.

SD_NOTIFY

Systemd permet de retarder le démarrage des services auxiliaires jusqu'à ce que le service conteneurisé dont ils ont besoin soit lancé. Podman peut transmettre le socket SD_NOTIFY au service conteneurisé pour que ce service informe systemd de sa disponibilité. Encore une fois, Docker, qui utilise un modÚle client-serveur, ne sait pas faire cela.

À venir

Nous prĂ©voyons d'ajouter la commande podman generate systemd CONTAINERID, qui gĂ©nĂ©rera un fichier d'unitĂ© systemd pour gĂ©rer un conteneur spĂ©cifique. Cela devrait fonctionner tant en mode root qu'en mode rootless pour les conteneurs non privilĂ©giĂ©s. Nous avons mĂȘme vu une demande pour crĂ©er un environnement d'exĂ©cution compatible OCI systemd-nspawn.

Conclusion

L'exĂ©cution de systemd dans un conteneur est un besoin tout Ă  fait comprĂ©hensible. Et grĂące Ă  Podman, nous avons enfin un environnement d'exĂ©cution de conteneurs qui ne s'oppose pas Ă  systemd, mais permet de l’utiliser facilement.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster