CSI dans Docker Swarm !

Avec la version 23, Docker (en réalité, moby/swarmkit) a ajouté le support de CSI dans le mode Swarm. Cette fonctionnalité était très attendue au sein de la (petite) communauté Swarm, car il s’agissait jusque là de son plus gros inconvénient par rapport à Kubernetes (si on parle uniquement des features natives à Swarm, pas de l’écosystème autour).

CSI, c’est quoi ?

CSI, c’est une abbréviation pour Container Storage Interface. Le concept est de standardiser la manière dont les orchestrateurs de containers (Docker Swarm, Kubernetes, Cloud Foundry, etc) gèrent l’accès au stockage persistant (sur disque par exemple). En effet, lorsque vous utilisez un orchestrateur, cela signifie que vos containers vont pouvoir démarrer sur plusieurs machines différentes. Cependant, un problème majeur se pose : comment faire lorsque les containers ont besoin de stocker des données persistantes, puisque ces containers doivent être en mesure de démarrer sur n’importe laquelle des machines de votre cluster ?

CSI harmonise la manière de faire des orchestrateurs en la matière (un peu comme CNI avec le réseau), et vous permet de directement déclarer la manière dont les containers instanciés doivent accèder à la donnée : localement, sur un montage NFS, Samba, Seaweed, Gluster, S3, etc. L’orchestrateur s’occupe alors de faire le point de montage directement dans le container, ce qui signifie que le système hôte n’a pas a accèder de lui-même au montage.

En dehors de la praticité (les données sont montées de la même manière qu’un réseau virtuel ou qu’une configuration), c’est également un gain de fiabilité (aucun risque d’oublier un point de montage sur l’hôte qui se propage mal dans un container, ou qu’une machine perde le montage sans s’en rendre compte), et de sécurité (les hôtes système n’ont pas directement accès aux données, ce qui limite les soucis de permissions sur les fichiers, et évite que n’importe qui puisse lire les données).

Bref, la Container Storage Interface, c’est un standard qui apporte un réel confort d’usage au quotidien, en améliorant sensiblement la qualité de notre infrastructure. Si les utilisateurs de Kubernetes en profitent depuis 2019, les utilisateurs de Docker Swarm auront dû attendre février 2023 pour voir cette fonctionnalité arriver en statut expérimental (autrement dit, ça risque de faire tout noir, alors doucement avant de l’utiliser en production !).

Swarm CSI - Comment ça marche ?

Note importante : En raison d’un bug actuellement non-résolu sur Docker Swarm, ce tutoriel ne fonctionne pas sur des versions ultérieures à 26.0.2.

Docker Swarm est livré avec CSI, mais sans provider intégré : les utilisateurs doivent par eux-même installer des plugins sur chacun des noeuds du cluster Swarm pour leur usage. Et là où le bat blesse un peu, c’est que Mirantis (le principal contributeur à Swarmkit, et vendeur de solutions Swarm Entreprise) s’est bien gardée de fournir des plugins prêt à l’emploi. La communauté à donc commencée à se saisir du sujet, Certains dépôts comme celui-ci regroupent de la documentation et quelques drivers. En supporté, nous pouvons citer NFS, Samba, SeaweedFS, et quelques Cloud Providers qui ont porté leur plugin Kube vers Swarm (Hetzner et DigitalOcean font partie des bons élèves).

Une fois le plugin installé sur chacun de vos hôtes Docker, vous allez pouvoir créer des services Swarm utilisant des points de montage via ces plugins.

Mise en pratique

Dans cet exemple, nous allons utiliser quatre machines virtuelles situées sur un même réseau virtuel (10.0.0.0/8) : trois machines forment un cluster Docker Swarm (10.0.1.1, 10.0.1.2, 10.0.1.3), et une machine fait office de serveur NFS (10.0.100.1). Ces quatres machines sont installées sous Debian 12.

Installation du serveur NFS

En premier lieu, connectons-nous sur notre machine NFS, et installez le paquet nfs-kernel-server ; et créez le dossier /mnt/myshareddir.

Ensuite, éditez le fichier /etc/exports, et mettez ce contenu :

/mnt/myshareddir 10.0.1.0/24(rw,sync,no_subtree_check)

Enfin, exportez la nouvelle configuration, et redémarrez le serveur NFS : exportfs -a ; systemctl restart nfs-kernel-server.

Votre serveur NFS est créé ; nous pouvons passer au cluster. Bien entendu, cette configuration est très sommaire (pas d’authentification, contrôle sommaire via l’IP…). Il va sans dire que cette configuration n’est pas adaptée pour une production.

Installation du cluster Swarm.

Installez Docker en suivant la documentation officielle sur chaque machine. En raison d’un bug en version 27 non-résolu (voir le haut de l’article), il vous faudra revenir en version 26.0.2 (sur chaque machine également) :

apt install -y docker-ce=5:26.0.2-1~debian.12~bookworm --allow-downgrades

Créez ensuite un cluster Swarm. La version détaillée est disponible ici, mais, pour les pressés, voici un petit tl;dr :

  1. Sur la première machine, tapez docker swarm init ; docker swarm join-token manager
  2. Sur les deux autres machines, tapez la commande obtenue à l’étape précédente.

Notre cluster est opérationnel ! Un petit docker node ls vous permettra de vous en assurer.

Maintenant, nous devons installer le plugins CSI-NFS qui nous permettra d’utiliser notre serveur NFS directement dans Swarm. Comme la dernière version du plugin n’était pas disponible, je l’ai compilée et poussée sur DockerHub moi-même, en me basant sur les sources présentes ici.

Sur chaque machine, taper :

docker plugin install \
  --alias csi-nfs \
  --grant-all-permissions \
  artheriom/swarm-csi-nfs:v4.9.0

Si tout s’est bien passé vous devriez, sur chacune des machines, avoir un résultat similaire à celui-ci en tapant docker plugin ls :

root@test-1:/home/debian# docker plugin ls
ID             NAME             DESCRIPTION                       ENABLED
4af20db19305   csi-nfs:latest   NFS CSI driver for Docker Swarm   true

Créer notre volume

Maintenant que tout est fin prêt, nous pouvons créer un nouveau volume sur notre cluster, qui va utiliser notre serveur NFS ! Cette commande est à lancer sur un seul noeud (le volume va se propager à travers tout le cluster) :

docker volume create \
  --driver csi-nfs \
  --type mount \
  --opt server="10.0.100.1" \
  --opt share="/mnt/myshareddir" \
  my-nfs-volume

Ici, nous créons un volume nommé my-nfs-volume de type mount (ce qui permet d’expliciter à Swarm qu’en réalité, nous utilisons un point de montage), utilisant notre driver installé via le plugin ; et qui va se créer sur notre serveur NFS. Il existe plusieurs autres options de configuration non-abordées ici, n’hésitez pas à consulter la documentation au besoin.

Si tout a bien fonctionné, votre volume devrait avoir le statut Created :

root@test-1:/home/debian# docker volume ls --cluster
VOLUME NAME               GROUP     DRIVER         AVAILABILITY   STATUS
my-nfs-volume                       csi-nfs        active         created

Si votre volume reste en pending creation, vérifiez la configuration de votre serveur NFS.

Utiliser notre montage !

Maintenant que votre volume est créé, vous pouvez vous en servir dans votre service !

docker service create \
  --name my-service \
  --mount type=cluster,src=my-nfs-volume,dst=/usr/share/nginx/html \
  --mode global \
  nginx

Et voilà, vous utilisez votre premier montage via CSI pour vos données ! 🎉 Vous pouvez vérifier que tout fonctionne bien en ajoutant/supprimant du contenu dans les containers et en vérifiant que les modifications se propagent bien.

Docker Swarm CSI - Au final ?

Le CSI de Swarm est à l’image du reste de Swarm : c’est simple, élégant, et fonctionnel. Le côté modulable par plugin permet une extensibilité quasi-infinie et totalement modulable selon les besoins, ce qui est une autre excellente nouvelle.

Cependant, cette technologie est encore expérimentale, et cela se voit :

En bref, et pour conclure, CSI dans Swarm, c’est une excellente nouvelle pour la vie du produit ; mais du chemin reste à faire avant d’avoir ce genre de feature utilisables en conditions réelles. Et ça, c’est dommage, pour une feature qui aurait dû être là… En 2020.