Podman - Conteneurs en tant que service

Vérifier la santé des disques, les commandes diffères en fontion d’un SSD et d’un NVME

Conteneurs en tant que service

Création de fichiers utilisateur systemd pour les conteneurs

Il est possible de définir manuellement les services systemd dans le répertoire ~/.config/systemd/user/.

La commande podman generate systemd permet de configurer le service systemd afin de créer le conteneur lorsque le service démarre :

$ podman generate systemd --name mywebserver
[...]
ExecStart=/usr/bin/podman start mywebserver
ExecStop=/usr/bin/podman stop -t 10 mywebserver
ExecStopPost=/usr/bin/podman stop -t 10 mywebserver
[...]

Les paramètres :

  • ExecStart : systemd exécute la commande podman start pour démarrer le conteneur existant
  • ExecStop : systemd exécute la commande podman stop pour arrêter le conteneur (ne sera PAS supprimé)
  • ExecStopPost : systemd rappelle la commande si le service n’a pas démarré correctement ou est arrété

La commande podman generate systemd permet de configurer le service systemd afin de créer le conteneur lorsque le service démarre, et de supprimer le conteneur lorsque le service s’arrête avec l’option --new :

$ podman generate systemd --name mywebserver --new
[...]
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --
sdnotify=conmon --replace -d --name mywebserver -p 8080:8080 -v /home/john-adm/
app-artifacts:/var/www/html:Z registry.access.redhat.com/ubi8/httpd-24
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
[...]

Les paramètres :

  • ExecStart : systemd exécute la commande podman run pour créer et démarrer le nouveau conteneur puis lance un podman run --rm
  • ExecStop : systemd exécute la commande podman stop pour arrêter le conteneur
  • ExecStopPost : systemd appelle la commande podman rm -f quand le service est arrété

La commande podman generate systemd avec l’option --files permet de créer le fichier utilisateur systemd dans le répertoire actuel et comme le stockage est persistant ici, il faut également préciser --new :

$ podman generate systemd --name mywebserver --new --files
/home/john-adm/container-mywebserver.service

Création du répertoire ~/.config/systemd/user/ :

$ mkdir -p ~/.config/systemd/user/

Déplacement vers un nouvel emplacement :

$ mv container-mywebserver.service ~/.config/systemd/user/

Gestion des fichiers utilisateur systemd pour les conteneurs

L’option --user de la commande systemctl permet de gérer le conteneur mywebserver avec un nouvel utilisateur :

$ systemctl --user daemon-reload
$ systemctl --user start container-mywebserver.service
$ systemctl --user status container-mywebserver.service
● container-mywebserver.service - Podman container-mywebserver.service
Loaded: loaded (/home/john-adm/.config/systemd/user/container-mywebserver.service; disabled; vendor preset: disabled)
Active: active (running) since Thu 2022-04-28 21:22:26 EDT; 18s ago
Docs: man:podman-generate-systemd(1)
Process: 31560 ExecStartPre=/bin/rm -f /run/user/1003/containermywebserver.service.ctr-id (code=exited, status=0/SUCCESS)
Main PID: 31600 (conmon)
[...]

Listing des conteneurs :

$ podman ps
CONTAINER ID	IMAGE											COMMAND				 CREATED	  STATUS	PORTS					NAMES
18eb00f42324 registry.access.redhat.com/ubi8/httpd-24:latest /usr/bin/runhttp... 28 sec ago Up 29 sec 0.0.0.0:8080->8080/tcp mywebserver
Created symlink /home/john-adm/.config/systemd/user/default.target.wants/container-mywebserver.service → /home/john-adm/.config/systemd/user/containermywebserver.service.

Note : Si un conteneur est configuré avec systemd, ce dernier surveille l’état du conteneur et le redémarre en cas de défaillance. Il ne faut PAS utiliser la commande podman pour démarrer ou arrêter ce conteneurs (conflit)

Gestion des conteneurs en root avec systemd

Les fichiers de service fonctionnent comme des fichiers d’unité systemd courants (comme un utilisateur particulier).

Exceptions :

  • Ne pas faire un utilisateur dédié pour la gestion des conteneurs
  • Le fichier de service doit se placer dans /etc/systemd/system et pas dans ~/.config/systemd/user
  • Commande systemctl sans l’option --user
  • Ne pas exécuter loginctl enable-linger en tant que root

Comparaison entre les services système et utilisateur

Résumé des répertoires et commandes utilisées entre les services système et utilisateur systemd :

x Services système Services d’utilisateurs
Stockage des fichiers d’unité personnalisés /etc/systemd/system/unit.service ~/.config/systemd/user/unit.service
Rechargement des fichiers d’unité # systemctl daemon-reload $ systemctl --user daemon-reload
Démarrage et arrêt d’un service # systemctl start UNIT
# systemctl stop UNIT
$ systemctl --user start UNIT
$ systemctl --user stop UNIT
Démarrage d’un service lors du démarrage de la machine # systemctl enable UNIT $ loginctl enable-linger
$ systemctl --user enable UNIT

Conteneurs lancés au démarrage

La commande loginctl enable-linger permet au service de démarrer en même temps que le système et de rester persistant lorsque l’utilisateur se déconnecte :

$ loginctl show-user john-adm
[...]
Linger=no
$ loginctl enable-linger
$ loginctl show-user john-adm
[...]
Linger=yes

Pour annuler l’opération : loginctl disable-linger.

/!\ Résumé des commandes

Commandes :

$ podman generate systemd --name mywebserver			// Configurer le service systemd qui créera le conteneur à son démarrage
$ podman generate systemd --name mywebserver --new // Configurer le service systemd qui créera le conteneur à son démarrage et le supprimera à son arrêt
$ podman generate systemd --name mywebserver --files // Créer le fichier utilisateur systemd dans le répertoire actuel
$ podman generate systemd --name mywebserver --new --files // Créer le fichier utilisateur systemd dans le répertoire actuel persistant

// Gérer le conteneur mywebserver avec un nouvel utilisateur
$ systemctl --user daemon-reload
$ systemctl --user start container-mywebserver.service
$ systemctl --user status container-mywebserver.service

// Rechargement des fichiers d’unité
# systemctl daemon-reload // Système
$ systemctl --user daemon-reload // Utilisateur

// Démarrage et arrêt d’un service
# systemctl start UNIT // Système
# systemctl stop UNIT // Système
$ systemctl --user start UNIT // Utilisateur
$ systemctl --user stop UNIT // Utilisateur

// Démarrage d’un service lors du démarrage de la machine
# systemctl enable UNIT // Système
$ loginctl enable-linger // Utilisateur
$ systemctl --user enable UNIT // Utilisateur

// Démarrer le service en même temps que le système et de rester persistant lorsque l’utilisateur se déconnecte
$ loginctl enable-linger
$ loginctl disable-linger // Annuler

Fichiers :

// Stockage des fichiers d’unité personnalisés
/etc/systemd/system/unit.service // Système
~/.config/systemd/user/unit.service // Utilisateur

Cas pratique

Gestion des conteneurs en tant que services système

But :

  • Configurer un conteneur pour le gérer en tant que service systemd
  • Le faire démarrer automatiquement lors du démarrage de la machine hôte

Création d’un compte d’utilisateur appelé cpteservice avec pour mdp P123+ pour exécuter les conteneurs en tant que services systemd.

[aline@SERVER01 ~]$ sudo useradd cpteservice
[aline@SERVER01 ~]$ sudo passwd cpteservice

Pour la gestion des services d’utilisateurs systemd avec le compte cpteservice, il faut se connecter directement en tant qu’utilisateur cpteservice.

[aline@SERVER-BASE ~]$ ssh cpteservice@SERVER01
[...]
[cpteservice@SERVER01 ~]$

Configuration de l’accès au registre du labo registry.localhost.org dans le répertoire personnel de cpteservice :

Création du répertoire ~/.config/containers/ :

[cpteservice@SERVER01 ~]$ mkdir -p ~/.config/containers/

Copie du fichier /tmp/containers-services/registries.conf dans le répertoire ‘~/.config/containers/‘ :

[cpteservice@SERVER01 ~]$ cp /tmp/containers-services/registries.conf ~/.config/containers/

Vérification de l’accès au registre registry.localhost.org. Si tout est ok, la commande doit lister certaines images :

[cpteservice@SERVER01 ~]$ podman search ubi
NAME DESCRIPTION
registry.localhost.org/ubi7/ubi
registry.localhost.org/ubi8/ubi
registry.localhost.org/ubi9-beta/ubi

Création du répertoire ~/webcontent/html/.

[cpteservice@SERVER01 ~]$ mkdir -p ~/webcontent/html/

Création du fichier index.html et ajout de la ligne Hello World.

[cpteservice@SERVER01 ~]$ echo "Hello World" > ~/webcontent/html/index.html

Vérification des droits sur r-x dans webcontent/html et sur r-- pour index.html :

[cpteservice@SERVER01 ~]$ ls -ld webcontent/html/
drwxr-xr-x. 2 cpteservice cpteservice 24 Aug 28 04:56 webcontent/html/
[cpteservice@SERVER01 ~]$ ls -l webcontent/html/index.html
-rw-r--r--. 1 cpteservice cpteservice 12 Aug 28 04:56 webcontent/html/index.html

Connexion au registry.localhost.org :

[cpteservice@SERVER01 ~]$ podman login registry.localhost.org

Utilisation de l’image registry.localhost.org/rhel8/httpd-24:1-163 pour exécuter un conteneur appelé webapp en mode détaché et Rediriction du port 8080 sur l’hôte local vers le port de conteneur 8080 et montage du répertoire ~/webcontent sur SERVER01 au répertoire /var/www dans le conteneur :

[cpteservice@SERVER01 ~]$ podman run -d --name webapp -p 8080:8080 -v ~/webcontent:/var/www:Z registry.localhost.org/rhel8/httpd-24:1-163
750a681bd37cb6825907e9be4347eec2c4cd79550439110fc6d41092194d0e06
[...]

Vérification que le service Web fonctionne sur le port 8080 :

[cpteservice@SERVER01 ~]$ curl http://localhost:8080
Hello World

Création du répertoire ~/.config/systemd/user/ :

[cpteservice@SERVER01 ~]$ mkdir -p ~/.config/systemd/user/
[cpteservice@SERVER01 ~]$ cd ~/.config/systemd/user

Création du fichier d’unité pour le conteneur webapp (l’option --new pour que systemd crée un conteneur lors du démarrage du service et supprime le conteneur lors de l’arrêt du service) :

[cpteservice@SERVER01 user]$ podman generate systemd --name webapp --files --new
/home/cpteservice/.config/systemd/user/container-webapp.service

Arrêt, puis suppression du conteneur webapp :

[cpteservice@SERVER01 user]$ podman stop webapp
webapp
[cpteservice@SERVER01 user]$ podman rm webapp
750a681bd37cb6825907e9be4347eec2c4cd79550439110fc6d41092194d0e06
[cpteservice@SERVER01 user]$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Rechargement de la configuration du daemon systemd :

[cpteservice@SERVER01 user]$ systemctl --user daemon-reload

Activation et démarrage du service container-webapp :

[cpteservice@SERVER01 user]$ systemctl --user enable --now container-webapp
Created symlink /home/cpteservice/.config/systemd/user/default.target.wants/containerwebapp.service → /home/cpteservice/.config/systemd/user/container-webapp.service.

Verification que le serveur Web répond :

[cpteservice@SERVER01 user]$ curl http://localhost:8080
Hello World

Vérification que le conteneur est en cours d’exécution :

[cpteservice@SERVER01 user]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e996db98071 registry.access.redhat.com/ubi8/httpd-24:1-163 /usr/bin/run-http 3 minutes Up 0.0.0.0:8080->8080/tcp webapp

Utilisation des informations d’ID du conteneur pour vérifier que le daemon systemd crée un conteneur lorsque le service demmare. Arrêt du service container-webapp et le conteneur devrait se supprimer automatiquement :

[cpteservice@SERVER01 user]$ systemctl --user stop container-webapp
[cpteservice@SERVER01 user]$ podman ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Démarrage du service container-webapp :

[cpteservice@SERVER01 user]$ systemctl --user start container-webapp
[cpteservice@SERVER01 user]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4584b4df514c registry.access.redhat.com/ubi8/httpd-24:1-163 /usr/bin/run-http... 6 seconds ago Up 7 seconds ago 0.0.0.0:8080->8080/tcp webapp

Vérification que les services de l’utilisateur cpteservice démarrent au démarrage du système

Commande loginctl enable-linger :

[cpteservice@SERVER01 user]$ loginctl enable-linger
[cpteservice@SERVER01 user]$ loginctl show-user cpteservice
[...]
Linger=yes

Lors du reboot de la machine, le conteneur doit être en cours d’exécution :

[cpteservice@SERVER01 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6c325bf49f84 registry.access.redhat.com/ubi8/httpd-24:1-163 /usr/bin/run-http... 6 seconds ago Up 9 minutes ago 0.0.0.0:8080->8080/tcp webapp

Accès au contenu Web :
[cpteservice@SERVER01 ~]$ curl http://localhost:8080
Hello World

Exécution des conteneurs

But :

  • Configurer un conteneur avec un service de BDD MariaDB
  • Stocke la base de données sur un stockage persistant
  • Démarre automatiquement avec le serveur

Installation du paquetage container-tools :

[aline@SERVER02 ~]$ sudo dnf install container-tools
[...]
Is this ok [y/N]: y
[...]
Complete!

L’image mariadb-perso de conteneur est stockée sur registry.localhost.org.

Connexion à SERVER02 en tant qu’utilisateur pod-service :

[aline@SERVER-BASE ~]$ ssh pod-service@SERVER02
[...]
[pod-service@SERVER02 ~]$

Configuration de l’accès au registre de labo registry.localhost.org dans le répertoire personnel de l’utilisateur pod-service :

[pod-service@SERVER02 ~]$ mkdir -p ~/.config/containers/
[pod-service@SERVER02 ~]$ cp /tmp/registries.conf ~/.config/containers/

Connexion au registre de conteneurs avec la commande podman login :

[pod-service@SERVER02 ~]$ podman login registry.localhost.org

Affichage des informations sur l’image registry.localhost.org/mariadb-perso, la balise de version la plus basse est la version 1-86 :

[pod-service@SERVER02 ~]$ skopeo inspect docker://registry.localhost.org/mariadb-perso
{
"Name": "registry.localhost.org/mariadb-perso",
"Digest": "sha256:a95b...4816",
"RepoTags": [
"1-86",
"1-102",
"latest"
],
[...]

Création du répertoire /home/pod-service/db_data et configuration pour que les conteneurs aient un accès en lecture/écriture.

Déclaration des variables pour le conteneur :

Variable Valeur
MYSQL_USER operator1
MYSQL_PASSWORD redhat
MYSQL_DATABASE inventory
MYSQL_ROOT_PASSWORD redhat

Démarrage du conteneur détaché db_01 pour obtenir l’UID et le GID mysql en spécifiant la balise de version la plus basse (1-86) :

[pod-service@SERVER02 ~]$ podman run -d --name db_01 -p 13306:3306 \
-e MYSQL_USER=operator1 \
-e MYSQL_PASSWORD=redhat \
-e MYSQL_DATABASE=inventory \
-e MYSQL_ROOT_PASSWORD=redhat \
registry.localhost.org/mariadb-perso:1-86
[...]
c33f85d177dc8c51a303e231e6be63c1f251b9d426b4ccb56498603ab72d4219

Création du répertoire /home/pod-service/db_data :

[pod-service@SERVER02 ~]$ mkdir /home/pod-service/db_data

Récupération de l’UID et du GID mysql du conteneur db_01

[pod-service@SERVER02 ~]$ podman exec -it db_01 grep mysql /etc/passwd
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin

Arrêt et suppression du conteneur db_01 :

[pod-service@SERVER02 ~]$ podman stop db_01
db_01
[pod-service@SERVER02 ~]$ podman rm db_01
c33f85d177dc8c51a303e231e6be63c1f251b9d426b4ccb56498603ab72d4219

Définition de l’UID et du GID de l’espace de noms de l’utilisateur 27 en tant que propriétaire du répertoire avec odman unshare :

[pod-service@SERVER02 ~]$ podman unshare chown 27:27 /home/pod-service/db_data

Création du conteneur.

[pod-service@SERVER02 ~]$ podman run -d --name inventorydb -p 13306:3306 \
-e MYSQL_USER=operator1 \
-e MYSQL_PASSWORD=redhat \
-e MYSQL_DATABASE=inventory \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/pod-service/db_data:/var/lib/mysql/data:Z \
registry.localhost.org/mariadb-perso:1-86

Vérification que la base de données est en cours d’exécution :

[pod-service@SERVER02 ~]$ ~/containers-review/testdb.sh
Testing the access to the database...
SUCCESS

Création du répertoire ~/.config/systemd/user/ :

```
[pod-service@SERVER02 ~]$ mkdir -p ~/.config/systemd/user/

Création du fichier d’unité systemd à partir du conteneur en cours d’exécution :

[pod-service@SERVER02 ~]$ cd ~/.config/systemd/user/
[pod-service@SERVER02 user]$ podman generate systemd --name inventorydb --files --new
/home/pod-service/.config/systemd/user/container-inventorydb.service

Arrêt du conteneur inventorydb :

[pod-service@SERVER02 user]$ podman stop inventorydb
inventorydb

Suppression du conteneur inventorydb :

[pod-service@SERVER02 user]$ podman rm inventorydb
0d28f0e0a4118ff019691e34afe09b4d28ee526079b58d19f03b324bd04fd545

Configuration du daemon systemd pour recharger sa configuration :

[pod-service@SERVER02 user]$ systemctl --user daemon-reload

Activation et démarrage du service service container-inventorydb :

[pod-service@SERVER02 user]$ systemctl --user enable --now container-inventorydb.service
Created symlink /home/pod-service/.config/systemd/user/default.target.wants/container-inventorydb.service → /home/pod-service/.config/systemd/user/containerinventorydb.service.

Vérification que le conteneur est en cours d’exécution :

[pod-service@SERVER02 user]$ ~/containers-review/testdb.sh
Testing the access to the database...
SUCCESS
[pod-service@SERVER02 user]$ podman ps
CONTAINER ID	IMAGE										COMMAND		CREATED		STATUS	PORTS					NAMES
3ab24e7f000d registry.localhost.org/mariadb-perso:1-86 run-mysqld 7 min Up 0.0.0.0:13306->3306/tcp inventorydb

La commande loginctl enable-linger permet aux services utilisateur de démarrer automatiquement au reboot :

[pod-service@SERVER02 ~]$ loginctl enable-linger

Documentation

MAN loginctl(1)
MAN systemd.unit(5)
MAN systemd.service(5)
MAN subuid(5)
MAN podman-generate-systemd(1)

https://www.youtube.com/watch?v=AGkM2jGT61Y

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/htmlsingle/building_running_and_managing_containers/index

> Partager <