Prérequis
Avant d'attaquer ce tutoriel, je vous conseille d'avoir bien compris le fonctionnement de Docker. Il sera essentiel d'être à l'aise avec la notion de variables d'environnements, de conteneurs, de build... Pour cela, j'avais fait il y a quelques temps maintenant une série d'articles sur Docker pour son utilisation en développement ainsi qu'en production : Docker, du dev à la prod . Le but de cet article est d'aller plus loin en découvrant la scalabilité que nous offre Docker Swarm.
Installation de Docker et UFW
La première chose à faire est de créer un serveur. Pour cet exemple, je vais me créer une instance sur le public cloud d'OVH. Je vais prendre la D2-2 que je vais payer à l'heure à 0,00901 € HT. J'installe dessus une Debian 11. Je nomme cette instance demo-swarm-1
.
Petite astuce, au moment de la l'étape "Configurez votre instance", vous avez la possiblité de définir un script d'installation. C'est clairement très pratique pour démarrer rapidement une machine avec Docker et un pare-feu déjà configuré.
Pour le pare-feu, je vous conseille d'installer UFW. Il est très simple à manipuler. Vous pouvez facilement ouvrir ou fermer un port en entrée ou sortie, pour toutes les IPs, une IP en particulier ou une plage d'IPs... Bref, vous pouvez tout faire simplement. Par contre, avec Docker, vous risquez d'être déçu car il contournera les règles en place. Lorsqu'un conteneur sera créé sur votre système, les iptables seront modifiées afin que votre conteneur soit accessible de l'extérieur. Il y a donc quelques modifications à effectuer dans le fichier /etc/ufw/after.rules
et pour ça, je vous recommande cet article sur Medium.
La première chose que je vais faire, c'est autoriser le port 22 ( ssh ), ainsi que le trafic sur les ports 80 et 443.
sudo ufw allow ssh
sudo ufw route allow proto tcp from any to any port 80
sudo ufw route allow proto tcp from any to any port 443
Et c'est tout pour le moment ! Il ne me reste plus qu'à activer mon pare-feu
sudo ufw enable
debian@demo-swarm-1:~$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
80/tcp ALLOW FWD Anywhere
443/tcp ALLOW FWD Anywhere
80/tcp (v6) ALLOW FWD Anywhere (v6)
443/tcp (v6) ALLOW FWD Anywhere (v6)
Une fois que ma machine est créée et que docker
et docker-compose
sont bien installés, je vais pouvoir créer une machine docker sur mon mac à l'aide de docker-machine
. Son but sera de pouvoir gérer mes conteneurs sans me connecter en ssh. Mais avant cela, je vais devoir ouvrir le port 2376 pour mon adresse IP.
sudo ufw allow from MON_ADRESSE_IP to any port 2376
docker-machine create -d generic --generic-ip-address IP_DEMO_SWARM_1 --generic-ssh-user debian demo-swarm-1
Plus tard, lorsque j'aurai besoin de piloter mes conteneurs, je n'aurai pas besoin de me connecter en ssh. Je pourrai simplement lancer la commande suivante :
eval $(docker-machine env demo-swarm-1)
Cela sera particulièrement utile ( voir indispendable ) lorsque je souhaiterai déployer une stack à l'aide d'un docker-compose.yaml
.
Initialisation de Swarm
Dans cette partie, nous allons découvrir comment mettre en place l'orcherstration de conteneurs avec Swarm. Pour commencer, je vais utiliser la machine précédement créée afin d'initialiser Swarm.
eval $(docker-machine env demo-swarm-1)
docker swarm init --advertise-addr=XXX.XX.XX.XXX
--advertise-addr
définie l'adresse IP identifiant notre machine dans le cluster que l'on va créer. Dans notre cas, il s'agit de l'IP publique. Cela aurait pu fonctionner sans cet attribut dans ce cas particulier, mais en fonction de la configuration de votre réseau, ne pas ajouter cet attribut pourrait vous jouer des tours.
À l'aide de cette commande docker swarm init
, je viens de créer mon premier node manager sur demo-swarm-1
. Il aura comme responsabilité de déployer mes services sur le cluster. Car oui, l'intérêt de Swarm va être de faire tourner mon application PHP sur un cluster de serveurs quels que soient la nature et le nombre de serveurs. Cela peut être un VPS comme un dedié, à partir du moment où docker est intallé sur la machine, elle pourra être ajouté au cluster.
Après la création de ce node
, Swarm me propose deux commandes. La première, pour ajouter un worker, et la seconde, pour ajouter un manager. La différence entre le worker et le manager réside dans le fait que c'est le manager qui va avoir la résponsabilité du déploiement des services sur les workers.
Swarm initialized: current node (4mkg2t852rofyh3y1ujsjm42f) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5wouvlrplwu807znouhnaq9tejcyps6iqvtsvkbgn16404pfa5-4v5d1w5n2v3jdgjyr08x2ds3s IP_DEMO_SWARM_1:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Je vais maintenant créer une nouvelle instance chez ovh, demo-swarm-2
. De la même manière que demo-swarm-1
, je vais y installer Docker et configurer UFW.
Je me connecte alors sur ma machine demo-swarm-2
et lance la commande suivante
docker swarm join --token SWMTKN-1-5wouvlrplwu807znouhnaq9tejcyps6iqvtsvkbgn16404pfa5-4v5d1w5n2v3jdgjyr08x2ds3s IP_DEMO_SWARM_1:2377
Et là... ça tourne jusqu'au timeout ! Et oui, étant donné que j'utilise UFW sur mes machines, on ne peut pas utiliser le port 2377 comme ça. Il faut d'abord l'ouvrir.
Je retourne donc sur la machine demo-swarm-1
et j'ouvre le port 2377 juste pour l'IP de demo-swarm-2
sudo ufw allow from IP_DEMO_SWARM_2 to any port 2377
sudo ufw enable
Je peux alors retourner sur demo-swarm-2
et relancer ma commande docker swarm join
. Après quelques secondes, mes deux machines constituent un cluster swarm.
Revenons juste 5 minutes sur la documentation concernant les ports utilisés par Swarm. Il y en 3.
TCP port 2377 for cluster management communications
TCP and UDP port 7946 for communication among nodes
UDP port 4789 for overlay network traffic
Celui que je viens d'ouvrir concerne la gestion du cluster. Donc si on en reste là, on arrivera à faire tourner des noeuds sur demo-swarm-2
mais ils seront inaccessibles. Il faudra donc gérer l'ouverture du 7946 et 4789 sur demo-swarm-2
et demo-swarm-1
.
Il y a plus simple ? Oui ! Dans mon cas précis, les IP de mes machines étant publique, je n'ai pas d'autres choix que d'ouvrir les ports de façon restreinte à des IP spécifiques. Mais je pourrais très bien sur OVH créer un vrack ( un réseau privé ), dans lequel je désactiverai l'adressage publique de mes machines. Ensuite, je pourrais accéder à mes machines via un VPN présent sur ce réseau privé. Dans ce cas précis, je n'aurai même plus besoin de m'embéter à configurer UFW pour les machines de mon cluster, et j'aurai aucun risque d'attaque DDos sur une de mes machines dans la mesure où je n'aurai plus d'adressage publique. Sujet intéressant pour un prochain article pourquoi pas !
Pour finir, je vous laisse avec un schéma de l'architecture mise en place