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
machines provisionnées

machines provisionnées

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 :

  1. La création des services en ligne de commande, par des appels « docker service create »
  2. 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.

Page d'accueil de Portainer

Page d’accueil de Portainer

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.

visualiseur

visualiseur

Les services sont effectivement déployés et visibles via l’interface de gestion.

interface de gestion

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.

0 commentaires

votre commentaire

Se joindre à la discussion ?
Vous êtes libre de contribuer !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Inscription newsletter

Ne manquez plus nos derniers articles !