DockerCon2016

MAJ (lundi 25 Juillet 2016) : Nous avions constaté quelques dysfonctionnements sur la partie réseau dans le cas des rolling updates sur la version 1.12-rc2. Suite à de nouveaux tests avec la version 1.12-rc4, nous pouvons annoncer que ces dysfonctionnements sont bel et bien résolus !

Lundi 20 juin, lors de la séance plénière d’ouverture de la DockerCon 2016 à Seattle, d’importantes annonces ont été faites sur Swarm, l’orchestrateur officiel de Docker.

 

Quelles sont les nouveautés ?

Quels en sont les apports ?

Et si on passe aux tests : ça donne quoi en déploiement ? en utilisation ?

 

Yann Cézard, expert Docker chez Objectif Libre, analyse le contenu de cette annonce et détaille les tests de déploiement et d’utilisation réalisés dans le laboratoire d’Objectif Libre.

 

Vous trouverez dans cet article :

1. L’analyse des annonces Swarm de la DockerCon

2. Une prise en main pas à pas pour tester vous-même les nouveautés

3. Une conclusion pour savoir que retenir


1. Swarm : guest star de la DockerCon !

#Des annonces sur la mise en œuvre de Swarm

Parmi les nouveautés annoncées, 3 annonces concernent la mise en œuvre de Swarm :

 

l’intégration directe dans le Docker Engine

Jusqu’à présent, Swarm était un service supplémentaire qui s’installait entre vos hôtes et vos clients Docker. Notons que ce mode « supplémentaire » continuera à exister, et il sera possible d’activer un mode swarm directement au niveau de l’hôte, sans ajout de composant d’infrastructure supplémentaire.

 

l’intégration native d’un système de type K/V (clef/valeur) pour la gestion du cluster

Jusquelà, il fallait disposer d’un service Consul, etcd, ou zookeeper afin que swarm puisse fonctionner. Ce système sera utilisé par le mode swarm évoqué ci-dessus, et pour la gestion des réseaux overlay (multi-hosts, VXLAN).

 

la gestion interne d’un système de PKI pour l’authentification des machines participant au cluster, avec rotation automatique des certificats.

Tous les échanges entre les nœuds du cluster (maîtres ou simples nœuds) sont chiffrés.

#La mise en œuvre d’un cluster swarm devient aussi simple que d’installer des hôtes Docker !

Il y aura quelques commandes à passer sur les hôtes pour leur permettre de rejoindre le cluster, mais en terme d’infrastructure nécessaire à la mise en place du cluster, c’est beaucoup plus simple : tout est inclus !

 

A noter : l’algorithme utilisé pour le dialogue entre les machines du cluster est RAFT, déjà utilisé entre autres par Consul et etcd.

Les versions de swarm précédentes n’étaient pas forcément très complexes à mettre en place (en comparaison de ses « concurrents » tels Kubernetes ou Mesos), surtout si vous utilisiez Docker Machine pour configurer un hôte Docker comme membre d’un cluster Swarm via quelques options en ligne de commande, et qui s’occupait de tout (création et configuration des conteneurs swarm). Il fallait malgré tout préalablement avoir mis en en place un système de type K/V (Consul, etcd, zookeeper), et si possible en mode hautement disponible, ce qui était en général la partie un peu complexe de sa mise en œuvre.

 

En synthèse :

Swarm ré-affirme sa place de leader comme orchestrateur Docker « simple à installer », point sur lequel nous lui donnions déjà une légère avance sur ces principaux concurrents, en particulier Kubernetes et Mesos.

#Annonces relatives au mode swarm

On pouvait jusqu’ici reprocher à Swarm son approche un peu simpliste de l’orchestration : il était possible de positionner des contraintes/affinités, d’avoir du fail-over en cas de perte d’un maître ou d’un nœud, mais c’était à peu près tout.

 

En comparaison, Kubernetes propose depuis ses débuts la notion de replicas, de health-checks, un mécanisme de load-balancing interne ou encore un mécanisme de rolling-update pour mettre à jour son service de façon progressive et transparente. Kubernetes ne propose pas l’API de Docker, mais sa propre API, ce qui lui permet de proposer ces services supplémentaires.

 

Revenons sur les annonces sur le mode Swarm lors de la DockerCon 2016 et voyons si elles changent la donne :

– la notion d’état désiré du cluster : swarm sait maintenant combien d’instances de conteneurs doivent rendre un service, et peut donc gérer les pannes de membres du cluster

– la mise à l’échelle (scale)

– les rolling-updates

– les health-checks spécifiques à l’application (via l’introduction d’une nouvelle directive dans le Dockerfile : HEALTHCHECK)

– la mise en oeuvre des réseaux overlay (distribués) au niveau du cluster swarm (jusque là c’était géré indépendamment de swarm)

– load-balancing interne (via IPVS)

– un système de découverte de services basé sur DNS (et donc avec round-robin)

 

En synthèse :

En terme de fonctionnalités cette fois, il semble que Swarm réduit son retard sur Kubernetes.

 

Mais qu’en est-il concrètement ? Est-ce que toutes les promesses sont tenues ? Ou est-ce des effets d’annonce ? Comment ces nouvelles fonctionnalités ont-elles été introduites ?

 

Nous vous proposons de tester avec nous ces fonctionnalités en mettant en place un cluster swarm en quelques minutes.

2. Test pas-à-pas des nouveautés

#Déploiement

Nous utiliserons 3 VMs avec la distribution de votre choix, pourvu qu’elle soit supportée par Docker : Debian, Ubuntu, CentOS, …

Les 3 machines doivent être, si possible, dans le même sous-réseau IP, et il ne doit pas y avoir de filtrage entre elles (il est possible d’ouvrir uniquement les ports nécessaires à l’établissement du cluster swarm et des réseaux Overlay, mais cela risque de poser des problèmes par la suite, donc pour une maquette de test, ne vous embarrassez pas).

Vous aurez aussi installé votre clef publique SSH sur le compte root de ces 3 machines.

Nous effectuons l’installation en utilisant docker-machine (https://docs.docker.com/machine/install-machine/) et son driver generic.

Si vous avez l’habitude d’utiliser docker-machine avec un driver plus spécifique – openstack, amazon, virtualbox, etc. – vous pouvez adapter les commandes qui suivent. Nous avons fait le choix de donner l’exemple avec le driver generic qui peut être utilisé indépendamment du système sur lequel l’installation est réalisée.

 

Commencez par déclarer les adresses IP de vos 3 machines :

MACHINE1_IP=192.168.100.11
MACHINE2_IP=192.168.100.12
MACHINE3_IP=192.168.100.13

Puis lancez les commandes suivantes :

docker-machine create \
    -d generic \
    --engine-install-url https://experimental.docker.com \
    --generic-ip-address=${MACHINE1_IP} \
    --generic-ssh-user root \
    swarm12-1

docker-machine create \
    -d generic \
    --engine-install-url https://experimental.docker.com \
    --generic-ip-address=${MACHINE2_IP} \
    --generic-ssh-user root \
    swarm12-2

docker-machine create \
    -d generic \
    --engine-install-url https://experimental.docker.com \
    --generic-ip-address=${MACHINE3_IP} \
    --generic-ssh-user root \
    swarm12-3

Vos trois machines sont prêtes et disposent de la version 1.12-rc2 de Docker installée ?

Vous êtes fin prêt pour mettre en place votre cluster swarm !

Création de la première machine, initialisation du cluster

Connectez-vous tout d’abord en direct sur celle-ci :

$ docker-machine ssh swarm12_1

Puis lancez la commande suivante pour initialiser le cluster swarm :

# docker swarm init --auto-accept none --secret cdde9c4c-6425-4a8a-8091-1dc136d07ad5

Ici, les options utilisées indiquent :

  • que nous demandons à valider manuellement l’ajout de tout hôte à notre cluster, manager ou simple noeud (–auto-accept none)
  • à ce qu‘une demande pour rejoindre le cluster soit accompagnée d’un secret (–secret cdde9c4c-6425-4a8a-8091-1dc136d07ad5).

Vous pouvez bien sûr remplacer le secret utilisé ici par celui de votre choix, il faudra par la suite adapter les commandes suivantes.

Ajout de machines au cluster

Vous pouvez maintenant vous rendre sur un second nœud, afin dajouter un maître supplémentaire à votre cluster.

Dans un nouveau terminal :

$ docker-machine ssh swarm12_2

# docker swarm join --manager --secret cdde9c4c-6425-4a8a-8091-1dc136d07ad5 ${IP_SERVEUR_1}:2377
Error response from daemon: Your node is in the process of joining the cluster but needs to be accepted by existing cluster member.
To accept this node into cluster run "docker node accept 404it7iqxp8rdqjlny1xzxpxn" in an existing cluster manager. Use "docker info" command to see the current Swarm status of your node.

Vous retournez donc de nouveau sur la première machine (qui pour l’instant est seule dans le cluster).

Avant d’accepter la machine, regardons ce que nous indique la commande qui permet de lister les nœuds :

# docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
404it7iqxp8rdqjlny1xzxpxn Pending Unknown Active 
amnhk3iyt5hjjndldogyoodm9 * swarm12-1 Accepted Ready Active Leader

La demande de la seconde machine est bien présente. Validez avec :

# docker node accept 404it7iqxp8rdqjlny1xzxpxn
# docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
404it7iqxp8rdqjlny1xzxpxn swarm12-2 Accepted Ready Active Reachable
amnhk3iyt5hjjndldogyoodm9 * swarm12-1 Accepted Ready Active Leader

 

Enfin, reproduisez la procédure pour le 3ème et dernier nœud, en ouvrant un troisième terminal :

$ docker-machine ssh swarm12_3

# docker swarm join --manager --secret cdde9c4c-6425-4a8a-8091-1dc136d07ad5 192.168.122.20:2377
Error response from daemon: Your node is in the process of joining the cluster but needs to be accepted by existing cluster member.
To accept this node into cluster run "docker node accept 2teb1zom1tqk4oojvkmlw0ox0" in an existing cluster manager. Use "docker info" command to see the current Swarm status of your node.

 

De la même façon que pour la machine précédente, acceptez la machine depuis la première machine (ou la seconde qui est aussi un maître du cluster) :

# docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
2teb1zom1tqk4oojvkmlw0ox0 Pending Unknown Active 
404it7iqxp8rdqjlny1xzxpxn swarm12-2 Accepted Ready Active Reachable
amnhk3iyt5hjjndldogyoodm9 * swarm12-1 Accepted Ready Active Leader
# docker node accept 2teb1zom1tqk4oojvkmlw0ox0
# docker node ls
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS
2teb1zom1tqk4oojvkmlw0ox0 swarm12-3 Accepted Ready Active Reachable
404it7iqxp8rdqjlny1xzxpxn swarm12-2 Accepted Ready Active Reachable
amnhk3iyt5hjjndldogyoodm9 * swarm12-1 Accepted Ready Active Leader

#Utilisation

Notre cluster étant maintenant disponible, nous allons pouvoir jouer un peu avec…

#Modification de l’approche d’utilisation

 

Petit avertissement si vous avez déjà joué avec Swarm : l’approche a quelque peu changé.

D’ailleurs, notez que Swarm en tant que composant externe continue (pour le moment) à évoluer : on parle ici d’un « mode swarm » du docker engine.

Ceci ne facilite pas la visibilité sur le projet, mais c’est une étape de transition…

 

Avec les versions précédentes, il était possible de s’adresser à Swarm en dialoguant sur son port dédié (par défaut 3376) et de dialoguer avec un hôte particulier du cluster en dialoguant avec le docker engine (sur le port 2376 par défaut, et à condition d’avoir mis en place l’accès via le réseau).

 

Dorénavant, on dialogue uniquement sur le port du démon Docker (2376 par défaut), l’activation de swarm ne le rends pas disponible sur un port supplémentaire. Seules certaines sous-commandes particulières seront destinées à Swarm, et en particulier la nouvelle sous-commande « docker service ».

Les autres commandes (run, create, stop…) seront, elles, gérées par le démon de l’hôte.

 

On s’éloigne légèrement du principe « Swarm expose la même API que Docker » : il expose toujours la même API, mais ne gère plus que certaines actions spécifiques alors que l’ancien mode les prenait toutes en compte.

 

Cette nouvelle commande « service », qui n’est qu’une évolution logique de la notion de service introduite dans Docker Compose avec la version 2 de son fichier de description, va nous permettre de gérer les réplicas

C‘est une évolution très importante.

 

Jusqu’à présent, Swarm exposait l’API Docker standard et n’avait pas de réelle connaissance du nombre d’instances demandées pour un service, puisqu’il n’avait pas de notion de service. 

 

La commande scale de Docker Compose demandait N fois la création d’un conteneur de tel type avec tels attributs. A aucun moment le cluster Swarm (ou l’hôte Docker) ne disposait de l’information ‘Mon service S est rendu par N conteneurs basés sur l’image X’. 

 

Or il est essentiel que le système d’orchestration dispose de ces notions/informations (quels conteneurs participent à rendre un service ?) pour pouvoir mettre en place des mécanismes :

– de load-balancing / service discovery

– de rolling-update

– de résilience

 

Celles et ceux qui s’intéressent à l’orchestration de conteneurs auront constaté que les nouvelles fonctionnalités annoncées permettront à Docker de se rapprocher de Kubernetes en termes de fonctionnalités proposées, et ces principes de services et de replicas s’en rapprochent aussi. 

 

Par contre, le nombre de concepts à ingérer est moindre, puisque la notion de service de swarm semble fusionner les notions de replica-set et de services de k8s.

#En Pratique

Nous allons créer 2 services simples : il s’agit dans les 2 cas de conteneurs proposant un serveur web qui sert un simple fichier PHP affichant le nom du conteneur qui l’exécute.

Cet exemple permettra de tester le fonctionnement du load-balancer interne, ainsi que le système de service discovery (à travers le DNS). 

 

Ces 2 mécanismes sont très importants dans la mise en place d’une application de type micro-services, applications principalement visées par les solutions d’orchestration de conteneurs.

 

Les images utilisées par la démonstration sont construites de façon automatique par le docker hub, depuis le dépôt github suivant : https://github.com/eesprit/demo-swarm1_12/

(Nous vous laissons vous assurer que vous n’allez rien exécuter de dangereux.)

 

Les commandes qui suivent pourront être exécutées sur n’importe quelle machine de notre cluster.

Création d’un réseau overlay

Commencez par créer un réseau overlay dans lequel vous placerez les 2 services afin qu’ils puissent communiquer ensemble, et ce même si les conteneurs se trouvent sur des machines différentes. 

 

Note : les réseaux overlay ne sont pas propres à cette nouvelle version de Docker/swarm, par contre il ne nécessitent plus de configuration supplémentaire sur les hôtes pour être mis en place : ils sont maintenant inclus en standard dans le cluster swarm.

# docker network create -d overlay demo_net

Vous pouvez vérifier que le réseau a bien été créé en tapant la commande :

# docker network ls

...

1xyus3q5cp9s        demo_net            overlay             swarm               

...

qui doit renvoyer notre réseau demo_net, quelle que soit la machine du cluster sur laquelle vous tapez la commande (ou à qui vous vous adressez).

Création des services

Créez le premier service (frontend) :

– il reposera sur l’image eesprit/frontend

vous demanderez à disposer de 3 instances

– ce service sera exposé sur le port 8080 de tous les hôtes du cluster

# docker service create --name frontend --replicas 3 -p 8080:80 --network demo_net eesprit/frontend

Vérifiez que le service est bien créé :

# docker service tasks frontend

ID                         NAME        SERVICE   IMAGE             LAST STATE            DESIRED STATE  NODE

41veb5fubdg93qxhag1dqs65k  frontend.1  frontend  eesprit/frontend  Preparing 31 seconds  Running        swarm12-1

0det3taxlhqa89tglyad3hk3i  frontend.2  frontend  eesprit/frontend  Preparing 31 seconds  Running        swarm12-3

3j45nz3hf3biu8pdh559249iw  frontend.3  frontend  eesprit/frontend  Preparing 31 seconds  Running        swarm12-2

Une tache (task) est un conteneur participant à la réalisation d’un service.

Vous pouvez voir ici que les instances sont en cours de démarrage (récupération de l’image) : Preparing…

 

Pour le second service :

– il reposera sur l’image eesprit/backend

vous demanderez à disposer de 3 instances

– ce service n’exposera pas de port à l’extérieur, seuls les conteneurs de type frontend auront à y accéder, et ils pourront le faire via le réseau overlay, en résolvant via le DNS le nom du service.

# docker service create --name backend --replicas 3 --network demo_net eesprit/backend

# docker service tasks backend

ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE

bx2l5ub5pllq0eteoysuedmcj backend.1 backend eesprit/backend Running 4 seconds Running swarm12-2

8k68nth3wudkc8k1126pe401g backend.2 backend eesprit/backend Running 4 seconds Running swarm12-1

cfsaqmcbwm41zf6j3jrbmmbuo backend.3 backend eesprit/backend Running 4 seconds Running swarm12-3

Vous pouvez maintenant lancer votre navigateur web préféré, et indiquer dans la barre d’adresse une des IPs des machines de votre cluster swarm (en précisant bien le port : http://${MACHINE1_IP}:8080)

 

Vous devriez voir le comportement suivant :

– à chaque rafraîchissement, l’identifiant du composant de backend change.

Ceci illustre le fonctionnement du système de service discovery basé sur le DNS. En effet, le composant frontend s’adresse à un conteneur en résolvant le nom « backend », le serveur DNS embarqué effectue donc un simple round-robin entre les différentes instances (ou tâches) qui composent le service backend.

– l’identifiant du composant frontend change lui aussi, mais beaucoup moins souvent. De plus, selon la machine swarm sur laquelle vous vous connectez, celui-ci peut varier. Nous avons donc ici une illustration du système de load-balancing interne (basé sur IPVS).

 

Modification des services

Avertissement : la section qui suit n’est pas complètement fonctionnelle avec la version expérimentale actuelle de Docker (1.12-rc2). Nous avons tout de même souhaité la faire apparaître à titre d’information et pour ensuite la mettre à jour facilement avec les prochaines versions et constater les évolutions.

Il est aussi possible de mettre à jour vos services (changer l’image, ou bien le paramétrage).

 

Nous mettrons à jour ici une variable d’environnement (qui détermine la couleur d’affichage du nom du conteneur dans la page web), et nous demanderons à mettre à jour un seul conteneur à la fois par service (–update-parallelism 1), et d’attendre 30 secondes entre chaque mise à jour (–update-delay 30s) de façon à pouvoir constater l’évolution.

# docker service update --env COLOR=purple --update-delay 30s --update-parallelism 1 frontend 
# docker service update --env COLOR=orange --update-delay 30s --update-parallelism 1 backend

Dans votre navigateur, en rafraîchissant, vous devriez voir les couleurs des ids des conteneurs évoluer en fonction de l’avancement de la mise à jour.

MAJ du 25/05/2016 : nous évoquons ci-dessous des problèmes rencontrés lors de l’écriture de notre article de blog avec la version 1.12-rc2. De nouveaux tests avec la version 1.12-rc4 montrent que ces différents soucis ont bien été corrigés !

Il est aussi possible que cela ne fonctionne pas parfaitement… en effet, nos tests ont eu tendance à démontrer que l’équation : rolling update + réseau overlay = comportement inattendu.

Certains conteneurs semblent perdre leur connectivité, et pas seulement ceux qui ont été mis à jour. 

 

De nombreuses « issues«  sont déclarées dans le github des différents projets concernés par cette évaluation (docker, swarmkit, libnetwork) et devraient être corrigées d’ici la sortie de la 1.12 finale, et particulièrement autour de l’implémentation des réseaux overlay dans swarm (sans passer par un système K/V tiers).

Ces évolutions sont donc à suivre(MAJ du 25/05/2016 : la version 1.12-rc4 – et peut-être même déjà la rc3 que nous n’avons pas eu le temps d’évaluer – corrige donc bien ces petits problèmes)

 

Note : si pour vous cela fonctionne de façon attendue, nous sommes preneurs de vos retours : quelle version ? sur quelle distribution ? dans quel environnement ? à contact@objectif-libre.com 


3. Que retenir ?

Côté simplicité de déploiement : le contrat est rempli, il est difficile de faire plus simple.

 

Du côté des nouvelles fonctionnalités, et cette nouvelle notion de service :  il était nécessaire qu’elle soit introduite dans Docker, comme les sous-commandes network et volume avaient été précédemment introduites.

 

On pourra regretter que les commandes « traditionnelles » comme le run ne soient pas gérées par le mode swarm. Cela aurait pu permettre la mise en place d’un système de job « classique » (sans notion de réplicas), et serait resté plus dans l’approche précédente de swarm (qui présentait exactement la même API).

Des évolutions sont bien sûr possibles, et même probables.

 

L’ancien type de déploiement de Swarm va continuer à vivre pendant quelques temps, ce nouveau mode swarm embarqué ne va pas le remplacer de suite mais va commencer par évoluer en parallèle.

On pourra aussi regretter le choix d’implémentation du système de load-balancing : il semble efficace mais encore un peu limité, les notions d’affinité ou de sticky-sessions manquent.

 

Aurait-on pu introduire un load-balancer comme point d’entrée ? Ceci permettrait d’éviter de devoir intégrer un load-balancer existant, avec une intégration de qualité variable selon le produit utilisé.

 

Reste à voir comment l’intégration se fera avec la prochaine version de compose : sur ce point, peu de crainte à avoir, jusqu’à présent les différents outils ont sû évoluer en parallèle et c’est un des points forts des produits Docker. La notion de service étant déjà incluse dans compose, la notion de réplicas va très probablement apparaître.

 

Au final : les annonces sur ce mode swarm de Docker sont plutôt enthousiasmantes !

Nous vous conseillons de les tester sans plus attendre, à titre de prise en main/découverte, et en gardant à l’esprit :

    – que c’est encore expérimental

    – que le fond comme la forme peuvent évoluer

    – et qu’il faudra probablement attendre une version de plus pour que ces nouveautés soient parfaitement intégrées au reste de l’écosystème… comme c’est souvent l’usage avec Docker

    

Pour les quelques bugs évoqués : nous sommes confiants sur leur correction d’ici les prochaines « rc », ou au pire d’ici la version 1.12 finale. (MAJ du 25/05/2016 : ces problèmes sont bien résolus avec la version 1.12-rc4)

Si vous aviez déjà un déploiement de Swarm, pas d’inquiétude à avoir : le mode swarm de Docker est une alternative pour l’avenir, les anciens déploiements de Swarm continuent à être maintenus et à fonctionner.

 

Pour notre part, nous continuons notre veille sur les « issues«  dans GitHub et les prochaines release-candidate, en espérant pouvoir valider les rolling-updates sur un réseau de type overlay… (MAJ du 25/05/2016 : ces problèmes sont bien résolus avec la version 1.12-rc4)