Dans un précédent billet, j’avais évoqué la difficulté de construire un réseau de conteneurs Docker répartis sur plusieurs machines hôtes, l’interconnexion de 2 conteneurs n’étant possible qu’au sein d’un même hôte Docker.
L’autre limitation est la difficulté d’accéder, via un port unique, à 2 ou plusieurs conteneurs co-localisés dans le même hôte (par exemple, 2 serveurs web dockerisés dans le même hôte et écoutant tous deux sur le port 80).
Ces lacunes sont comblées par des solutions diverses, en compétition les unes avec les autres, les plus connues étant :
- Weave, objet de ce billet
- SocketPlane, racheté par Docker pour former le futur Docker Network (libnetwork)
- Open vSwitch
Note : Avant d’entrer dans le vif du sujet, rappelons deux annonces importantes de l’édition DockerCon 2015, la conférence annuelle organisée par Docker :
- Docker Network, annoncée pour la version 1.7, est issu en partie de l’intégration de SocketPlane
- Docker Plugin est un mécanisme permettant d’étendre les fonctionnalités de Docker Engine sous la forme de modules d’extension Docker Network a été conçu selon le principe “Batteries included, but removable” ouvrant la voie au développement de drivers réseau par des sociétés tierces sous la forme de plugins, ce qui est déjà le cas de Weave.
Avec Docker Network, nous disposerons donc d’une interface standardisée de gestion d’un réseau de conteneurs, à l’image de Docker Machine pour le provisionnement d’hôtes Docker. J’y reviendrai dans un prochain billet. Fin de la longue parenthèse.
Dans ce billet, nous explorerons en détail le fonctionnement et la mise en oeuvre de Weave à travers un cas pratique.
De l’intérêt de Weave
Weave permet d’interconnecter des conteneurs répartis sur plusieurs hôtes Docker, indépendamment de leur localisation physique, afin de constituer un réseau virtuel de conteneurs.
La disponibilité d’un mécanisme de découverte de service par DNS parachève un dispositif adapté à la construction d’une architecture de microservices.
Fonctionnement
Un réseau Weave est constitué de routeurs virtuels installés sur chacun des hôtes Docker et connectés entre eux en pair à pair.
Les routeurs sont en fait des conteneurs Docker maintenant entre eux une connexion TCP pour échanger des informations sur la topologie du réseau ainsi que des connexions UDP pour acheminer le trafic inter-conteneur.
Lorsque qu’un conteneur rejoint le réseau Weave, il est relié au routeur à travers une interface réseau virtuelle (bridge weave
).
Etude de cas
Le schéma ci-dessous décrit l’architecture constituée de 2 serveurs hébergeant chacun un hôte Docker et un routeur Weave.
Deux services dockerisés (svc1
, svc2
) sont déployés sur l’hôte orion.local
(sous Ubuntu), tandis que le service svc3
est déployé sur l’hôte macbook.local
(sous Boot2Docker).
Les services dockerisés sont issus de l’image ksahnine/dummy-http
, un service REST HTTP de test écoutant par défaut sur le port 8080
et utilisable comme suit :
- création du conteneur :
$ docker run -td -p 8080:8080 ksahnine/dummy-http svcN
- appel du service dockerisé :
$ curl http://host_ip:8080/ Hi! I'm [svcN] service and my Docker container's IP is [container_ip]
Notez sur le schéma le plan d’adressage des conteneurs dans le réseau weave (10.0.1.x/24
). Les adresses IP sont attribuées à la création des conteneurs.
Installation
Weave est distribué sous la forme d’images Docker, dont la disponibilité est évidemment un préalable.
L’utilisation des composants dockerisés de Weave (routeur, DNS, proxy) est encapsulé par un script shell faisant office d’interface CLI (weave
) installé sur chaque hôte Docker.
Sous Ubuntu / CentOS
Le mode opératoire d’installation est le suivant :
Sous Boot2Docker (Windows / MacOS)
Le mode opératoire d’installation est le suivant :
Démarrage des routeurs Weave
Démarrer le routeur Weave sur chacun des noeuds (orion.local
et macbook.local
) via la commande weave launch
:
Pour relier les 2 routeurs, connectons-nous sur l’un des noeuds, par exemple orion.local
, et utilisons la commande weave connect
suivie de l’adresse IP publique (sur le réseau physique) du second noeud :
Note : La commande
weave status
permet de connaître l’état du routeur.
Déploiement des services dockerisés sur le réseau Weave
La commande weave run
permet de démarrer un conteneur et de le relier au réseau Weave. Elle est immédiatement suivie de l’adresse IP assignée sur le réseau virtuel :
- sur
orion.local
:
orion.local:~$ sudo weave run 10.0.1.1/24 ksahnine/dummy-http svc1 orion.local:~$ sudo weave run 10.0.1.2/24 ksahnine/dummy-http svc2
- sur
macbook.local
:
macbook.local:~$ sudo weave run 10.0.1.3/24 ksahnine/dummy-http svc3
Note : La commande
weave run
démarre le conteneur en mode détaché (en tâche de fond). Par ailleurs, les ports exposés par le conteneur sont par défaut accessibles à l’extérieur du conteneur.
Accéder aux services dockerisés
A ce stade, le réseau de conteneurs est opérationnel. Voyons comment invoquer les services dockerisés de l’hôte orion.local
depuis un conteneur localisé sur macbook.local
.
Pour la démonstration, créons un nouveau conteneur issu de l’image Docker tutum/curl
de l’hébergeur Tutum sur macbook.local
et relié au réseau Weave :
Accédons à la console du conteneur :
Note : Penser à taper sur la touche
Enter
pour avoir le prompt.
Appelons les 3 services via cURL :
Plusieurs remarques :
- notez que les 2 services
svc1
etsvc2
, co-localisés sur le même hôte Docker, sont accessibles à travers le même port ! (8080
) - l’adresse IP retournée par le service (
172.17.0.x
) est celle de l’interface veth reliée au bridgedocker0
. Chaque conteneur a donc 2 interfaces réseaux :- l’une reliée au sous-réseau créé par Docker et partagé entre l’hôte et ses conteneurs
- l’autre reliée au réseau virtuel Weave :
- il devrait être possible de remplacer le bridge
docker0
par le bridge weave via l’option--bridge
du démon Docker, mais je n’ai pas encore testé. Voir la documentation de Docker : Advanced networking.
Simplifier le déploiement avec Weave Proxy
Weave Proxy est un conteneur Docker interceptant toutes les commandes émises par le client Docker vers le démon Docker.
Il permet d’utiliser directement la commande docker run
pour enregistrer automatiquement un conteneur sur le réseau Weave ou dans un DNS comme on le verra dans le paragraphe suivant.
Sur chaque noeud :
- lancer le routeur et le proxy Weave :
\# weave launch && weave launch-proxy
Note : le cas échéant, utiliser la commande
weave reset
pour réinitialiser le routeur Weave.
- configurer le client Docker pour le faire pointer vers Weave Proxy :
\# \`weave proxy-env\`
ce qui est équivalent à :
\# export DOCKER_HOST=tcp://127.0.0.1:12375
Créons un conteneur et assignons lui une adresse IP spécifique sur le réseau Weave :
Le support d’IPAM permet d’assigner automatique d’une adresse IP au conteneur. Il suffit d’omettre la variable d’environnement WEAVE_CIDR
, soit :
La plage d’adresse IP peut être redéfinie au lancement du routeur via l’option -iprange
, par ex: weave launch -iprange 10.2.3.0/24
.
Découverte de services par DNS
En combinant le routeur Weave, le proxy Weave et le DNS Weave, il est aisé de mettre en oeuvre une solution de découverte de service totalement dynamique.
Pour ce faire, il suffit d’activer les 3 composants Weave sur chaque noeud :
- lancer le routeur, le DNS et le proxy Weave :
\# weave launch && weave launch-dns && weave launch-proxy
- configurer le client Docker pour le faire pointer vers le proxy Weave :
\# \`weave proxy-env\`
Déployons le service svc1
:
Note : le paramètre
--name
est utilisé pour enregistrer le service dans le DNS. Ainsi, son nom pleinement qualifié serasvc1.weave.local
.
Créons un nouveau conteneur issu de l’image Docker tutum/curl
de l’hébergeur Tutum sur macbook.local
et relié au réseau Weave :
Enfin, vérifions que le service est accessible sous son nom pleinement qualifié (svc1.weave.local
) :
Noter que l’architecture est scalable horizontalement en déployant le service svc1
sur plusieurs hôtes Docker et ce, sans répartiteur de charge ou reverse-proxy.