📘 RĂ©seaux virtuels et dĂ©ploiements multi-conteneurs

1. Problématique

Nous avons vu qu’un processus doit souvent communiquer avec d’autres processus (et donc d’autres logiciels) pour fonctionner. Par exemple, le processus d’un site web doit souvent communiquer avec le processus d’une base de donnĂ©es, par exemple pour demander Ă  ce dernier de stocker des informations.

IdĂ©alement, lors d’un dĂ©ploiement qui implique plusieurs logiciels, nous souhaitons que chaque logiciel soit isolĂ© dans son propre conteneur, pour faciliter son dĂ©ploiement et pour lui offrir le meilleur environnement. Nous appelons ce type de dĂ©ploiement un dĂ©ploiement multi-conteneurs.

Cependant, une question technique doit ĂȘtre rĂ©solue pour permettre ce type de dĂ©ploiement : comment permettre Ă  des processus situĂ©s dans des conteneurs diffĂ©rents de communiquer entre eux ?

Nous avons vu dans un chapitre prĂ©cĂ©dent qu’il Ă©tait possible pour un conteneur de publier un port rĂ©seau. Malheureusement, ce mĂ©chanisme ne sera pas suffisant pour un dĂ©ploiement multi-conteneurs: une publication de port permet uniquement Ă  un processus extĂ©rieur Ă  l’environnement d’accueil de communiquer avec un processus situĂ© dans le conteneur.

Pour résoudre ce problÚme, dans ce (bref) chapitre nous allons apprendre le principe du réseau virtuel, qui permet de relier plusieurs conteneurs entre eux via un réseau purement logiciel.

2. Principe

La publication de port permet de rĂ©pondre Ă  une situation oĂč un processus extĂ©rieur Ă  l’environnement d’accueil souhaite communiquer avec un processus Ă  l’intĂ©rieur d’un conteneur de l’environnement d’accueil.

Cependant, que faire lorsque deux processus souhaitent communiquer alors qu’ils sont dans le mĂȘme environnement d’accueil, mais chacun dans un conteneur diffĂ©rent ?

Exemple 1. ProblĂšme de communication depuis l’extĂ©rieur vers Simplestblog conteneurisĂ©

On considĂšre Ă  nouveau, Simplestblog, un logiciel qui s’exĂ©cute sous la forme d’un serveur web. Cette fois-ci, on se focalise sur le fait que Simplestblog stocke ses donnĂ©es dans un systĂšme de gestion de base de donnĂ©es (SGBD) via un logiciel Ă  part appelĂ© MariaDB. Dans ce contexte, c’est Simplestblog qui joue le rĂŽle de processus client qui se contacte au processus serveur du SGBD.

Supposons que :

  • Simplestblog s’exĂ©cute au sein d’un conteneur dans un environnement d’accueil.

  • MariaDB s’exĂ©cute au sein d’un second conteneur dans le mĂȘme environnement d’accueil.

  • Le processus MariaDB Ă©coute sur le port 3306 et attend qu’un processus client se connecte pour lire ou Ă©crire des entrĂ©es dans la base de donnĂ©es.

    MĂȘme si MariaDB Ă©coute sur un port rĂ©seau, ce n’est pas une publication de port puisqu’il n’y a aucun lien dĂ©fini avec un port de l’interface rĂ©seau de l’environnement d’accueil.

Schématiquement, nous avons donc la situation suivante :

simplestblog networking problem.drawio
Ce schéma ne montre volontairement pas la publication de port définie dans la partie précédente, pour nous concentrer sur le problÚme de communication inter-conteneurs.

ProblĂšme : mĂȘme si MariaDB Ă©coute bien sur un port rĂ©seau, il est impossible pour Simplestblog de s’y connecter puisque les deux conteneux ne sont pas sur un mĂȘme rĂ©seau informatique.

Pour remĂ©dier Ă  ce type de situation, il est possible de relier diffĂ©rents conteneurs d’un mĂȘme environnement Ă  l’aide d’un rĂ©seau virtuel. Un rĂ©seau virtuel est un type de rĂ©seau purement logiciel (tout comme le rĂ©seau de rebouclage propre Ă  chaque environnement) qui existe virtuellement au sein d’un environnement d’accueil donnĂ©. À sa crĂ©ation, un conteneur peut ĂȘtre connectĂ© Ă  un rĂ©seau virtuel Ă  l’aide de son interface rĂ©seau virtuelle.

Par dĂ©faut, au sein d’un rĂ©seau virtuel, le nom d’hĂŽte d’un conteneur est le nom donnĂ© au conteneur Ă  sa crĂ©ation.
networking.drawio

L’illustration ci-dessus prĂ©sente trois conteneurs dans le mĂȘme environnement d’accueil. On crĂ©e deux rĂ©seaux virtuels, Ă  savoir R1 et R2. On ajoute les conteneurs A et B au rĂ©seau R1, et les conteneurs B et C au rĂ©seau R2.

  • Sur le rĂ©seau R2, les conteneurs B et C peuvent se contacter mutuellement. Par exemple, un processus exĂ©cutĂ© dans C peut se connecter sur le port 465 du conteneur B (ou Ă©crit autrement, peut se connecter Ă  B:465).

  • Sur le rĂ©seau R1, les conteneurs A et B peuvent se contacter mutuellement. Par exemple, un processus exĂ©cutĂ© dans B peut se connecter sur le port 5000 du conteneur A (ou Ă©crit autrement, peut se connecter Ă  A:5000).

Quelques points importants pour bien comprendre le cas général :

  • Un conteneur peut ĂȘtre sur plusieurs rĂ©seaux virtuels simultanĂ©ment. C’est par exemple le cas ici du conteneur B.

  • Il est Ă©galement possible qu’un rĂ©seau virtuel connecte plus de deux conteneurs simultanĂ©ment.

  • Contrairement Ă  la publication de port, la crĂ©ation et l’usage de rĂ©seaux virtuels est complĂ©tement sĂ©parĂ©e des interfaces rĂ©seaux matĂ©rielles de l’environnement d’accueil. Par exemple ici l’interface ethernet n’est absolument pas concernĂ©e par la mise en rĂ©seau purement logicielle des diffĂ©rents conteneurs entre eux.

Exemple 2. Relier Simplestblog à sa base de données avec un réseau virtuel

Pour permettre Ă  Simplestblog, exĂ©cutĂ© dans un conteneur appelĂ© simplestblog_app, de communiquer avec le systĂšme de gestion de base de donnĂ©es MariaDB, exĂ©cutĂ© dans un conteneur appelĂ© simplestblog_db, on crĂ©e un rĂ©seau virtuel appelĂ© simplestblog_network sur lequel on connecte les deux conteneurs :

simplestblog networking.drawio

Ainsi, le processus Simplestblog exĂ©cutĂ© dans le conteneur simplestblog_app peut effectuer un accĂšs rĂ©seau sur nom d’hĂŽte simplestblog_db et le port 3306 (aussi Ă©crit sous la forme simplestblog_db:3306), et ainsi se retrouver Ă  Ă©changer avec le processus MariaDB du conteneur simplestblog_db.

Exemple 3. SynthÚse montages + publication de port + réseau virtuel pour déployer Simplestblog

Jusqu’ici dans le cours, sur le cas d’Ă©tude Simplestblog, nous avons regardĂ© de maniĂšre sĂ©parĂ©e :

  • l’utilisation du montage de fichiers/rĂ©pertoires, utilisĂ© Ă  la fois pour fournir un fichier de configuration Ă  Simplestblog et pour persister les donnĂ©es de la base de donnĂ©e MariaDB,

  • l’utilisation d’une publication de port pour pouvoir se connecter au port rĂ©seau sur lequel Ă©coute le processus Simplestblog,

  • l’utilisation d’un rĂ©seau virtuel pour permettre au processus Simplestblog de communiquer avec le processus MariaDB situĂ© dans un conteneur sĂ©parĂ©.

Voyons schématiquement à quoi ressemble ce déploiement une fois ces trois principes combinés :

simplestblog complete.drawio

3. Mise en Ɠuvre avec Podman

La crĂ©ation d’un rĂ©seau virtuel doit se faire sĂ©parĂ©ment et au prĂ©alable de la crĂ©ation d’un conteneur.

Pour crĂ©er un nouveau rĂ©seau virtuel :

$ podman network create <nom du réseau>

Pour lister tous les rĂ©seaux créés :

$ podman network ls

Ensuite, la connexion d’un conteneur Ă  un rĂ©seau virtuel se fait lors de la crĂ©ation d’un conteneur (par exemple lors d’un appel Ă  podman container run) Ă  l’aide de l’option suivante :

  • --network <nom du rĂ©seau> : connecte le conteneur au rĂ©seau virtuel appelĂ© <nom du rĂ©seau>.

Exemple 4. Déploiement de Simplestblog et sa base de données avec Podman

On souhaite dĂ©ployer Simplestblog Ă  l’aide de conteneurs. Il nous faut pour cela crĂ©er deux conteneurs : Simplestblog d’une part, et une base de donnĂ©es compatible MySQL d’autre part. Il nous faut Ă©galement relier ces deux conteneurs Ă  l’aide d’un rĂ©seau virtuel, afin de permettre Ă  Simplestblog de se connecter Ă  sa base de donnĂ©es.

On commence par prĂ©parer un rĂ©seau virtuel appelĂ© simplestblog_network qui permettra aux deux conteneurs d’ĂȘtre connectĂ©s :

$ podman network create simplestblog_network

Pour la base de donnĂ©es, on souhaite utiliser l’image MariaDB disponible sur le registre Docker Hub Ă  l’emplacement mariadb.

On souhaite que notre conteneur MariaDB :

  • soit nommĂ© simplestblog_db,

  • soit en mode dĂ©tachĂ©,

  • soit automatiquement supprimĂ© Ă  la fin de son exĂ©cution,

  • possĂšde un montage du rĂ©pertoire de l’environnement d’accueil /data/simplestblog/database_data vers le rĂ©pertoire /var/lib/mysql du conteneur, de maniĂšre Ă  persister le contenu de la base de donnĂ©es sur l’environnement d’accueil,

  • soit sur la rĂ©seau virtuel simplestblog_network,

  • configure les variables d’environnement attendues par l’image MariaDB, c’est Ă  dire :

    • MARIADB_ROOT_PASSWORD, le mot de passe administrateur de l’instance MariaDB, avec la valeur "my_very_very_secret_root_password",

    • MARIADB_DATABASE, le nom de la base de donnĂ©e pour Simplestblog, avec la valeur simplestblog

    • MARIADB_USER, le nom d’utilisateur du compte base de donnĂ©es, avec la valeur "simplestblog",

    • MARIADB_PASSWORD, le mot de passe pour le compte base de donnĂ©es, avec la valeur "my_very_secret_db_password",

  • utilise la version 11 de l’image de conteneur.

On exĂ©cute donc la commande suivante :

$ podman container run --name simplestblog_db \
             --detach \
             --rm \
             --mount type=bind,source=/data/simplestblog/database,target=/var/lib/mysql \
             --env MARIADB_ROOT_PASSWORD="my_very_very_secret_root_password" \
             --env MARIADB_DATABASE="simplestblog" \
             --env MARIADB_USER="simplestblog" \
             --env MARIADB_PASSWORD="my_very_secret_db_password" \
             --network simplestblog_network \
             docker.io/mariadb:11

Ensuite, pour Simplestblog, on fait usage de l’image disponible dans le registre de conteneurs du Gitlab Nantes UniversitĂ©, accessible Ă  l’emplacement developpement_exploitation/resources/simplestblog. On suppose qu’une image de conteneur a dĂ©jĂ  Ă©tĂ© prĂ©parĂ©e pour Simplestblog, et que cette image fait l’hypothĂšse qu’un fichier de configuration doit se trouver Ă  l’emplacement /config.py au sein du conteneur. Ce fichier doit notamment contenir les informations indiquant Ă  Simplestblog comment se connecter Ă  sa base de donnĂ©es.

On prĂ©pare le fichier configuration Simplestblog suivant, Ă  l’emplacement /data/simplestblog/test_config.py dans l’environnement d’accueil :

SECRET_KEY = "my_very_secret_key"

DB_TYPE = "mysql"

MYSQL_DATABASE_USER = "simplestblog"
MYSQL_DATABASE_DB = "simplestblog"
MYSQL_DATABASE_PASSWORD = "my_very_secret_db_password"
MYSQL_DATABASE_HOST = "simplestblog_db"
MYSQL_DATABASE_PORT = "3306"

Le contenu de ce fichier de configuration est prĂ©parĂ© de maniĂšre Ă  ĂȘtre compatible avec le conteneur MariaDB prĂ©parĂ© plus haut. Plus prĂ©cisĂ©ment on peut constater que :

  • MYSQL_DATABASE_USER correspond Ă  MARIADB_USER dans la configuration du conteneur MariaDB,

  • MYSQL_DATABASE_DB correspond Ă  MARIADB_DATABASE dans la configuration du conteneur MariaDB,

  • MYSQL_DATABASE_PASSWORD correspond Ă  MARIADB_PASSWORD dans la configuration du conteneur MariaDB,

  • MYSQL_DATABASE_HOST correspond au nom du conteneur MariaDB, car le nom du conteneur est Ă©galement un nom d’hĂŽte permettant d’atteindre le dit conteneur au sein du rĂ©seau virtuel oĂč il se trouve (Ă  savoir le rĂ©seau simplestblog_network dans notre exemple).

  • MYSQL_DATABASE_PORT correspond au port sur lequel Ă©coute le processus MariaDB (Ă  savoir, par dĂ©faut, 3306)

Enfin on souhaite que notre conteneur Simplestblog :

  • soit nommĂ© simplestblog_app,

  • soit en mode dĂ©tachĂ©,

  • soit automatiquement supprimĂ© Ă  la fin de son exĂ©cution,

  • possĂšde un montage du rĂ©pertoire de l’environnement d’accueil /data/simplestblog/test_config.py vers le fichier /config.py du conteneur,

  • soit sur la rĂ©seau virtuel simplestblog_network,

  • publie son port 5000 sur le port 8100 de l’environnement d’accueil,

  • utilise la version 52 de l’image de conteneur.

On exĂ©cute donc la commande suivante :

$ podman container run --name simplestblog_app \
                       --detach \
                       --rm \
                       --mount type=bind,source=/data/simplestblog/test_config.py,target=/config.py \
                       --network simplestblog_network \
                       --publish 8100:5000 \
                       docker-registry.univ-nantes.fr/gl/developpement_exploitation/resources/simplestblog:60

On se retrouve ainsi avec un conteneur Simplestblog relié par un réseau virtuel à un conteneur MariaDB !

On notera Ă©galement la commande suivante, pour supprimer tous les rĂ©seaux non utilisĂ©s par des conteneurs (pratique pour faire le mĂ©nage) :

$ podman network prune