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 , et quelques années plus tard, un autre article intitulé , 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 .
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 :
- 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.
- 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.
- 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 ou 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 . Il s'appelle 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 , 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 .)
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
