Docker – le réseau

J’ai mis en oeuvre mon premier conteneur hier, une instance de Gitlab que j’ai exposé sur internet. La question de la configuration du réseau et la façon dont docker s’intègre se pose. L’objectif est de limiter les configurations et les compétences requises afin de montrer que c’est accessible.

Rappel sur un reseau domestique

La configuration du schéma précédent est commune dans les accès internet grand public. Comme évoqué dans le billet De la virtualisation à la conteneurisation ce reseau domestique peut peut-être utiliser pour accueillir des services autohébergés.

Avec la mutualisation comme les services sont sur la même IP, les conflits de port surviennent. Même si on pourrait definir plusieurs interfacex reseaux ou attribuer plusieurs IP à la même interface, cela complexifie la configuration de l’hôte et le routage au niveau de la box qui possède l’ip publique. Au final pour rester simple avec une seul IP sur l’hôte, on expose autant de ports qu’il y a de services.

Avec certains protocoles comme HTTP il est possible de virtualiser les serveurs basés sur le nom de domaine. Dans le DNS il suffit d’associer plusieurs noms de domaine à la même IP publique. On diminue ainsi le nombre de ports exposés sur l’IP publique.

Le paramétrage des services pour changer leur port d’écoute n’est pas le plus compliqué mais les conflits de librairies et de paramétrage des applications sur le même hôte fini par limiter l’agilité de la solution mutualisé. La virtualisation apporte des solutions.

La configuration de chaque service est autonome ainsi les virtualappliance permettent de dupliquer les services et la couche de virtualisation quemu/kvm crée automatiquement un réseau pour les VM. Ainsi on a une IP par service. Cette IP est attribuée par adresse MAC et même si elles ne sont pas visibles du réseau local, elles sont fixes et sont accessibles par l’hôte.

Reste le problème des ports de l’hôte. On peut là aussi mutualiser certains ports pour les services basés sur le nom de domaine. Dans le cas contraire il faut ouvrir un nouveau port sur la box. Ce port devra être redirigé vers l’IP de la VM. Par défaut cette IP est interne à l’hôte et non visible du reseau local (depuis le routeur de la box) donc il faudrait faire une redirection des paquets depuis l’hôte ou bien configurer la VM en mode bridge pour qu’elle ait une IP dans le réseau local et permettre de faire une redirection depuis le routeur vers l’IP de la VM.

Dans tous les cas il faudra ouvrir un nouveau port sur la box: un part instance de service. Avec le reroutage local à l’hôte la VM reste cachée derrière l’hôte et dans l’autre la VM sera visible du reseau local.

Avec les conteneurs docker

Le dernier schema vu plus haut reste vrai avec la configuration par défaut quand on utilise docker directement sur la machine hôte. On remplace les VM par des conteneurs.

On peut toujours mutualiser les ports 80 et 443 en déployant autant de services HTTP que voulu derrière le reverse proxy. On remarque déjà que les IP1 et IP2 associées à chacun des conteneurs ne sont pas utilisérs par le reverse proxy même si l’hôte les voit. Ces IP sont ephémères et changent d’un redémarrage à l’autre du service.

Docker expose chaque services sur un port de l’hôte.

On revient à l’organisation d’un serveur mutualisé… c’est d’ailleurs ce que l’on voulait en passant de la virtualisation à l’isolation autre terme pour parler de conteneurisation.

Conteneur virtualisé

On va avoir une concurrence entre les applications docker pour l’attribution des ports de l’hôte. Or la machine hôte est également une machine de développement. Nous sommes en informatique résidentielle. Il faudra séparer les réseaux en gérant soi-même 2 réseaux sur l’hôte avec 2 IP l’une pour le dev l’autre pour la production. Outre la compétence supplémentaire, la configuration de dev sera differente de celle de production. Ce qui n’est jamais bon et qu’on cherche à éviter. Cela est encore plus vrai si on veut avoir un environnent de préprod iso-prod. Une autre machine identique en guise d’hôte…. la virtualisation répond à ce besoin.

Faire tourner docker en machine virtuelle

L’utilisation de docker en VM est d’ailleurs un moyen de permettre la scalabilité. Au lieu d’augmenter la mémoire et le nombre de process sur même hôtes, on finit par trouver plus simple d’augmenter le nombre d’hôtes et distribuer les traitements à travers ceux-ci.

On voit que d’un point de vue de l’hôte (rectangle arrondi), les services conteneurisés dans une VM sont accessible par une IP spécifique car exposés par docker sur un port de l’hôte sur lequel il tourne, c’est-à-dire avec une IP fournie par la couche de virtualisation quem/kvm.

L’étape ultime sera pour moi d’avoir sur une VM tous les services du domaine bressure.net, ainsi j’aurais totalement séparé  par virtualisation  et conteneurisation les applications qui n’ont rien à faire sur un poste de travail. A partir de là, tous ces services pourront être hébergé ailleurs ou bénéficier d’une ré-allocation sur des ressources physiques plus grande sans être limité à l’hôte.

La suite au prochain billet.

 

Docker – sautons le pas

Docker est sans doute la plus populaire des solutions de conteneurisation du moment. Elle a l’avantage d’être assez mature puisque elle existe depuis 2013. Par ailleurs de nombreux outils et une documentation suffisante existe c’est un projet très actif pour l’outillage complémentaire contrairement à Lxc.

Si dans l’article précédent //blog.bressure.net/index.php/2019/05/24/de-la-virtualisation-kvm-a-la-conteneurisation-docker/ je présentais des idées générales, dans le présent article je vais illustrer par un cas pratique de mise en œuvre étant moi même le cobaye de cette expérience de migration de VM au conteneurs avec docker.

Pas convaincu

Pour l’histoire je viens de finir d’être convaincu que la conteneurisation est supérieur à la virtualisation en terme de prédictibilité d’exécution. Comme je suis débutant avec Docker, je vais sans doute faire des erreurs et un environnement de développement avec au minimum Git est nécessaire. Pour cela, je me suis tourné vers une Virtual Appliance turnkeylinux Gitlab. Je pensais comme cela avoir une solution sur étagère pour m’offrir le service de gestion de source moderne avec éditeurs etc etc.

Malheureusement, avec une VM de 2 Go de mémoire adressable, mon Gitlab plante sur erreur 500. En passant à 3 Go même erreur. Comme je n’ai pas le temps d’investiguer, alors je me suis installé une gitlab dans docker. Et là ça a marché du premier coup !!!

Docker pour peu que les images prises soient récentes honore bien le principe de prédictibilité de l’exécution.

Revenons à mon cas

L’objectif est de migrer une quinzaine de VM constituant mes serveurs tous hébergés sur mon gros PC Linux/Debian qui fait également office de PC de bureau. Certes je m’en sers très peu, c’est donc plus un serveur mais par période il m’arrive de l’utiliser et….

Utilisation mémoire de mon serveur

… l’image ci-dessus montre de l’overcommit de mémoire et du swap malgré mon passage de 16 à 32 Mo de RAM. Entre-temps, le nombre de VM avait bien augmenté également.

VM et mémoire hôte uilisée

Récemment j’ai installé ElasticSearch et Owncloud, la mémoire de mon PC est mise à rude épreuve. Et finalement le seuil d’overcommit que je me suis fixé a été atteint aujourd’hui.

Overcommit et swap, mon serveur est à la peine

Feuille de route

La migration a pour objectif de:

  • Réduire le nombre de VM (moins d’administration etc)
  • Réduire l’empreinte mémoire des services (blog divers, owncloud etc)
  • Répondre au besoin de sauvegarde comme à l’heure actuel
  • Répondre au besoin de monitoring comme à l’heure actuel
  • Ajouter la possibilité d’avoir une préproduction complète

En option:

  • Permettre la scalabilité des services
  • L’exécution des services dans le cloud

Préliminaires

Après avoir parcouru la documentation de docker, voici les étapes à faire:

  1. Installer les dépôt docker
  2. puis docker
  3. enfin docker-compose

Toutes ces actions sont décrites dans la documentation et ce n’est pas mon propos de la dupliquer ici. Je précise en revanche leur intérêts:

Le dépôt docker plutôt que ceux de Débian afin d’avoir la dernière version de docker. Docker lui-même permettra d’exécuter des images chacune offrant un service tandis que docker-compose permettra d’agréger des services entre eux afin de constituer une application.

VOCABULAIRE

On voit que j’utilise les VM comme réceptacle pour accueillir un service ou une application : une application wordpress pour offrir un service de blog par exemple. Turnkeylinux est ainsi fait: une VM qui contient toute l’application.

Avec Docker, il faut oublier la notion de VM et surtout la relation 1-1 VM-application

Avec docker, les services sont des éléments unitaires logiciels qui s’exécutent dans un conteneur. La granularité est importante car la bonne pratique dans docker est de conserver au service la granularité la plus fine possible. Par exemple un service sera dans mon cas la couche web wordpress. Je vais donc avoir besoin d’un service de base de données en plus. Ces 2 services devront être agrégés pour constituer mon application wordpress fonctionnelle.

Heureusement que les services de bases sont déjà disponibles et c’est ce qui permet à tout un chacun de créer des applications en agrégeant des services pris sur l’étagère. Ces services sont distribués sous forme d’image docker.

Premier conteneur GItlab

Comme je l’indiquais plus haut le premier conteneur qui sera installé sur mon serveur debian, sera Gitlab pour avoir l’outillage de développement.

Faire un premier test en lançant en tant que root dans un terminal

# docker run gitlab/gitlab-ce

La première fois c’est long car il faut que docker télécharge l’image qui fait plus de 600 Mo. Quand c’est finit gitlab va envoyer une sortie de ce genre

GItlab en fonctionnement

On vient de lancer le conteneur avec aucune option. C’est juste pour la premier essai afin de prendre confiance dans en docker. On va se connecter à l’application par l’adresse ip du conteneur même. Prendre un autre terminal lancer la commande suivantes afin de voir le conteneur gitlab:

# docker container ps

Ensuite déterminer l’identifiant du réseau bridge qui est celui auquel est connecté le conteneur lancé sans aucune option.

# docker network ls

Puis regarder le réseau bridge

# docker network inspect 4f1346b59d99

Le conteneur possède l’ip 172.17.0.2 et quand on ouvre un navigateur sur cette ip depuis la machine qui a lancé la commande docker run gitlab/gitlab:ce alors on arrive sur notre instance gitlab.

GITLAB PERSISTENT

Le conteneur gitlab que l’on a lancé précédemment ne conserve pas les informations en cas d’arrêt/redémarrage. Une notion importante à garder à l’esprit, un conteneur n’est pas une VM c’est seulement l’exécution d’un service (d’un programme) dans un espace isolé. Tant que le conteneur s’exécute il écrit sur le disque dans on espace mais quand il s’éteint, tout disparaît. C’est ce que docker appelle l’éphémérité.

La plupart des services doivent être persistent. Heureusement permet de relier des répertoire du système de fichier du conteneur à un point sur la machine hôte.

Commençons par arrêter le conteneurs éphémère

# docker container stop 1b166f7989b1

Préparer un fichier de définition du service gitlab docker-compose.yml

version: "3.7"
services:

 web:
   image: 'gitlab/gitlab-ce:latest'
   restart: always
   hostname: 'gitlab.bressure.net'
   environment:
     GITLAB_OMNIBUS_CONFIG: |
       # external_url '//gitlab.bressure.net'
       # Add any other gitlab.rb configuration here, each on its own line
   ports:
      - '8080:80'
 #    - '443:443'
      - '2222:22'
   volumes:
     - '/srv/gitlab/config:/etc/gitlab'
     - '/srv/gitlab/logs:/var/log/gitlab'
     - '/srv/gitlab/data:/var/opt/gitlab'

Comme l’ip du serveur gitlab change au grès des redémarrages du conteneur, il faut passer par l’ip de l’hôte qui est bien plus stable… Je vais par la suite utiliser une redirection depuis mon frontal apache et j’aurais alors besoin d’un ip fixe vers laquelle rediriger les flux. Comme sur l’ip de l’hôte le port 80 es déjà pris par mon apache, j’indique le port 8080 comme celui sur lequel sera exposé le conteneur gitlab sur l’hôte. De même pour le port ssh pour les commit git, le port 22 étant déjà occupé sur l’hôte, le port 2222 sera utilisé pour accéder à mon serveur git dans gitlab.

En tant que root il suffit de lancer

# docker-compose up -d

La suite

Je viens de monter mon premier service docker. La prochaine étape va consister à mettre en place la redirection web et la couche TLS dans le frontal apache ainsi que la redirection pour SSH afin de pouvoir utiliser mon serveur gitlab depuis internet avant de replonger dans le conteneurisation de mes VM.