Temps de lecture : 10 minutes

HypriotOs est une version de raspbian dans laquelle docker, et docker swarm sont pré installés. La particularité est que HypriotOs tourne sur des architectures ARM telles que les Raspberry, le Nvidia shield et quelques autres cartes comme les ODROID C2.

Dans cet article, nous allons voir comment monter un petit cluster swarm avec trois noeuds (1 manager et 2 workers). Une fois la partie serveur montée, nous ferons tourner des services dessus à la fois en lignes de commandes et via une interface graphique.

Swarm

Swarm est l’orchestrateur historiquement intégré dans docker. Il permet de distribuer automatiquement les containers sur l’un ou l’autre des noeuds du cluster en fonction de l’indisponibilité ou de la charge d’un noeud.  Docker inc a été testé pour scal

ler jusqu’à 1 000 nœuds et  50 000 conteneurs sans dégradation de performance. A mon avis nous allons avoir du mal à faire tourner autant de conteneurs sur nos Raspberry.

Il existe deux types de noeuds, les managers et les workers. Pour faire simple, les managers peuvent administrer ce qui tourne sur le cluster et répartir le travail sur les workers tandis que les workers sont de simples exécutants qui lancent des containers.

De base, le cluster va faire du mesh routing. Cela signifie, par exemple, que si vous lancez un serveur web sur le port 80 quelque part sur votre cluster, vous pourrez y accéder en attaquant n’importe quelle machine (worker ou manager) qui compose le cluster. Swarm va aussi nous proposer un système de load balancing afin de pouvoir distribuer la charge entre différentes instances d’un service. 

https://docs.docker.com/engine/swarm/ingress/#publish-a-port-for-a-service

Les deux points précédents sont disponibles, sans configuration, dès la création de votre cluster.

Choix des matériaux

Pour monter mon cluster avec trois noeuds il va me falloir le matériel suivant :

Matériel pour un cluster swarm de raspberry pie

Installer HypriotOs sur les cartes

Pour les utilisateurs de Linux et MacOs il existe un outil proposé par la communauté de Hypriot pour flasher les cartes. Malheureusement, pour les utilisateurs de Windows, les choses sont un peu plus compliquées.

Pour linux et mac

Hypriot flash est un utilitaire en lignes de commandes qui va s’occuper de tout, de la décompression de l’image à l’installation sur la carte SIM. Pour l’installation, tout est précisé dans le readme du dépôt.

Télécharger la dernière image de hypriotos

wget https://github.com/hypriot/image-builder-rpi/releases/download/v1.9.0/hypriotos-rpi-v1.9.0.img.zip

Vérifier le checksum de l’image

➜  cat ../Downloads/hypriotos-rpi-v1.9.0.img.zip.sha256
be21a702887817d8c84c053f9ee4c54e04fd55e9fb9692edc3904801b14c33a8  hypriotos-rpi-v1.9.0.img.zip

# sur linux sha256sum / sur mac gsha256sum

➜  gsha256sum hypriotos-rpi-v1.9.0.img.zip
be21a702887817d8c84c053f9ee4c54e04fd55e9fb9692edc3904801b14c33a8  hypriotos-rpi-v1.9.0.img.zip

Flasher les cartes SD

Pour notre manager:

flash hypriotos-rpi-v1.9.0.img.zip --hostname manager-01

Pour nos workers :

flash hypriotos-rpi-v1.9.0.img.zip --hostname worker-01
flash hypriotos-rpi-v1.9.0.img.zip --hostname worker-02

Votre mot de passe root vous sera demandé pendant l’installation de l’image sur la carte.

Vous devriez avoir une sortie console proche de celle ci:

flash --hostname worker-01 hypriotos-rpi-v1.9.0.img.zip
Using cached image /tmp/hypriotos-rpi-v1.9.0.img

Is /dev/disk2 correct? yes
Unmounting /dev/disk2 ...
Unmount of all volumes on disk2 was successful
Unmount of all volumes on disk2 was successful
Flashing /tmp/hypriotos-rpi-v1.9.0.img to /dev/rdisk2 ...
No 'pv' command found, so no progress available.
Press CTRL+T if you want to see the current info of dd command.
Password:
930+1 records in
930+1 records out
975765504 bytes transferred in 111.983538 secs (8713473 bytes/sec)
Mounting Disk
Mounting /dev/disk2 to customize...
Set hostname=worker-01
Unmounting /dev/disk2 ...
"disk2" ejected.
Finished.

Pour windows

Je n’ai jamais flashé mes cartes SD depuis Windows. Mais vous pourrez trouver une procédure sur le site de hypriot. 

Dans le cas de Windows il faudra, si possible, éditer le fichier user-data  (c’est un yml sans extension) à la racine de la carte SD pour changer le hostname qui est présent dedans. Il faudra en nommer un manager-01 et les deux autres worker-01 et worker-02 histoire de pouvoir suivre dans la suite de l’article.

Les branchements

Rien de bien complexe, les câbles ethernet dans les prises ethernets, les cables d’alimentation dans les micro usb et les cartes SD dans les slots prévus à cet effet. Et hop, le tour est joué. Vous devriez pouvoir détecter les machines sur votre réseau local.

Branchements raspberry pi pour un cluster swarm

Se connecter en SSH sur les différents noeuds

Sur mac, j’utilise l’application LanScan Pro depuis des années pour scanner mon réseau local.

Détection des machines du cluster swarm sur le réseau

J’ai bien mes trois Raspberry qui sont présents sur le réseau avec les ip 192.168.1.22, 23 et 24.

Pour se connecter en ssh sur les Raspberry il faut utiliser le login/ mot de passe par défaut de hypriotOS. A savoir pirate/ hypriot.

Première connexion SSH sur hypriot

A cette étape je vous conseille de faire les mises à jour avant d’aller plus loin. Ce serait dommage de faire toute sa configuration sur une version qui a des failles de sécu. De plus il est préférable d’avoir les versions de docker sur l’ensemble du cluster.

Le temps des mises à jour vous avez le temps d’aller prendre un café 😀

Les versions de docker

Création du cluster swarm

Creation du manager

Sur le rasp nommé manager-01 je vais créer le cluster swarm :

docker swarm init

La commande va créer le cluster, vous enregistrer en temps que leader et vous donner la commande pour ajouter des workers.

La création du cluster swarm
La liste des noeuds du cluster après création

Ajout des workers

Pour ajouter les workers on va utiliser la commande donnée au moment de la création du cluster en lançant sur les Raspberry worker-01 et worker-02.

Si vous avez perdu la commande vous pouvez la récupérer en vous connectant sur un manager et en exécutant la ligne de commande :

docker swarm join-token worker
Récupération de la commande pour joindre un cluster swarm

On va donc se connecter en ssh sur worker-01 et worker-02 et lancer la commande de join. Vous devriez avoir le résultat suivant :

Joindre un cluster swarm

Sur le manager on va voir apparaitre les noeuds en tant que worker si on utilise la commande docker node ls

La liste des noeuds d’un cluster swarm

Installation et utilisation de Portainer

Portainer est un outil de visualisation et d’administration et de visualisation open source pour docker. Il est assez intéressant dans notre cas car il va nous permettre de visualiser ce qu’il se passe sur l’ensemble de notre cluster depuis une interface WEB. 

Installation de portainer

On va lancer un container Portainer sur le noeud manager-01.

docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

Portainer est maintenant compatible avec notre architecture arm, il est donc possible d’utiliser l’image officielle. 

Une fois le container lancé, vous pouvez vous rendre, via votre navigateur, sur le port 9000 de votre manager. Pour moi http://192.168.1.22:9000.

Vous allez être redirigé sur la page de création du compte administrateur. Il  est préférable de ne pas conserver le nom d’utilisateur par défaut.

Installation portainer

La seconde étape de l’installation est le choix du type de connexion à docker. Nous allons choisir local car nous avons monté le socket docker lors de la création du container.

Installation portainer

Maintenant que Portainer est configuré nous allons pouvoir consulter notre cluster swarm, mais aussi lancer des services si nous le souhaitons. 

On remarque déjà, que notre cluster est présent et que nos 3 noeuds sont bien détectés.

Cluster swarm dans portainer

En l’état notre cluster est composé de 12 coeurs et de 3 Go de ram.

Cluster visualizer

Lancer un service sur swarm

Pour lancer un service, il y a deux possibilité. Soit passer par portainer soit le faire en lignes de commandes. A vous de voir ce que vous préférez. J’ai préparé une petite image pour faire cette démo. Je m’excuse d’avance du poids de l’image (120Mo) pour faire un hello world…

J’ai buildé une image apache/ php qui affiche le hostname courant (celui du container). L’idée est de déployer un service sur le cluster et de voir comment il réagit et quel est le comportement que l’on obtient.

Déployer un service en lignes de commandes

Nous allons lancer une instance de notre image sur le cluster. Nous n’avons pas à nous soucier du choix de la machine sur laquelle l’application va tourner car le routing mesh nous permettra d’y accéder depuis n’importe quel noeud.  Mais vous pouvez le savoir dans portainer en retournant sur la vue Cluster visualisation.

docker service create -p 80:80 --name hello-world docker.io/lahaxearnaud/swarm-hello-world
Création d’un service dans swarm

Il est possible de préciser beaucoup d’options pour limiter les ressources que le container pourra utiliser, la façon de vérifier que l’application est toujours up (health check)…

Déployer un service avec Portainer

Toutes les options que l’on peut donner via le cli sont disponibles via portainer pour la création de service. La mise en place de nouveau service est très simplifié grâce à l’interface graphique.

Creation d’un service dans portainer

Pour notre test nous n’avons pas besoin des configurations avancées.

Tester le load balancing

Nous avons maintenant un service qui tourne sur notre cluster et qui sert une « page » web contenant le nom du container qui le fait tourner. Pour tester le load balancing on fait une série d’appels et on va regarder si on obtient toujours le même nom de container.

for ((i=1;i<=10;i++)); do curl "http://192.168.1.22"; echo ""; done

Sans surprise pour le moment je vais obtenir 10 fois la même valeur, car nous n’avons qu’une instance qui tourne :

Dans un premier temps nous allons faire scaller notre application pour faire tourner 9 instances.

docker service scale hello-world=9

Vous pouvez aussi le faire via portainer en cliquant sur le service hello-world dans la section service et en modifiant la valeur dans le champs Replicas.

Scaller un service avec portainer

Il va falloir attendre un peu que l’image soit téléchargée sur les différents Raspberry et que les containers soient lancés. Mais une fois que tout est prêt, on va pouvoir relancer notre commande.

On se rend bien compte que la charge est distribuée entre les différentes machines. Sur les 10 hits on a touché les 9 instances.

Consulter les logs

Sur le manager vous pouvez faire un tail sur les logs d’un service via la commande docker service log -ft hello-world.

Visualisation des logs d’un service swarm

Dans portainer par contre il semblerait qu’il y ait un bug et qu’il ne remonte que les logs des instances présentes sur le manager. 

Que mettre sur le cluster ?

Pour ma part, j’utilise swarm depuis au moins deux ans pour ma domotique. Comme je voulais jouer un peu avec l’IoT j’ai mis des capteurs un peu partout dans l’appartement (luminosité, température, mouvements, capteurs d’ouverture de porte et de fenêtre…) et chaque élément envoie des messages dans un rabbitmq. Mon cluster contient l’ensemble des consommateurs et l’application symfony qui sert l’interface graphique. Les consommateurs sont des workers symfony 4 qui utilisent le composant symfony messenger

Avoir cette architecture en cluster permet de perdre ou d’ajouter un ou plusieurs serveurs sans devoir déplacer des applications à la main. Là où il faut être attentif c’est que swarm peut continuer de fonctionner en perdant un worker, mais la perte des managers est plus problématique. Il est préférable d’avoir plusieurs managers pour éviter que le cluster se retrouve sans manager en cas de panne. Un nombre impair de managers est préférable pour s’assurer que l’algorithme (Raft) arrive à élire un nouveau leader.

Retour d’expérience

La technologie est sympa et la fiabilité est au rendez-vous sur tout ce qui est worker et application web. Par contre, j’ai rencontré pas mal de problèmes en voulant mettre un rabbitmq, un elastic search ou encore un mysql dans le cluster. Après plusieurs crashes je les ai installés sur une machine séparée. Je ne sais pas à quel niveau se situe le problème, mais depuis que c’est sur un rasp séparé il n’y a plus de problèmes.

L’autre point est que j’ai une livebox à la maison, c’est elle qui me sert de DHCP (c’est dans ma todo de faire autrement). Elle a tendance à sortir du réseau les machines avec des ips fixes au bout de quelques jours. Je me suis retrouvé à plusieurs reprises avec un cluster qui était HS car toutes les machines étaient déconnectées.

Le fait d’être sur une architecture ARM nous empêche d’utiliser la plupart des images disponibles sur les hubs. Il faut donc passer du temps à faire ses propres images. Ce n’est pas forcement un mal !

Faq

Comment retirer proprement un noeud d’un cluster swarm ?

Si c’est un manager il faut se poser la question de promouvoir un worker en manager avant de commencer docker node promote worker-02 puis vous devez retirer le role manager au noeud à supprimer docker node demote manager-01. La seconde étape est de dire à l’orchestrateur d’enlever tout ce qui tourne sur le noeud docker node update --availability drain worker-01. Une fois qu’il n’y a plus rien sur le noeud on peut le sortir du cluster via la commande docker node rm worker-01. De cette manière il n’y aura pas d’interruption de service.

Comment supprimer le cluster swarm ?

Dans un premier temps il faut supprimer les services qui tournent dessus : docker service rm mon-service. Une fois que c’est fait vous pouvez supprimer les noeuds un à un via docker node rm -f node-name. Puis sur le manager faire un docker swarm leave -f.

Est-ce qu’il est possible de deployer une image locale ?

Non, il n’est pas possible de déployer une image qui n’est pas dans un registry. Mais vous pouvez monter votre propre registry et l’utiliser pour déployer vos images sur vos workers.

Est-il possible de déployer un fichier docker-compose sur swarm ?

Oui c’est possible via docker stack deploy

Est-ce que l’on peut monter des volumes dans les services ?

Oui vous pouvez, maintenant il y aura autant de volume que de noeuds sur lesquels tourneront vos applications.