Exemple pratique : le livre d’or (guestbook)
Dans cette partie de l’article, nous allons voir comment déployer une application simple avec Docker et Kubernetes.
Le livre d’or (guestbook)
L’application que nous allons déployer est une application multi-tiers simple. L’application offre une interface web qui permet de laisser des messages sur une page, d’où l’appellation livre d’or. Cet exemple est inspiré du site kubernetes.io où on trouve le tutoriel pour le déploiement du livre d’or avec Kubernetes.
Dans un premier temps, nous allons déployer l’application avec Docker, sans orchestrateur. Ensuite, nous déploierons l’application en utilisant Kubernetes en tant qu’orchestrateur. Nous pourrons ainsi comparer et illustrer l’intérêt d’utiliser un orchestrateur de conteneurs.
L’architecture de l’application du livre d’or est la suivante :
Comme on peut le voir, l’application se partage en deux parties :
- La partie web (frontend) accessible depuis l’extérieur,
- La partie base de données (backend) composées de bases de données Redis. Ces bases de données peuvent être de deux types : master ou slave. L’écriture d’une nouvelle ligne est stockée sur le master, qui répliquera ensuite sur les slaves de telle sorte à ce que toutes les base de données soient synchronisées. La lecture se fait depuis les slaves.
Prérequis
Pour le déploiement sans orchestrateur, Docker est nécessaire afin de pouvoir instancier des conteneurs Docker sur la machine. Disponible sous Linux, ainsi que Windows et MacOS (avec Docker desktop)
Pour le déploiement avec Kubernetes, un cluster Kubernetes ainsi que l’outil de commande kubectl sont nécessaires. Pour une installation simple et rapide, il est possible d’utiliser Minikube, un outil qui instanciera une VM préconfigurée avec Kubernetes. Ce lien explique comment installer Minikube.
Les images de conteneurs utilisées pour le livre d’or sont disponibles à ces liens :
- Web : gcr.io/google-samples/gb-frontend:v4
- Redis Master : k8s.gcr.io/redis:e2e
- Redis slave : gcr.io/google_samples/gb-redisslave:v1
Déploiement avec Docker — sans orchestrateur
Pour construire notre application manuellement sous Docker, nous allons procéder de la sorte :
- Creation d’un user-defined bridge ,
- Téléchargement des images,
- Instanciation des conteneurs à partir des images
Remarques:
- La création d’un user-defined bridge est conseillée pour que les conteneurs puissent se trouver par leurs noms sans aucune modification manuelle des images ou des conteneurs une fois lancés (en allant ajouter une entrée sur le fichier hosts par exemple). Ceci repose alors sur un serveur DNS qui est inclus (embedded) dans ce user-defined bridge . Une alternative, plus laborieuse, consisterait à créer manuellement des tuyaux entre les conteneurs (option — link).
- Le conteneur qui héberge la partie web doit être accessible depuis l’extérieur de la VM
Création du user-defined bridge :
Dans le langage docker, un bridge network est un composant logiciel qui permet la communication entre les conteneurs. Par défaut, seuls les conteneurs connectés au même bridge peuvent communiquer. Le default bridge est le bridge disponible par défaut. Ce bridge n’offre cependant pas de résolution DNS automatique entre les conteneurs. Pour avoir cette fonctionnalité, nous aurons besoin de créer un user-defined bridge. D’autres différences entre le default bridge et l’user defined bridge existent. Elles sont consultables à ce lien.
Le default bridge est nommé bridge. On peut le voir avec la commande docker network ls:
Le subnet utilisé pour le bridge par défaut est le 172.17.0.0/16 :
Pour créer un nouveau subnet, on utilise la commande docker network create:
Téléchargement des images :
La commande docker pull permet de récupérer une image à partir d’un registre. Par exemple, pour récupérer l’image redis-slave, accessible à l’adresse gcr.io/google_samples/gb-redisslave:v1 :
Nous faisons la même chose pour les deux autres images : redis-master et frontend. Une fois téléchargées, on vérifie que les images sont bien présentes avec la commande docker images:
Instancier les conteneurs :
Maintenant que nous avons les images, nous pouvons lancer nos conteneurs. Pour rappel, nous avons 3 images pour notre application. Une image pour le frontend, une image pour la base de données master, et une image pour la base de données slave. Les images sont paramétrées de telle sorte qu’elles se trouvent à travers les noms redis-master et redis-slave. Par exemple, lorsque le frontend cherche à écrire sur une base de données, il cherche la base de données par le nom redis-master (ligne 11 du fichier de configuration). Aussi, l’image de base de données slave est configurée de telle sorte à ce qu’elle cherche le master avec le nom redis-master. Il est donc nécessaire que nous nommions nos conteneurs avec ces noms.
docker run permet de lancer un conteneur. Pour lancer un conteneur à partir de l’image du redis-master, nous utilisons la commande suivante :
e5e67996c442 est l’id de l’image (on peut l’obtenir avec docker image ls). Le conteneur utilise le user-bridge network guestBookNetwork créé plus haut et se nomme redis-master. Les autres conteneurs qui seront connectés au même user-bridge network pourront donc trouver ce conteneur via le nom redis-master.
Avec docker ps, nous vérifions que notre conteneur est bien fonctionnel :
On remarque que le conteneur écoute sur le port 6379. Port du conteneur et non de l’host qui héberge le conteneur (ici le PC).
Faisons de même pour les deux autres conteneurs :
On remarque pour le frontend l’option -p 80:8080. Ceci pour exposer le port 80 du conteneur sur le port 8080 de la machine host. Afin de connaître les adresses que nos conteneurs ont obtenues, on utilise la commande docker network inspect :
Nos trois conteneurs sont maintenant fonctionnels et peuvent communiquer entre eux via le bridge guestBookNetwork. Le conteneur frontend est accessible depuis l’extérieur de la VM host:
Note : eth1 est l’interface réseau qui interconnecte la VM contenant les conteneurs et la machine host (ici le PC de test).
A partir du navigateur, le livre d’or est désormais accessible :