Actualités

[21/07/2017] Smile lance les premiers vélos solaires connectés à l’occasion du Sun Trip Tour 2017

Smile, leader des solutions IoT et open source, confirme sa solide expertise sur le marché de l’embarqué en participant activement à la course de vélos solaires du Sun Trip Tour.

[03/07/2017] Smile remporte le Drupagora d'Or 2017 du meilleur site e-commerce

Le vendredi 30 juin, la 3ème édition des Drupagora d'Or s'est déroulée à Paris.

[30/06/2017] Découvrez les projets de nos équipes au Hackathon Data Énergie

Les 29 et 30 juin, le Hackathon Data Énergie s'est déroulé au Liberté Living Lab à Paris.

Toutes les actualités picto
       

Vous avez besoin de mettre à jour votre Lecteur Flash Flash 7

Guillemet ouvrant l'actualité des solutions
et des technologies open source Guillemet fermant
picto

Retour d'expérience sur Docker, ou comment mettre d’accord les administrateurs système et les développeurs

S’il y a bien une technologie dont on entend parler ces derniers temps, c’est bien Docker.io. Ce système de gestion de conteneur applicatif est entré dans les moeurs des développeurs et ingénieurs systèmes en deux ans. Voici un tour d’horizon des expériences que nous avons faites avec Docker, et ce sera l’occasion de faire un point sur l’avenir et la concurrence qui se profile.

S’il y a bien une technologie dont on entend parler ces derniers temps, c’est bien Docker.io.

Ce système de gestion de conteneur applicatif est entré dans les moeurs des développeurs et ingénieurs systèmes en deux ans. Certains aiment à dire que nous n’avions pas eu telle avancée technologique depuis OpenSSH. Docker est désormais un acteur majeur et fortement utilisé sur des architectures systèmes de cloud. Mais pas seulement. Docker sait se faire apprécier sur les postes des développeurs.

Voici un tour d’horizon des expériences que nous avons faites avec Docker, et ce sera l’occasion de faire un point sur l’avenir et la concurrence qui se profile.

Rappel, qu’est-ce que Docker ?

Docker est un outil de gestion de “micro-conteneurs” utilisant “libcontainer”. Développé en Go par le français Solomon Hykes, il a été rendu libre en 2013 et a rapidement été adopté par des grands comptes. La souplesse de l’outil a changé la donne.

Jusqu’à son arrivée, la création de conteneur applicatif demandait des notions relativement pointues. LXC avait déjà commencé à se tailler la part du lion, mettant à mal des solutions de “virtualisation pure”, OpenVZ et Xen ont aussi joué leur rôle. Mais ces systèmes sont essentiellement adaptés à des solutions serveurs et demandent une dose d’effort considérable en terme de configuration.

Soyons clairs, Docker n’est pas une solution de remplacement à LXC, OpenVZ, ou encore Xen. Ce n’est pas non plus une solution de virtualisation comme on l’entend avec KVM, VirtualBox ou VMWare. Docker est une autre vision, un autre fonctionnement, et ne sert pas exactement les mêmes fins.

Tout comme OpenVZ, Xen ou LXC, Docker propose un principe de “rootfs” qui n’est rien d’autre qu’une racine d’un système cible. Il va utiliser cette arborescence comme racine d’un système déporté (comme le ferait chroot) et offre une couche réseau et un système de montage. Mais il a son lot de différences.

D’abord, les images et conteneurs sont une série de couches montées en UnionFS. Cela permet d’une part de sauver de l’espace disque, mais aussi de construire rapidement un conteneur en évitant la copie complète de racine.

L’autre différence est que Docker évite la phase d’initialisation du système invité. En d’autres termes, la racine du conteneur sert uniquement d’environnement à l’application visée.

Enfin, Docker gère nativement la gestion de registre d’images versionnées. Par défaut, c’est le registre public qui est utilisé. Ce registre propose une multitude d’images prêtes à l’emploi (soit officielles, soit proposées par des utilisateurs de la communauté), et propose aussi un espace privé moyennant finance. Dans le principe, Docker se rapproche beaucoup de Git et le “Hub” peut être comparé à un service tel que GitHub. On y retrouve d’ailleurs des notions communes telles que les “commit”, les “tags” ainsi qu’un serveur “registre” distant.

Autour du projet, la communauté a été active et elle a proposé des outils de démarrage automatisée (fig, devenu DockerCompose), ou de réduire la complexité d’intégration et d’administration d’un cloud (CoreOS), des outils de monitoring (cAdvisor), etc.

Aujourd’hui, Docker inonde le monde de l’informatique. OpenStack, Amazon, Google, CoreOS, etc. Tous se penchent sur cette technologie, ou l’intègrent déjà dans leur infrastructure.

Mais la concurrence arrive !

Pratique pour le système

Le premier attrait de Docker est certainement la facilité de créer des conteneurs pour gérer des microservices. Un conteneur est avant tout une isolation quasi complète d’une application. Via la librairie “libcontainer”, Docker utilise donc l’isolation mémoire et processus au travers de la gestion des “cgroups”.

Docker ne va pas ouvrir de port sur la machine “hôte” à moins qu’on ne lui demande explicitement. Si deux conteneurs doivent communiquer via la couche ip, il est possible de les “lier” afin que seuls ces deux instances communiquent.

Cloud, scaling

La faible consommation de ressources et sa gestion de volumes ainsi que le mode “UnionFS” qui réduit l’espace disque nécessaire ont contribué à rendre Docker très populaire dans un “cloud”. En étudiant le fonctionnement de Docker, on se rend compte qu’il est très aisé de créer un système scallable et/ou de haute disponibilité.

La commande “docker” est en fait un simple client REST qui communique avec le “daemon”. Ce service (daemon) crée par défaut un socket unix (/var/run/docker.sock) qui fournit cette API. Toutes les commandes “docker” ne font qu’utiliser l’API.

L’API peut être utilisée pour écouter les évènements tels que la création, le démarrage ou la coupure d’un conteneur. En manipulant les informations que fournit cette API, il est possible de savoir quel conteneur exécute quel service, sur quel port, etc.

Si vous ne voulez pas ou ne pouvez pas utiliser des structures imposées par CoreOS, OpenStack, ... il peut être possible de créer sa propre architecture et ses propres outils assez facilement. L’API est relativement facile d’accès et très performante.

Une architecture utilisée dans un de nos projets est la suivante :

Pour simplifier le principe :

  • Chaque serveur physique esclave a un service de “découverte” qui écoute le socket Docker
  • Si un conteneur est démarré ou éteint, le service contacte le serveur maitre et fournit les informations

Le serveur maitre peut alors agir en conséquence, par exemple modifier la configuration nginx et supprimer ou enlever un serveur de “l’upstream”.

Une autre méthode peut être mise en place en modifiant la configuration de Docker pour qu’il expose l’API en mode TCP (donc accessible depuis le réseau). Cela a permis de mettre en place cette architecture :

Dans ce cas précis, un petit client se connecte à tous les serveurs esclaves et écoute tous les évènements. Ensuite le principe reste le même que précédemment, chaque évènement va permettre d’ajouter ou supprimer un serveur upstream dans nginx (par exemple).

La différence ici est que le maitre doit gérer toutes les connexions à tous les esclaves, la méthode précédente est moins couteuse car ce sont les esclaves qui se connectent au maitre.

Dans les deux cas, le serveur principal est prévenu de chaque démarrage ou extinction de conteneur et peut modifier le serveur NGinx principal, relancer des conteneurs ou encore prévenir d’un incident.

Il est aussi tout à fait possible de mettre en place deux serveurs maitres pour la gestion “failover”. La solution est adaptable et facilement maintenable.

Pratique aussi pour les développeurs

Docker est certes une solution vraiment adaptée pour les administrateurs systèmes. Mais il peut aussi rendre de sérieux services à la production, c’est-à-dire pour les développeurs. Une solution que nous avons utilisée chez un de nos clients est la conjugaison de Dockerfile et docker-compose (récupération par Docker du projet “fig”).

Le principe est de définir ce dont a besoin un poste de développeur pour exécuter le projet, de créer (si besoin) des Dockerfile qui construira des images adaptées au contraintes, et enfin un fichier docker-compose.yml qui lie les conteneurs.

En utilisant un serveur de contrôle de version (git, mercurial, svn...), il suffit alors de préparer le répertoire de projet pour y inclure ces fichiers, les sources du projet et de spécifier les volumes à monter dans les conteneurs. Ensuite, l’équipe récupère le projet et la seule commande nécessaire pour démarrer les services se résume à “docker-compose up”.

Prenons l’exemple d’un projet Drupal, 2 conteneurs peuvent être utilisés :

  • un conteneur MySQL
  •  un conteneur avec Apache + le module PHP

Les sources de Drupal sont déposées dans “/src” et montées dans le conteneur Apache. C’est le principe de “volume”, un répertoire ou un fichier locale sur l’hôte peut être attaché à un ou plusieurs conteneurs dans un répertoire spécifique. On fait de même pour le répertoire de stockage MySQL afin de ne pas perdre les enregistrements de la base de données.

Le Dockerfile pourrait donc être :

FROM debian:7
MAINTAINER admin-dt@smile.fr
 
# Installation des paquets
RUN apt-get update && \
    apt-get install \
        apache2 \
        php5 \
        php5-mysql \
        libapache2-mod-php5
 
# Lancer apache
CMD /usr/sbin/apache2ctl -D FOREGROUND

Et le fichier “docker-compose.yml” :

web:
        dockerfile: .
        volumes:
        - "./src:/var/www/drupal"
        ports:
         - "8080:80"
        links:
         - "db"
db:
        image: mysql
        volumes:
        - "./data:/var/lib/mysql"

Le service “web” est lié à “db” (voir la directive “links” dans le fichier ci-dessus), de ce fait il est possible de lire des variables d’environnement qui fournissent les adresses et les ports de la base mysql (exposés par son Dockerfile).
Ici, par exemple, les variables accessibles dans le conteneur “web” sont :

    • DB_PORT_3306_TCP_ADDR=172.17.1.24
  •  DB_PORT_3306_TCP_PORT=3306
  •  etc.

Mais il est aussi possible d’utiliser les noms de conteneurs qui sont résolus, ainsi “web” et “db” sont considérés comme des noms de machines dans les deux conteneurs.

Ainsi, l’adresse “mysql://db” est résolue. Il suffit alors de modifier le fichier de configuration de Drupal pour accéder à la base de données, et le tour est joué.
Le projet a donc cette structure :
 “data/” pour stocker les données de MySQL
 “src/” qui contient les sources de Drupal
 “Dockerfile” pour créer l’image spécifique Apache/PHP
 “docker-compose.yml” qui permet de décrire comment lancer les conteneurs

Pour que l’exemple reste simple, il n’a pas été mentionné que les fichiers de configuration Apache sont aussi des volumes montés dans les conteneurs. Cela a pour
incidence de permettre la modification de la configuration du serveur Web.

Vous l’aurez aussi remarqué, le “bind” de port est effectué. Puisqu’un développeur n’a pas forcément les droits pour utiliser le port “80”, nous mappons le port
“8080” local au port “80” du conteneur apache. Il suffit au développeur d’utiliser http://127.0.0.1:8080 pour voir son instance Drupal.

Pour comprendre la liaison, je vous laisse étudier la figure 3.

La concurrence

On pourrait presque croire que Docker est seul au monde à nager dans son océan de louanges. Mais...

Rappelons que Docker utilise libcontainer et les cgroups, de ce fait, afin de pouvoir utiliser ces capacités kernel, il faut que le service tourne en “root”. Et cela peut potentiellement être exploité...

C’est d’ailleurs ce que reproche CoreOS à Docker malgré son attrait certain pour cette technologie qui leur a permis de créer l’un des systèmes de cloud les plus connus. Docker a besoin de droits “root” afin de s’interfacer dans les cgroups. Or, un service qui tourne en “root” ouvre potentiellement une brêche.

L’équipe de développement de Docker a répondu de manière courtoise. Il est clair que les futures évolutions vont prendre en compte cette problématique et que
toutes propositions pour fixer ces failles (qui jusqu’à présent n’ont pas causé de souci particulier) seront activement étudiées. Pour éviter la panique, il faut savoir
que la possibilité d’exploitation de cette faille est relativement réduite. À ce jour, la seule faille exploitée remonte à une version datant de 2014 (version 1.0) qui a été colmatée.

Bref, CoreOS a décidé de créer son propre système de conteneur (capable d’utiliser des images Docker) nommé Rkt (que l’on prononce “rock-it”). Cependant, rien ne vous empêche de continuer à utiliser Docker avec leur solution. A peine Rkt est annoncé que le projet “LinuxContainers” (parent de LXC) annonce en collaboration de Canonical le développement de “LXD” (prononcez “el-ex-di”).

Vous l’aurez compris, tout est prêt pour que la gestion de conteneur s’approche le plus possible du kernel, et par conséquent que les performances s’accroissent.

Plus le temps passe, et plus les conteneurs s’imposent.

Mais qu’en est-il de Windows et OS X ? Pour OS X il n’y a ni annonce, ni produit existant. L’utilisation de boot2docker (une machine virtuelle prévue pour faire tourner Docker) est donc de rigueur. Pour Windows, jusqu’ici, il fallait aussi passer par boot2docker, mais une annonce laisse entrevoir une possibilité de voir des conteneurs tourner sur l’OS de Microsoft. Affaire à suivre donc.

Conclusion

Docker est clairement une technologie adaptée au développement et à l’administration système. Son apport en terme de simplification, de performance ou encore son adaptabilité rend possible la mise en place de services avec une aisance jusque là inaccessible. Quelque soit la taille de l’infrastructure, Docker offre une possibilité.

Mais ses atouts servent aussi à la production. Le développement s’homogénéise et la couche entre le pôle “développeurs” et le pôle “système” s’affine. Reste à voir à quel point les prochaines moutures vont évoluer, et ce que la concurrence va proposer.

À ce jour, Docker est encore roi dans ce domaine !

Patrice Ferlet
picto

Commentaires

Soyez la premiere personne à ajouter un commentaire sur cet article.
Ecrire un nouveau commentaire