Table des matières

Sujet de TP : Mise en œuvre de Docker Swarm

Remarque

Ce TP n'est pas noté.

Pour ce TP vous devez créer 3 machines virtuelles par groupe, or le projet ne permet la création que de 120 machines environ. Il est donc très important de travailler en binôme et de supprimer les machines erronées que vous pouvez créer aujourd'hui.

Introduction

L'objectif de ce TP est de se familiariser avec la solution de clusterisation proposée par Docker et nommée Swarm. Comme vu en cours, il existe des solutions alternatives que nous n'explorerons pas dans le cadre de ce TP (ex: Kubernetes).

Nous nous appuierons sur l'infrastructure OpenStack de l'IFI http://10.10.30.11/horizon. Pour obtenir des informations sur comment se connecter : voir le TP précédant. Dans le projet Cloud nous déploierons au préalable 3 petites machines virtuelles (small est suffisant). L'une sera utilisée comme Manager, et les deux autres comme Worker. <hi #ffc90e>Attention :</hi> Pour ce TP nous avons préparé une image avec un docker pré-installé et pré-configuré qui fonctionne à l'université. Vous devez créer vos instances à partir d'un snapshot de volume nommé snap-docker-ready.

Si vous utilisez des machines en dehors de l'université, installez bien une version de docker récente (>=1.12) et le paquet docker-engine dont l'installation est décrite ici. Le paquet docker.io présent par exemple sur Ubuntu est justement une version de docker sans Swarm.

Partie I : Installation de Docker Swarm

L'installation de base se fait à présent de manière très simple. Tout d'abord sur la VM qui hébegera le manager :

docker swarm init --advertise-addr 192.168.XXX.YYY

Puis sur chacun des workers

# docker swarm join --token letokenrenvoyeparleswarminit 192.168.XXX.YYY:2377

Remarque : Pour chacune des questions vous trouverez des éléments de réponse dans la documentation officielle de Docker Swarm.

NB: Une fois le cluster installé, la commande ci-dessous vous permettra d'avoir un visualiseur de votre infrastructure déployée (http://IPDEVOTREVM:8080):

docker service create   --name=viz   --publish=8080:8080/tcp   --constraint=node.role==manager \
                        --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock    \
                        dockersamples/visualizer

Partie II : Usage d'un cluster swarm

Exécutons trois instances de nginx dans notre cluster swarm.

(manager)# docker service create --name Web --publish 80:80 --replicas=3 nginx:latest
Comment étendre un service ?

Afin d'avoir à présent cinq instances de notre service

(manager)# docker service scale Web=5

On peut également réduire le nombre de services (scale down)

(manager)# docker service scale Web=1

Supprimons à présent notre service

(manager)# docker service rm Web
Maintient automatique du service

Si nous avons défini un service avec un nombre donné de replicas, le Swarm manager est en charge de s'assurer de maintenir cet état. Pour vous en assurer :

Partie III : Gestion des nœuds composant le cluster

Partie IV : Réseau overlay

Supprimez tous les services utilisés précédemment, vous allez en relancer un seul avec un unique réplicas :

docker service create --name nginx -p 80:80 --replicas 1 nginx

Ensuite, retrouvez sur quel nœud de calcul se trouve le docker. Le nom du docker est un peu différent du nom du service, Grâce à la commande

docker logs -f nginx.x.yyyyyyyyyyy

Afficher les logs du docker nginx. Puis avec votre navigateur tentez de contacter le serveur web sur vos 3 machines.

Créez votre réseau overlay

Partie V : Création d'un registry privé

Vous avez vu lors du TP précédant que le cluster swarm pouvait facilement lancer des dockers basés sur des images publiques. Mais pour le moment vous ne pouvez pas le faire avec des images construites via un dockerfile. Pour éviter cette limite, il faut installer un dépôt docker privé dans lequel vous placerez et téléchargerez les images que vous avez générées. Vous trouverez la documentation ici

Attention, les registry que vous pouvez facilement utiliser sont des registry locaux c'est à dire que leur adresse est localhost. En effet, pour autoriser un registry distant, il faut gérer des certificats d'authentification SSL ce qui est hors du cadre de ce cours. Vous allez donc créer un unique docker registry qui répondra à l'adresse localhost:5000 sur plusieurs machines virtuelles. Cela n'est possible que grâce au cluster swarm qui va s'occuper pour vous de la redirection des paquets.

Exploration du registry

Le registry semble un peu abstrait car il ne permet pas facilement d'explorer son contenu. Mais il y a des services spécialisés dans cette exploration que vous pouvez bien sur installer sous forme de conteneurs.

docker service create  -d --network reseau  -e ENV_DOCKER_REGISTRY_HOST=registry   \
                       -e ENV_DOCKER_REGISTRY_PORT=5000 -p 8443:80  --name regbrowser \
                       konradkleine/docker-registry-frontend:v2

Consultez la page http://IP_DE_VOTRE_VM/8443 et explorez le contenu du registry.

Partie VI Utilisation d'un stockage partagé

La gestion des données persistante est un problème dans ce type de cluster, car l'ordonnanceur est susceptible de déplacer le conteneur à tout moment. Si ce conteneur détient des données, rien n'est a priori prévu pour déplacer les données sur nouveau nœud. Une première méthode est d'interdire ce déplacement. C'est ce qui est utilisé pour le registry de la question précédente. Mais cela n'est pas idéal.

Prenons le cas d'un docker implémentant un notebook jupyter : notebooktoto.zip. Dans l'archive, il y a un fichier Dockerfile et un docker-compose qui permettent de lancer le conteneur en tant que service dans le cluster.

docker stack deploy --compose-file docker-compose.yml notebook
import socket
def get_Host_name_IP(): 
    try: 
        host_name = socket.gethostname() 
        host_ip = socket.gethostbyname(host_name) 
        print("Hostname :  ",host_name) 
        print("IP : ",host_ip) 
    except: 
        print("Unable to get Hostname and IP") 
  
# Driver code 
get_Host_name_IP() #Function call 

En effet, le volume contenant le répertoire work est uniquement présent sur la machine qui exécutait le docker au départ, il a donc été perdu.

Pour résoudre le problème, il faut utiliser un volume présent sur tous les nœuds du cluster. Pour cela, il faut utiliser un partage de fichier et un driver spécial pour les volumes qui permet de s'y connecter. Le driver le plus simple à utiliser sous docker swarm est NFS, il n'est pas idéal, car il n'est pas adapté à la plupart des besoins des services (ne l'utilisez pas pour une base de donnée par exemple). Le serveur nfs préparé pour le TP est 192.168.76.5 (dans le projet TIW7) et 192.168.246.27 (dans le projet IGA)

$ sudo mkdir -p /mnt/partage
$ sudo mount -t nfs ADRESSEIPSERVEUR:REPERTOIRESURLESERVEUR /mnt/partage
# On peut vérifier le montage par la commande df et démonter par umount

Est-ce suffisant pour créer un cluster de notebook ?

Partie VI : préparation de la suite du TP

Pour la suite du TP nous allons recréer les 2 worker, il va donc falloir les supprimer proprement.

Vous constatez que les services sont déplacés sur le manager (qui est le seul nœud encore utilisable du cluster).

Partie VII: Docker Machine

Docker machine est un script qui permet de générer des machines virtuelles et d'installer docker automatiquement. Il est capable d'utiliser plusieurs hyperviseurs comme virtutalbox ou openstack mais aussi les fournisseurs de cloud publiques : AWS, Azure … Vous avez une documentation plus spécifique sur openstack ici.

Normalement, toutes les machines utilisées sont générées par docker-machine. Mais certaines requêtes de docker machine utilisent un port inhabituel qui est filtré sur le réseau wifi ce qui perturberait le TP. Il faut donc l'utiliser depuis une machine qui se trouve dans le même réseau. Pour ce TP, il est donc plus simple de l'utiliser depuis le manager pour créer les 2 workers.

La commande docker-machine est assez simple car elle signale la plupart des options qui lui manque. La commande de création est documentée ici, les options relatives à openstack là. CE qu'il faut comprendre est que la commande va contacter les API openstack et s'occuper de l'installation des machines à votre place. Il faut donc lui fournir toutes les informations qui vous serait nécessaire pour faire la même chose. Vous pouvez aussi bien sur suivre la progression de son travail en consultant le site https://cloud-info.univ-lyon1.fr. Vous devez savoir que :

  1. le driver est openstack
  2. l'url d'authentification est https://cloud-info.univ-lyon1.fr:5000/v3/
  3. le nom d'utilisateur et le mot de passe sont ceux qui vous permettent de vous connecter (voir la remarque plus loin).
  4. le tenant est le projet openstack où créer les machines Il faut donner son identifiant avec l'option openstack-tenant-id et lui donner la valeur 9b0d64f0d1d241d8b8afbd60caac615a 1).
  5. le nom de l'image à utiliser est celui du snapshot habituel snap-docker-machine2).

Quelques conseils :

il faut bien spécifier les options nécessaires au fonctionnement à l'université. Le proxy via l'option engine-env qui permet de spécifier une variable d'environnement3). Cela permettra de configurer le docker installé pour l'utilisation du proxy de l'université et s'utilise de cette manière :

docker-machine ... 
  --engine-env HTTP_PROXY=http://proxy.univ-lyon1.fr:3128 \
  --engine-env HTTPS_PROXY=http://proxy.univ-lyon1.fr:3128 \
  --engine-env NO_PROXY=.univ-lyon1.fr \
  --engine-opt "dns 10.10.10.10" \
  --engine-opt "log-level debug" \
  ... NOMDELAMACHINE

Lorsque docker-machine a commencé à créer une machine, il en garde une trace et interdit de réutiliser le même nom. Vous pouvez effacer ces traces en utilisant la commande docker-machine rm -f NOMMACHINE.

<hi #ff7f27>Protection de votre mot de passe</hi>: Attention, vous vous connectez au serveur openstack avec votre login et mot de passe de l'université. Pour éviter de laisser votre mot de passe en clair dans la ligne de commande, n'utilisez pas l'option openstack-password. Vous devez stocker votre mot de passe dans la variable d'environnement OS_PASSWORD. Pour cela copier/coller la commande :

  export OS_PASSWORD=$(python3 -c "import getpass; pa=getpass.getpass('Mot de passe : '); print (pa)")

Ensuite, vous pourrez utiliser la variables d'environement $OS_PASSWORD

<hi #ff7f27>Erreur</hi>: Si vous obtenez l'erreur suivante faite un export NO_PROXY=.univ-lyon1.fr

Error creating machine: Error in driver during machine creation: Post https://cloud-info.univ-lyon1.fr:5000/v3/auth/tokens: Forbidden

<hi #ff7f27>Erreur</hi>: Vous aurez sans doute l'erreur suivante :

Error creating machine: Error running provisioning: Unable to verify the Docker daemon is listening: Maximum number of retries (10) exceeded

Elle est du à l'utilisation du proxy, mais normalement, elle n'a pas empêcher le lancement des machines. Donc vous pouvez simplement l'ignorer.

Vous pouvez ensuite voir les nœuds gérés par docker-machine via la commande docker-machine ls, en supprimer une par docker-machine rm

docker-machine stocke ses informations dans le répertoire .docker/machine/….

Pour exécuter des commandes docker sur ces machines il y a 3 méthodes :

  1. Vous pouvez utiliser les variables d'environnement docker fixées par la commande docker-machine env NOMMACHINE.
  2. Vous pouvez vous connecter sur les machines via la commande docker-machine ssh NOMMACHINE
  3. Vous pouvez exécuter les commande à distance via la commande docker-machine ssh NOMMACHINE COMMANDE. Par exemple
docker-machine ssh NOMMACHINE sudo docker ps
1)
Cette information se trouve dans le fichier généré par le menu fichier openstack rcv3 en haut à droite de l'interface horizon
2)
Il est possible de lui faire utiliser une image standard à condition de lui donner toutes les options qui permettent d'adapter docker à notre environnement, mais cela est fastidieux et il serait impossible à vos enseignants de faire les corrections
3)
donnez une valeur pour HTTP_PROXY et HTTPS_PROXY