L'adoption de Podman comme moteur de conteneur par défaut sous RHEL 8 est un signal fort pour considérer cette solution comme mature et crédible pour enfin se passer de Docker. En effet, Red Hat ne fait pas de choix technologiques à la légère quand il s'agit ensuite d'assurer le support pendant 10 ans de la solution.
Dans cet article, je vais expliquer comment migrer un conteneur, d'une complexité normale, vers Podman et j'explorerai ensuite certain des apports de Podman.
Présentation de Podman
Podman est un moteur de conteneur, conforme aux spécifications de l'Open Container Initiative (OCI). Le projet a initialement émergé au sein du projet CRI-O, sous le nom de kpod.
Podman est spécialisé dans l'exécution des conteneurs, il est développé parallèlement à d'autres projets qui se concentrent sur d'autres étapes du cycle de vie des conteneurs :
-
Buildah : spécialisé dans la construction d'images
-
Skopeo : spécialisé dans la gestion des images et des registry
Podman se distingue de Docker par, entre autres, son fonctionnement sans démon et sa possibilité de fonctionner sans droits root.
Migration d'un conteneur
Podman est compatible, à quelques exceptions près, avec les commandes Docker. Red Hat va jusqu'à proposer une commande docker qui pointe sur le binaire podman. Personnellement, je préfère prendre l'habitude d'appeler directement le bon binaire.
J'ai sur mon infrastructure personnelle une instance de Collabora, qui me permet d'intégrer une possibilité d'éditer des documents Libre Office, de manière collaborative, depuis mon instance Nextcloud. Voilà le docker-compose.yaml
que j'utilisais :
version: '3'
services:
collabora:
ports:
- "9980:9980"
image: collabora/code:latest
environment:
domain: nextcloud\.mondomaine\.fr
username: superuser
password: securepassword
allowed_languages: en_US fr_FR
dictionaries: en_US fr_FR
cap_add:
- MKNOD
restart: always
L'utilisation de docker-compose ici n'apportait rien de particulier d'autre que ce qui pouvait être fait via un simple docker run
. On peut donc simplement remplacer cela par un podman run
(exécuté en root)
podman run --name collabora --env-file collabora.env --cap-add MKNOD -p 9980:9980 collabora/code:latest
Avec les variables d'environnement externalisées dans un fichier collabora.env
:
domain=nextcloud\.mondomaine\.fr
username=superuser
password=securepassword
allowed_languages=en_US fr_FR
dictionaries=en_US fr_FR
On peut vérifier la bonne exécution de notre conteneur avec les commandes podman ps
et podman logs
.
Maintenant, afin de permettre de gérer ce conteneur comme un service, on crée le service systemd qui va bien. Dans le fichier /etc/systemd/system/collabora.service
:
[Unit]
Description=Custom Collabora Podman Container
After=network.target
[Service]
Type=simple
TimeoutStartSec=5m
ExecStartPre=-/usr/bin/podman rm "collabora"
ExecStart=/usr/bin/podman run --name collabora --env-file /etc/systemd/system/collabora.env --cap-add MKNOD -p 9980:9980 collabora/code:latest
ExecReload=-/usr/bin/podman stop "collabora"
ExecReload=-/usr/bin/podman rm "collabora"
ExecStop=-/usr/bin/podman stop "collabora"
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target
On peut alors vérifier via systemctl
qu'on est capable de contrôler le conteneur comme un service. Il ne reste plus ensuite que faire un systemctl enable
pour démarrer automatiquement le conteneur avec le serveur.
A noter qu'il existe une commande podman generate systemd
mais le résultat ne me convenait pas car il permet uniquement l'arrêt relance d'un conteneur existant.
Conteneur sans root
Podman permet d'être utilisé et d'exécuter des conteneur avec des utilisateurs non privilégiés. Cela ne fonctionne pas (encore) pour tous les scénarios, notamment il n'est pas possible d'ajouter une Capability Linux à l'exécution (ce qui exclu donc notre conteneur Collabora qui a besoin de MKNOD).
Espaces de nommage utilisateur
Pour fonctionner avec un utilisateur lambda, Podman utilise le concept de subuid qui permet de déléguer la gestion d'une plage d'UID à un utilisateur. Ce mécanisme, fournit par shadow-utils se configure dans le fichier /etc/subuid
(et de même pour les GID dans /etc/subgid
). Par exemple :
cedric:100000:65536
Cela signifie que l'utilisateur cedric
pourra utiliser 65536 UID, à partir de l'UID 100000. Attention à bien spécifier des UID qui ne sont pas utilisés par le système hôte et de ne pas se faire recouvrir les subuid de plusieurs utilisateurs.
Concrètement, cela veut dire que l'UID 1 dans un conteneur exécuté par cet utilisateur correspondra à l'UID 100000 du point de vue de l'hôte, l'UID 2 à l'UID 100001, et ainsi de suite. À noter que l'UID 0 (root) sera lui mappé à l'UID de l'utilisateur.
Stockage
Lorsque Podman fonctionne avec l'utilisateur root, il utilise l'espace de stockage configuré dans /etc/containers/storage.conf
. Lorsqu'il est exécuté par un autre utilisateur, il utilise un espace de stockage spécifique situé dans ~/.local/share/containers
.
Cela permet d'isoler les espaces de stockage des différents utilisateurs du système avec tous les avantages (sécurité, isolation,...) mais aussi tous les inconvénients (duplication éventuelle des images et autres données) que cela comporte.
OverlayFS fonctionnant en mode Kernel, il n'est évidemment pas possible pour un utilisateur non privilégié d'en tirer parti. Il est donc nécessaire d'utiliser fuse-overlayfs qui est une implémentation FUSE d'OverlayFS. Sans cette bibliothèque, Podman utilise VFS qui n'a aucun mécanisme de déduplication et donc peut être très problématique en terme d'espace dès que l'utilisateur multiplie le nombre de conteneurs utilisés.
Pods
Podman ne s'appellerait pas ainsi sans la gestion de pods. Les pods sont un concept hérité de Kubernetes. Il s'agit d'une abstraction permettant de gérer de manière cohérente un ou plusieurs conteneurs.
La gestion des pods dans Podman est initialement dû à l'objectif initial de ce dernier : Podman a été développé pour faciliter le débogage de conteneurs sur un nœud Kubernetes (lorsque le démon CRI-o n'est pas accessible ou pour permettre une investigation plus fine).
Cela permet également de faciliter la migration de conteneurs vers Kubernetes en utilisant le même type d'objets. Il est d'ailleurs possible d'extraire sous forme de fichier YAML importable par Kubernetes, des conteneurs Podman, grâce à la commande podman generate kube
. Le résultat peut alors être réimporté par Podman avec la commande podman play kube
(qui officiellement ne supporte que les YAML générés par lui-même, Podman ne supportant pas tous les objets et les paramètres de Kubernetes) ou importé dans Kubernetes avec la commande kubectl create -f
.
En dehors de Kubernetes, ce concept de pod permet surtout de pouvoir gérer un groupe de conteneurs de manière cohérente comme on peut le faire avec un docker-compose.
Pour manipuler des pods avec Podman, rien de plus simple. Il suffit d'utiliser podman pod create
pour créer un pod et de rajouter l'option --pod
à une commande podman run
pour créer un conteneur dans un pod.
Conclusion
La facilité de migration (pour les cas les plus simple) de Docker vers Podman est rassurante. À iso-fonctionnalités, Podman à l'avantage d'être pleinement basé sur des standards ouverts (OCI) et d'être un vrai projet Open Source.
Les fonctionnalités apportées par Podman sont très intéressantes. Notamment la possibilité de faire fonctionner des conteneurs sans être root qui sera très appréciée dans le monde de l'entreprise.
Les projets frères que sont Buildah et Skopeo méritent eux aussi d'être explorés pour des besoins avancés (il reste tout à fait possible de faire un podman build
, par exemple, pour les besoins standards).
Comments
No comments yet. Be the first to react!