Principe
Docker Swarm est un système d’orchestration de conteneur incorporé à Docker Engine. Moins populaire et complet de Kubernetes, il est aussi plus simple à utiliser.
Un cluster Swarm est composé de deux types de noeuds :
- Les manager nodes qui gèrent la configuration du cluster
- Les worker nodes qui offrent de la capacité de calcul
Swarm va permettre de déployer des services. Un service est l’état désiré d’un ou plusieurs conteneurs, les ports exposés, le nombre de conteneurs à instancier pour assurer le fonctionnement etc… Le manager node va ensuite se charger de gérer l’orchestration sur les worker afin d’offire le fonctionnement désiré.
Pour la suite, je disposerai de 3 nodes sous Ubuntu 22.04 :
- swarm0 / 192.168.69.60 : manager node
- swarm1 / 192.168.69.61 : worker node
- swarm2 / 192.168.69.62 : worker node
Si docker-ce n’est pas installé, cela se règle rapidement avec :
sudo apt update sudo apt -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common sudo apt -y remove docker.io sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg |apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt update sudo apt -y install docker-ce sudo systemctl enable --now docker
Créer le cluster
Docker Swarm est compris par défaut donc il n’y a rien de plus à installer. On peut donc initier le cluster sur le manager avec en advertise address, l’ip du manager :
sudo docker swarm init --advertise-addr 192.168.69.60 Swarm initialized: current node (qeo9wfwnm22pd9mae9hscxfcs) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-13bd0a7lozmekt5ph18igdtngwnqqe9s8lezwcxybqcz05p1gb-0dt1bomyoleflgzy58xbri5e6 192.168.69.60:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Le token est à conserver de manière sécurisée dans un vault ou un keepass par exemple.
On peut maintenant joindre les worker node au manager node avec ce toker et en précisant l’IP du manager :
sudo docker swarm join --token SWMTKN-1-13bd0a7lozmekt5ph18igdtngwnqqe9s8lezwcxybqcz05p1gb-0dt1bomyoleflgzy58xbri5e6 192.168.69.60:2377 [sudo] password for julien: This node joined a swarm as a worker.
Vérifions nos noeuds :
sudo docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION qeo9wfwnm22pd9mae9hscxfcs * swarm0 Ready Active Leader 23.0.1 aq0jchfcz0c0vedu6gsdteoav swarm1 Ready Active 23.0.1 daspjlhzxpk2xkg9mpbf70s2l swarm2 Ready Active 23.0.1
Lancer un service
Avec Swarm, on ne déploie pas un simple conteneur, il serait instancié bien entendu mais géré comme un conteneur autonome.
On va donc se créer un fichier docker-compose.yml et le déployer sur le cluster. Ici, on va simplement déployer une image nginx avec deux réplicas.
version: "3" services: web: image: nginx deploy: replicas: 2 ports: - "8080:80" environment: - NGINX_HOST=morot.local - NGINX_PORT=80
Et vérifier que le service est bien déployé
julien@swarm0:~$ sudo docker stack deploy --compose-file docker-compose.yml nginx-stack Creating network nginx-stack_default Creating service nginx-stack_web
Il est possible de visualiser où nos conteneurs sont lancés :
sudo docker service ps nginx-stack_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS fhgipvoq55wl nginx-stack_web.1 nginx:latest swarm1 Running Running 5 minutes ago wd2obqai9xoj nginx-stack_web.2 nginx:latest swarm0 Running Running 5 minutes ago
Sur chaque noeud on peut visualiser les conteneurs qui y sont lancés.
sudo docker ps [sudo] password for julien: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 569eeae4351e nginx:latest "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 80/tcp nginx-stack_web.1.fhgipvoq55wl6qfuals6cxpdg
Après arrêt d’un des deux worker, le conteneur lancé sur swarm1 est lancé sur swarm2 :
julien@swarm0:~$ sudo docker service ps nginx-stack_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS w0ns4o93q4dp nginx-stack_web.1 nginx:latest swarm2 Running Running 18 seconds ago fhgipvoq55wl \_ nginx-stack_web.1 nginx:latest swarm1 Shutdown Running 8 minutes ago wd2obqai9xoj nginx-stack_web.2 nginx:latest swarm0 Running Running 8 minutes ago
Maintenant, faisons en sorte que notre manager ne soit plus un worker node :
julien@swarm0:~$ docker node update --availability drain swarm0 swarm0
Pour assurer le nombre de réplicas, un second conteneur a été démarré sur le worker swarm 2 :
sudo docker service ps nginx-stack_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS w0ns4o93q4dp nginx-stack_web.1 nginx:latest swarm2 Running Running 5 minutes ago fhgipvoq55wl \_ nginx-stack_web.1 nginx:latest swarm1 Shutdown Running 13 minutes ago s8olvpwus904 nginx-stack_web.2 nginx:latest swarm2 Running Running 10 seconds ago wd2obqai9xoj \_ nginx-stack_web.2 nginx:latest swarm0 Shutdown Shutdown 12 seconds ago
Redémarrons le node précédemment arrêté et pour assurer la montée en charge, nous allons indiquer que nous souhaitons 3 réplicas désormais :
docker service scale nginx-stack_web=3 nginx-stack_web scaled to 3 overall progress: 3 out of 3 tasks 1/3: running [==================================================>] 2/3: running [==================================================>] 3/3: running [==================================================>] verify: Service converged docker service ls ID NAME MODE REPLICAS IMAGE PORTS llv38z9l6a0p nginx-stack_web replicated 3/3 nginx:latest *:8080->80/tcp sudo docker service ps nginx-stack_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS w0ns4o93q4dp nginx-stack_web.1 nginx:latest swarm2 Running Running 12 minutes ago fhgipvoq55wl \_ nginx-stack_web.1 nginx:latest swarm1 Shutdown Shutdown 2 minutes ago s8olvpwus904 nginx-stack_web.2 nginx:latest swarm2 Running Running 7 minutes ago wd2obqai9xoj \_ nginx-stack_web.2 nginx:latest swarm0 Shutdown Shutdown 7 minutes ago k9g4x9kjsham nginx-stack_web.3 nginx:latest swarm1 Running Running about a minute ago
Faisons le ménage et supprimons notre stack :
sudo docker stack rm nginx-stack Removing service nginx-stack_web Removing network nginx-stack_default