DevOps : transformer le processus de développement en une chaîne de production logicielle - Partie 2
Mise en œuvre d’un cluster Docker Swarm Mode
Provisionnement des machines avec docker-machine
Le provisionnement des machines virtuelles qui accueillent le cluster Docker peut s’effectuer avec docker-machine – voir ici la documentation officielle.
Le déploiement d’un cluster peut s’effectuer sur une machine de développement à des fins d’évaluation (option 1 présentée ci-dessous).
- Option 1 : sur un poste Windows, Mac ou Linux en s’appuyant sur le driver Virtual Box (cf. script ci-dessous)
#!/usr/bin/env bash if [ "$1" != "" ]; then node_name="$1" else node_name='swarm-node' fi # Créer 3 hôtes Docker en utilisant le driver Virtual Box for i in 1 2 3; do docker-machine create -d virtualbox $node_name-$i done
- Option 2 : sur des machines fournies par un cloud provider – voir ici la liste des Cloud supportés
- Option 3 : sur des machines virtuelles qui supportent Docker (version du noyau Linux > 3.10), comme présenté ci-dessous.
Les machines virtuelles Linux utilisées ici sont des distributions Debian Jessie (Debian v. 8). Le provisionnement des machines s’effectue avec docker-machine, en utilisant le driver générique (SSH). Au préalable, il est nécessaire d’installer un couple de clés RSA sur la machine cible pour pouvoir s’authentifier sans devoir saisir de mot de passe.
Il est également nécessaire de créer un groupe docker et un utilisateur affecté à ce groupe.
useradd -g docker docker mkdir -p /home/docker/.ssh/ chown -R docker /home/docker/ su docker
Suivre ici les instructions pour Debian 8.
Il faut également ajouter l’utilisateur Docker aux « sudoers sans mot de passe » de la machine cible (cf. documentation Docker machine).
Pour cela, insérer la ligne :
docker ALL=(ALL) NOPASSWD: ALL
dans le fichier des sudoers (/etc/sudoers).
Note sur la sécurité : La mise en œuvre décrite ici est menée à des fins d’évaluation de l’orchestrateur Docker Swarm Mode.La mise production d’un cluster Docker Swarm Mode nécessite d’étudier les risques occasionnés par l’innovation (augmentation de la surface d’attaque, risque d’afflux d’images basées sur du code source vulnérable, risque de monopolisation de ressources système …) et de prendre les précautions nécessaires (scans d’images, activation de Docker Content Trust, benchmarks de sécurité Docker tels que Docker bench security, durcissement des hôtes Docker …). |
Créer les machines Docker
docker-machine create --driver generic --generic-ip-address=10.41.22.109 --generic-ssh-key ~/.ssh/id_rsa --generic-ssh-user=docker sqli-node-1
Répéter l’opération avec les autres machines.
Vérifier le succès du provisionning :
docker-machine ls
La mise à jour de la version de docker sur la machine cible est extrêmement simple :
docker-machine upgrade sqli-node-1
Cluster Docker Swarm Mode
Une fois le provisionnement des machines achevé, créer un cluster Docker Swarm Mode :
# Injecter les variables d’environnement Docker pour configurer le client et pointer sur un manager
eval $(docker-machine env sqli-node-1) # Initialiser le cluster Docker docker swarm init --advertise-addr $(docker-machine ip sqli-node-1)
# Créer un token pour ajout de swarm node de type "manager" TOKEN=$(docker swarm join-token -q manager) # Les noeuds 2 et 3 rejoignent le cluster for i in 2 3; do eval $(docker-machine env sqli-node-$i) docker swarm join \ --token $TOKEN \ --advertise-addr $(docker-machine ip sqli-node-$i) \ $(docker-machine ip sqli-node-1):2377 done
Note : Afin d’assurer la haute disponibilité, il est nécessaire d’utiliser au minimum 3 nœuds de type manager dans un cluster (5 sont recommandés).
Déployer les services sur le cluster
Deux approches sont décrites ci-dessous :
- La création des services en ligne de commande, par des appels « docker service create »
- Le déploiement d’une stack complète selon une approche « déclarative » basée sur le format docker-compose, version 3
Option 1 : créer les services individuellement
Visualizer
Le visualizer Docker Swarm est une application Node JS packagée dans un conteneur, qui permet de visualiser la répartition des tâches/conteneurs (les instances des services) sur le cluster.
docker service create \ --name=viz \ --publish=8083:8080/tcp \ --constraint=node.role==manager \ --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ dockersamples/visualizer
Pointer un navigateur à l’adresse http://$(docker-machine ip sqli-node-1):8083.
Portainer
Portainer est une interface simple de gestion des hôtes Docker et des clusters Swarm.
Déployer le service de gestion du cluster Portainer.
docker service create \ --name portainer \ --publish 9000:9000 \ --constraint 'node.role == manager' \ --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ portainer/portainer \ -H unix:///var/run/docker.sock
Pointer un navigateur à l’adresse http://$(docker-machine ip sqli-node-1):9000 et saisir un mot de passe administrateur.
Registry
Un registre Docker privé permet de stocker des images et de les rendre accessibles aux noeuds du cluster.
docker service create --name registry \ -p 5000:5000 \ --reserve-memory 100m \ --mount "type=bind,source=/home/docker/registry,target=/var/lib/registry" \ registry:2.5.0
docker service create --name registry-frontend \ -e ENV_DOCKER_REGISTRY_HOST=10.41.22.109 \ -e ENV_DOCKER_REGISTRY_PORT=5000 \ -p 8084:80 \ konradkleine/docker-registry-frontend:v2
La création d’un registre d’entreprise accessible via un nom de domaine (afin d’héberger par exemple les images Docker produites par les différentes équipes projet) doit être sécurisée (communications TLS).
L’installation complète et sécurisée d’un registre d’entreprise est décrite ici.
Déploiement d’un service Jenkins
docker service create --name jenkins \ -p 8085:8080 \ -p 50000:50000 \ --mount "type=bind,source=/home/jenkins,target=/var/jenkins_home" \ --mount "type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock" \ --constraint "node.hostname == sqli-node-1" \ jenkinsci/jenkins:lts
Déploiement du service Artifactory
docker service create –name artifactory-5 \
–mount « type=volume,source=artifactory5_data,target=/var/opt/jfrog/artifactory » \
-p 8086:8081 docker.bintray.io/jfrog/artifactory-oss:5.0.0
Option 2 : déployer la stack complète avec docker stack
Docker stack permet de déployer un ensemble de services dont la configuration est décrite dans un fichier docker-compose (en version 3).
Les services sont ainsi déployés à l’aide du fichier docker-compose-stack.yml de façon « déclarative » plutôt que scriptée.
version: '3' services: jenkins: image: jenkinsci/jenkins:lts ports: - 8085:8080 - 50000:50000 deploy: placement: constraints: - node.hostname == sqli-node-1 volumes: # Named volume - /home/jenkins:/var/jenkins_home # Bind volume to run Docker in Docker - /var/run/docker.sock:/var/run/docker.sock:rw - /usr/bin/docker:/usr/bin/docker:ro sonarqube: image: sonarqube:6.3.1 ports: - 9001:9000 environment: - SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar volumes: - sonarqube_conf:/opt/sonarqube/conf - sonarqube_data:/opt/sonarqube/data - sonarqube_extensions:/opt/sonarqube/extensions - sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins db: image: postgres:9 environment: - POSTGRES_USER=sonar - POSTGRES_PASSWORD=sonar volumes: - postgresql:/var/lib/postgresql - postgresql_data:/var/lib/postgresql/data artifactory-5: image: docker.bintray.io/jfrog/artifactory-oss:5.0.0 ports: - 8086:8081 volumes: - artifactory5_data:/var/opt/jfrog/artifactory networks: cd: driver: overlay volumes: sonarqube_conf: sonarqube_data: sonarqube_extensions: sonarqube_bundled-plugins: postgresql: postgresql_data: artifactory5_data: docker-compose-stack.yml Le déploiement s’effectue à l’aide de la commande « docker stack deploy » : docker stack deploy -c docker-compose-stack.yml cip
Pour visualiser le résultat, pointer un navigateur à l’adresse du visualiseur.
Les services sont effectivement déployés et visibles via l’interface de gestion.
En conclusion
Docker Swarm Mode permet de gérer les hôtes Docker en tant que cluster et modifie la relation des développeurs et des opérateurs système à l’égard des serveurs, en la rendant plus abstraite et détachée, selon la métaphore « les serveurs : des animaux de compagnie ou des animaux de bétail (cf. pets VS cattle) ? ».
L’automatisation de la chaîne de production logicielle nécessite une excellente connaissance du processus de développement et permet de le rendre répétable et prédictible. Selon Edward Deming : « If you can’t describe what you are doing as a process, you don’t know what you are doing », et c’est bien d’une parfaite description du processus de développement dont il s’agit ici.
Dans cette démarche d’industrialisation, les solutions de containerisation telles que Docker jouent un rôle essentiel en permettant de fiabiliser les environnements dans lesquels les applications s’exécutent et d’automatiser les activités de déploiement des applications.

Directeur Technique, SQLI Suisse
votre commentaire
Se joindre à la discussion ?Vous êtes libre de contribuer !