Podman - Gestion du stockage

Dans le cas d’un conteneur faisant office de server Web ou de BDD, il sera sans doute nécessaire d’accrocher un stockage persistant ou un accès à d’autres réseaux.

Stockage persistant de conteneur

Par défaut, toutes les nouvelles données écrite dans le conteneur sont perdues après sa suppression.

Pour conserver les données, l’option --volume (-v) permets d’utiliser le système de fichier de l’hôte (et prévoir les bonnes autorisations).

Mappage UID/GID

La commande podman unshare cat permet d’afficher le mappage UID/GID :

$ podman unshare cat /proc/self/uid_map
0 1000 1 // root
1 100000 65536 // Correspondance entre le conteneur et l'hôte
$ podman unshare cat /proc/self/gid_map
0 1000 1 // root
1 100000 65536 // Correspondance entre le conteneur et l'hôte

La commande podman exec affiche l’UID et le GID de l’user mysql à l’intérieur du conteneur qui s’exécute avec le stockage non persistant :

$ podman exec -it my_db_01 grep mysql /etc/passwd
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin

Stockage persistant

Création d’un répertoire sur l’hôte :

$ mkdir /home/projet/db_data

Mappage des UID/GID :

$ podman unshare chown 27:27 /home/projet/db_data

Afficher la mise en correspondance (27:27 -> 100026:100026) :

$ ls -l /home/projet/
total 0
drwxrwxr-x. 3 100026 100026 18 May 5 14:37 db_data
[...]

Monter le répertoire avec l’option -d de podman run -d :

$ podman run -d --name my_db_01 \
-e MYSQL_USER=luci \
-e MYSQL_PASSWORD=Luci3v1l \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=Aw3s0m3P4SS! \
-v /home/projet/db_data:/var/lib/mysql \
my.com.pany.org/rhel8/MYSQL-105

Maintenant il faut définir le contexte SELinux.

Contextes SELinux pour le stockage de conteneurs

La commande podman container logs affiche aussi les erreurs d’autorisation, ici pour /var/lib/mysql/db_data :

$ podman container logs my_db_01
[...]
---> 16:41:25 Initializing database ...
---> 16:41:25 Running mysql_install_db ...
mkdir: cannot create directory '/var/lib/mysql/db_data': Permission denied
Fatal error Can't create database directory '/var/lib/mysql/db_data'

Cette erreur se produit à cause du contexte SELinux défini sur /home/projet/db_data sur l’hôte.

Il faut définir le contexte SELinux container_file_t avant de monter le répertoire en tant que stockage persistant.

La commande podman run -v /home/projet/db_data:/var/lib/ mysql:Z défini le contexte SELinux de /home/projet/db_data quand il sera monté comme stockage persistant pour /var/lib/mysql :

$ podman run -d --name my_db_01 \
-e MYSQL_USER=luci \
-e MYSQL_PASSWORD=Luci3v1l \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=Aw3s0m3P4SS! \
-v /home/projet/db_data:/var/lib/mysql:Z \
my.com.pany.org/rhel8/MYSQL-105

Vérifier le contexte sur /home/projet/ :

$ ls -Z /home/projet/
system_u:object_r:container_file_t:s0:c81,c1009 db_data
[...]

/!\ Résumé des commandes

Commandes :

$ podman unshare cat /proc/self/uid_map
$ podman unshare cat /proc/self/gid_map
$ podman exec -it my_db_01 grep mysql /etc/passwd
$ podman unshare chown 27:27 /home/projet/db_data

$ podman run -d --name my_db_01 \
-e MYSQL_USER=luci \
-e MYSQL_PASSWORD=Luci3v1l \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=Aw3s0m3P4SS! \
-v /home/projet/db_data:/var/lib/mysql \
my.com.pany.org/rhel8/MYSQL-105

$ podman container logs my_db_01

$ podman run -d --name my_db_01 \
-e MYSQL_USER=luci \
-e MYSQL_PASSWORD=Luci3v1l \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=Aw3s0m3P4SS! \
-v /home/projet/db_data:/var/lib/mysql:Z \
my.com.pany.org/rhel8/MYSQL-105

$ ls -Z /home/projet/

Fichiers :

/proc/self/uid_map
/proc/self/gid_map

Cas pratique

But :

  • Passer des variables d’environnement à un conteneur lors de la création
  • Monter le stockage persistant sur un conteneur
  • Créer et connecter plusieurs réseaux de conteneurs
  • Ouvrir les ports de conteneur à partir de la machine hôte

Résultats :

  • Créer des réseaux de conteneurs et les connecter à des conteneurs
  • Résoudre les problèmes liés aux conteneurs défaillants
  • Transmettre les variables d’environnement aux conteneurs lors de la création
  • Créer et monter un stockage persistant sur des conteneurs
  • Mapper les ports de l’hôte sur les ports à l’intérieur des conteneurs

La commande podman network create avec les options --subnet et --gateway permet de créer le réseau frontend et le sous-réseau 10.89.1.0/24 et la passerelle 10.89.1.1 :

[aline@SERVER01 ~]$ podman network create --subnet 10.89.1.0/24 --gateway 10.89.1.1 frontend
frontend

Connexion au registre localhost:5000 (si pas défini, connexion à localhost:5000):

[aline@SERVER01 ~]$ podman login localhost:5000
Username: <userName>
Password: <p4ssW0rd>
Error: authenticating creds for "localhost:5000": pinging container registry localhost:5000: Get "http://localhost:5000/v2/": dial tcp 127.0.0.1:80: connect: connection refused
[aline@SERVER01 ~]$ podman login podman login localhost:5000
Username: <..vide..>
Password: <..vide..>
Login Succeeded!

La commande suivante permet de :

  • run -d --name db_client : démarrer en arrière-plan un conteneur nommé db_client
  • --network frontend : qui sera onnecté au réseau frontend
  • -v /etc/yum.repos.d:/etc/yum.repos.d : qui sera monté au répertoire des paquets (pour pouvoir en installer au sein du conteneur)
  • localhost:5000/ubi9/ubi : utilisera l’image dans le localhost
  • sleep infinity : et tournera en boucle

Sur une seule ligne :

[aline@SERVER01 ~]$ podman run -d --name db_client --network frontend -v /etc/yum.repos.d:/etc/yum.repos.d localhost:5000/ubi9/ubi sleep infinity

Sur plusieurs, pour la visibilité et la compréhension :

[aline@SERVER01 ~]$ podman run -d --name db_client \
--network frontend \
-v /etc/yum.repos.d:/etc/yum.repos.d \
localhost:5000/ubi9/ubi \
sleep infinity
e5758bd4f6a98ac6642298c22c6557271601f302c30396474a62c5ab7d4763f5

Vérification :

[root@Redhat1-Test5 ~]# podman ps
CONTAINER ID  IMAGE                           COMMAND         CREATED        STATUS        PORTS  NAMES
e5758bd4f6a9 localhost:5000/ubi9/ubi:latest sleep infinity 8 minutes ago Up 8 minutes db_client

Utilisation de l’image localhost:5000/my-mysql pour démmarer un conteneur en arrière-plan nommé my_db_01 en le connectant au réseau frontend :

[aline@SERVER01 ~]$ podman run -d --name my_db_01 --network frontend localhost:5000/my-mysql
653d5a77d36e224a7ebe20e6b36f9909771b1a61304e9f9e4a253d00817285dd

Affichage de tous les conteneurs :

[aline@SERVER01 ~]$ podman ps -a
CONTAINER ID  IMAGE                           COMMAND         CREATED             STATUS            PORTS     NAMES
e5758bd4f6a9 localhost:5000/ubi9/ubi:latest sleep infinity About an hour ago Up About an hour db_client
653d5a77d36e localhost:5000/my-mysql:latest mysqld 46 seconds ago Up 47 seconds my_db_o1

Affichage des journaux du conteneur pour déterminer pourquoi il s’est arrêté :

[aline@SERVER01 ~]$ podman container logs `my_db_01`
[...]
You must either specify the following environment variables:
MYSQL_USER (regex: '^[a-zA-Z0-9_]+$')
MYSQL_PASSWORD (regex: '^[a-zA-Z0-9_~!@#$%^&*()-=<>,.?;:|]+$')
MYSQL_DATABASE (regex: '^[a-zA-Z0-9_]+$')
Or the following environment variable:
MYSQL_ROOT_PASSWORD (regex: '^[a-zA-Z0-9_~!@#$%^&*()-=<>,.?;:|]+$')
Or both.
[...]

Supression du conteneur my_db_01 et recréation mais avec des variables d’environnement :

[aline@SERVER01 ~]$ podman rm my_db_01
3e767ae6eea4578152a216beb5ae98c8ef03a2d66098debe2736b8b458bab405
[aline@SERVER01 ~]$ podman run -d --name my_db_01 \
--network frontend \
-e MYSQL_USER=dev1 \
-e MYSQL_PASSWORD=MyPass \
-e MYSQL_DATABASE=devdb \
-e MYSQL_ROOT_PASSWORD=My5UP3RPass \
localhost:5000/my-mysql
c0e8da319abef6e3b24fd85414353ea66a224a14c0a791aae1e1bd0ccf07ec8c

Affichage des conteneurs en cours d’exécution :

[aline@SERVER01 ~]$ podman ps
CONTAINER ID  IMAGE                             COMMAND         CREATED         STATUS         PORTS   NAMES
e5758bd4f6a9 localhost:5000/ubi9/ubi:latest sleep infinity 2 hours ago Up 2 hours db_client
c0e8da319abe localhost:5000/my-mysql:latest mysqld 36 seconds ago Up 36 seconds my_db_01

Création d’un stockage persistant pour le service MYSQL en conteneur et mappage du port 13306 de la machine locale sur le port 3306 dans le conteneur. Autorisation du trafic vers le port 13306 sur la machine SERVER01.

Création d’un stockage persistant /home/aline/databases pour le service MYSQL en conteneur sur la machine locale :

[aline@SERVER01 ~]$ mkdir /home/aline/databases

Recherche de l’UID et du GID mysql du conteneur my_db_01 :

[aline@SERVER01 ~]$ podman exec -it my_db_01 grep mysql /etc/passwd
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin

Arrêt et supression du conteneur my_db_01 :

[aline@SERVER01 ~]$ podman stop my_db_01
[aline@SERVER01 ~]$ podman rm my_db_01

Exécution de la commande chown à l’intérieur de l’espace de noms du conteneur, puis définition de l’utilisateur et du groupe propriétaire sur 27 dans le répertoire /home/aline/database :

[aline@SERVER01 ~]$ podman unshare chown 27:27 /home/aline/databases/
[aline@SERVER01 ~]$ ls -l /home/aline/
total 0
drwxr-xr-x. 2 100026 100026 6 May 9 17:40 databases

Création du conteneur my_db_01 et montage du répertoire /home/aline/databases de la machine SERVER01 dans le répertoire /var/lib/mysql à l’intérieur du conteneur my_db_01. L’option Z permet d’appliquer le contexte SELinux requis :

[aline@SERVER01 ~]$ podman run -d --name my_db_01 \
--network frontend \
-e MYSQL_USER=dev1 \
-e MYSQL_PASSWORD=devpass \
-e MYSQL_DATABASE=devdb \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/aline/databases:/var/lib/mysql:Z \
-p 13306:3306 \
localhost:5000/my-mysql

Intallation du paquetage MYSQL dans le conteneur db_client :

[aline@SERVER01 ~]$ podman exec -it db_client dnf install -y MYSQL
[...]
Complete!

Création de la table user_data dans la base de données dev_db dans le conteneur my_db_01 à partir du conteneur db_client :

[aline@SERVER01 ~]$ podman exec -it db_client mysql -u dev1 -p -h my_db_01
Enter password: devpass
[...]
MYSQL [(none)]> USE devdb;
Database changed
MYSQL [devdb]> CREATE TABLE user_data(column1 int);
Query OK, 0 rows affected (0.036 sec)
MYSQL [devdb]> SHOW TABLES;
+-----------------+
| Tables_in_devdb |
+-----------------+
| user_data |
+-----------------+
1 row in set (0.001 sec)
MYSQL [devdb]> quit
Bye

Autorisation du trafic vers le port 13306 dans le pare-feu sur la machine SERVER01 :

[aline@SERVER01 ~]$ sudo firewall-cmd --add-port=13306/tcp --permanent
[sudo] password for aline: aline
success
[aline@SERVER01 ~]$ sudo firewall-cmd --reload
success

Sur SERVER02, se connecter au client MYSQL atteindre la machine SERVER01 sur le port 13306 et afficher les tables du conteneur my_db_01 stockées dans le stockage persistant :

[aline@SERVER02 ~]$ mysql -u dev1 -p -h SERVER01 --port 13306 devdb -e 'SHOW TABLES';
Enter password: devpass
+-----------------+
| Tables_in_devdb |
+-----------------+
| user_data |
+-----------------+

Création d’un 2ème réseau de conteneurs backend avec le sous-réseau 10.90.0.0/24 et la passerelle 10.90.0.1. :

[aline@SERVER01 ~]$ podman network create --subnet 10.90.0.0/24 --gateway 10.90.0.1 backend
backend

Connexion au réseau de conteneurs backend aux conteneurs db_client et my_db_01 :

[aline@SERVER01 ~]$ podman network connect backend db_client
[aline@SERVER01 ~]$ podman network connect backend my_db_01

Récupération des adresses IP du conteneur my_db_01 :

[aline@SERVER01 ~]$ podman inspect my_db_01
[...]
"Networks": {
"backend": {
"EndpointID": "",
"Gateway": "10.90.0.1",
"IPAddress": "10.90.0.3",
[...]
"frontend": {
"EndpointID": "",
"Gateway": "10.89.1.1",
"IPAddress": "10.89.1.5",
[...]

Installation du paquetage iputils dans le conteneur db_client :

[aline@SERVER01 ~]$ podman exec -it db_client dnf install -y iputils
[...]
Complete!

Test ping sur le nom du conteneur my_db_01 à partir du conteneur db_client :

[aline@SERVER01 ~]$ podman exec -it db_client ping -c4 my_db_01
PING my_db_01.dns.podman (10.90.0.3) 56(84) bytes of data.
[...]
--- my_db_01.dns.podman ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3048ms rtt min/avg/max/mdev = 0.043/0.049/0.054/0.004 ms

Documentation

MAN podman(1)
MAN podman-exec(1)
MAN podman-info(1)
MAN podman-network(1)
MAN podman-network-create(1)
MAN podman-network-inspect(1)
MAN podmannetwork-ls(1)
MAN podman-port(1)
MAN podman-run(1)
MAN podman-unshare(1)

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/building_running_and_managing_containers/assembly_working-withcontainers_building-running-and-managing-containers

> Partager <