Docker 1.12 Swarm mode – Shortcuts

Seit den ersten Tests und dem Aufbau eines Docker Swarm Clusters unter Docker 1.12 mit dem so genannten Swarm mode habe ich mich weiter mit den neuen Features von Docker 1.12 beschäftigt. Bevor ich jedoch zu einem ausführlicheren Beitrag über Docker Services in der Praxis komme, möchte ich zunächst einige Themen erläutern, die mir beim weiteren Ausprobieren aufgefallen sind. 

Node-Rollen ändern – Worker zu Manager

Ein weiterer zu Testzwecken aufgebauter Swarm sieht wie folgt aus:

geschke@waren:~$ docker node ls
ID                           HOSTNAME               MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
082s07yjictb73ch10aerioq4    chemnitz               Accepted    Ready   Active
5rbu26ms9zp8uw7fu3cc0uydr    schwerin.mushaake.org  Accepted    Ready   Active
81jpd9k6kc05dnwca0msqgm6j    frankfurt              Accepted    Ready   Active
bcuny83lllnn37vrxbwc2r5gi    rostock                Accepted    Ready   Active        Reachable
cydggci6rmv923krcvl17po5e *  waren                  Accepted    Ready   Active        Leader

Dabei fällt zunächst auf, dass „schwerin.mushaake.org“ einen FQDN (fully qualified domain name) als Hostname hat, während die anderen nur die Kurzbezeichnung tragen. Das liegt daran, dass der Hostname auf „schwerin“ im Unterschied zu den anderen Nodes in der Datei /etc/hostname mit Domain angegeben ist – warum auch immer.

Nun sind in diesem Cluster zwei Manager Nodes enthalten – und zwar „waren“ und „rostock“. Diesen sollte ein dritter Manager hinzu gefügt werden, was mit dem Kommando „docker node promote <hostname>“ möglich sein sollte:

geschke@waren:~$ docker node promote chemnitz
Node chemnitz promoted to a manager in the swarm.

Das Ergebnis war jedoch ernüchternd:

geschke@waren:~$ docker node ls
ID                           HOSTNAME               MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
082s07yjictb73ch10aerioq4    chemnitz               Accepted    Ready   Active
5rbu26ms9zp8uw7fu3cc0uydr    schwerin.mushaake.org  Accepted    Ready   Active
81jpd9k6kc05dnwca0msqgm6j    frankfurt              Accepted    Ready   Active
bcuny83lllnn37vrxbwc2r5gi    rostock                Accepted    Ready   Active        Reachable
cydggci6rmv923krcvl17po5e *  waren                  Accepted    Ready   Active        Leader

Der Node „chemnitz“ war offensichtlich noch kein Manager, was auch ein Test bestätigte:

geschke@chemnitz:~$ docker node ls
Error response from daemon: This node is not a Swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.

Eine weitere Fehlermeldung war nicht zu erkennen, und während sich die genannten Nodes problemlos als Worker hinzufügen ließen, war die Ernennung zum Manager nicht möglich.

Woran das lag, hatte sich mir zunächst nicht erschlossen. Daher wollte ich das Verhalten auf einem anderen Swarm verifizieren. Dabei handelt es sich um denjenigen aus dem letzten Artikel, mehrere VMs auf drei physischen Servern in einem privaten Netzwerk:

ID                           HOSTNAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
28v6jjr50etv4sjmx5p4yuhmp    lausen     Accepted    Ready   Active
2hwa815cxk6pf8bh4mo7hkx11    tolkewitz  Accepted    Ready   Active
3eg4vn9io09v0046tmuwibsa5    lindenau   Accepted    Ready   Active
64nf6p2azvujv291ay4g1nhwl    kaditz     Accepted    Ready   Active        Reachable
76nj42jlv8ih1lz1yp98juzf7 *  tondi      Accepted    Ready   Active        Leader
7yte21jbezc7lwznton64bwi8    pirita     Accepted    Ready   Active
9r6mfzv4gflyafi9uwikaaqvf    connewitz  Accepted    Ready   Active        Reachable
cixviuywhxd6qe2pr2f1u7rwd    miltitz    Accepted    Ready   Active

Einer der Worker sollte zum Manager ernannt werden:

geschke@tondi:~$ docker node promote lausen
Node lausen promoted to a manager in the swarm.

Das Ergebnis:

geschke@tondi:~$ docker node ls
ID                           HOSTNAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
28v6jjr50etv4sjmx5p4yuhmp    lausen     Accepted    Ready   Active        Reachable
2hwa815cxk6pf8bh4mo7hkx11    tolkewitz  Accepted    Ready   Active
3eg4vn9io09v0046tmuwibsa5    lindenau   Accepted    Ready   Active
64nf6p2azvujv291ay4g1nhwl    kaditz     Accepted    Ready   Active        Reachable
76nj42jlv8ih1lz1yp98juzf7 *  tondi      Accepted    Ready   Active        Leader
7yte21jbezc7lwznton64bwi8    pirita     Accepted    Ready   Active
9r6mfzv4gflyafi9uwikaaqvf    connewitz  Accepted    Ready   Active        Reachable
cixviuywhxd6qe2pr2f1u7rwd    miltitz    Accepted    Ready   Active

Interessanterweise hatte es diesmal problemlos funktioniert! Also untersuchte ich die Firewall-Einstellungen auf dem betreffenden Node des ersten Swarms, tatsächlich gab es dort eine Ubuntu-ufw-Firewall, jedoch waren die Ports für den Swarm eigentlich freigeschaltet. Eigentlich. Da jedoch der Node „chemnitz“ in einem vollkommen anderen Netzwerk, d.h. bei einem anderen Provider steht als die beiden Manager-Nodes „waren“ und „rostock“, vermute ich an dieser Stelle eine mögliche Ursache. Denn der Node „schwerin“ konnte wiederum zum Manager ernannt werden:

geschke@waren:~/orchestration-workshop/dockercoins$ docker node promote 5rbu26ms9zp8uw7fu3cc0uydr
Node 5rbu26ms9zp8uw7fu3cc0uydr promoted to a manager in the swarm.
geschke@waren:~/orchestration-workshop/dockercoins$ docker node ls
ID                           HOSTNAME               MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
082s07yjictb73ch10aerioq4    chemnitz               Accepted    Ready   Active
5rbu26ms9zp8uw7fu3cc0uydr    schwerin.mushaake.org  Accepted    Ready   Active        Reachable
81jpd9k6kc05dnwca0msqgm6j    frankfurt              Accepted    Ready   Active
bcuny83lllnn37vrxbwc2r5gi    rostock                Accepted    Ready   Active        Reachable
cydggci6rmv923krcvl17po5e *  waren                  Accepted    Ready   Active        Leader

Docker Services

Docker beschreibt die in der Version 1.12 neu hinzu gekommenen Services als „replizierte, verteilte, lastverteilte Prozesse in einem Swarm von Docker Engines“ (“ replicated, distributed, load balanced process on a swarm of Engines“). Letztlich handelt es sich dabei um eine neue Art, Container zu starten, zu verteilen und zu verwalten. Die bisherige Art und Weise funktioniert zwar nach wie vor, ist aber teilweise eingeschränkt. Während es im bisherigen Swarm möglich war, einen Container auch auf einem Host per „docker run...“ zu starten und dabei ein im Swarm angelegtes Overlay-Network zu nutzen, ist dies im neuen Swarm nicht mehr möglich. die Overlay-Networks beziehen sich hier nur noch auf dem Swarm und können nur mit den Services verwendet werden. Da die Beispiele zu den Services bislang eher sagen wir mal sehr beispielhaft sind, habe ich versucht, mich anhand einer realen Anwendung dem Thema zu nähern. Dazu verweise ich (schon wieder) auf den nächsten Artikel. Ein sehr, sehr simples Beispiel ist der Start eines „ping“-Kommandos innerhalb eines Containers. Anstatt diesen einzelnen Container per „docker run...“ zu starten, wird er als Service deklariert:

geschke@connewitz:~$ docker service create --name pingping alpine ping 8.8.8.8
52kd1tkp8vi2vu6ssu5oh5aqc

geschke@connewitz:~$ docker service ls
ID            NAME        REPLICAS  IMAGE                        COMMAND
52kd1tkp8vi2  pingping    1/1       alpine                       ping 8.8.8.8

geschke@connewitz:~$ docker service tasks pingping
ID                         NAME        SERVICE   IMAGE   LAST STATE              DESIRED STATE  NODE
0vzbr535s4po81o4bdeb8fuzf  pingping.1  pingping  alpine  Running 50 seconds ago  Running        pirita

An dieser Stelle steht naturgemäß die Frage nach dem „Warum?“. Was ist der Zweck dieser neuen Art? Docker selbst nennt wiederum einige Argumente – Services sind selbstheilend, belastbar, beinhalten ein internes Load-Balancing, repliziert (verteilt oder „global“, d.h. auf jedem Node laufend) und werden deklarativ definiert, d.h. der gewünschte Status wird angegeben, Docker kümmert sich um die Einhaltung. Tatsächlich klingt dies nach einigen großartigen Features – und das sind sie auch, vorausgesetzt, die Anwendung ist dementsprechend darauf ausgelegt.

Im Beispiel wurde der Service einmal gestartet und läuft auf dem Node „pirita“. Durch Constraints ist es auch möglich, die Nodes näher zu spezifizieren, auf denen der Service laufen soll.

Sollen z.B. zehn Container laufen, lässt sich der Service einfach skalieren:

geschke@connewitz:~$ docker service scale pingping=10
pingping scaled to 10

geschke@connewitz:~$ docker service ls
ID            NAME        REPLICAS  IMAGE                        COMMAND
52kd1tkp8vi2  pingping    3/10      alpine                       ping 8.8.8.8

Wie zu erkennen ist, sind zum Zeitpunkt des Aufrufs der Service-Liste erst drei Container gestartet worden. Das liegt daran, dass die meisten Nodes das zugrunde liegende Image noch nicht heruntergeladen hatten. Das Herunterladen geschieht automatisch, so dass wenig später das Kommando zu diesem und somit gewünschten Ergebnis führt:

geschke@connewitz:~$ docker service ls
ID            NAME        REPLICAS  IMAGE                        COMMAND
52kd1tkp8vi2  pingping    10/10     alpine                       ping 8.8.8.8

Eine Übersicht der jeweiligen Container erhält man mit dem „docker service tasks <servicename>„-Kommando. Das erste Beispiel zeigt den Status kurz nach dem Aufruf des scale-Befehlt, im zweiten sind bereits alle notwendigen Images heruntergeladen und die Container gestartet worden:

geschke@connewitz:~$ docker service tasks pingping
ID                         NAME         SERVICE   IMAGE   LAST STATE                DESIRED STATE  NODE
0vzbr535s4po81o4bdeb8fuzf  pingping.1   pingping  alpine  Running 4 minutes ago     Running        pirita
0s3t480ifto7uajcu2mi1qn8u  pingping.2   pingping  alpine  Preparing 20 seconds ago  Running        tolkewitz
e9shm3bdvxlfbz2w07a7p3vu4  pingping.3   pingping  alpine  Ready 20 seconds ago      Running        miltitz
5pwbxnk7ff38syqnprjvc1shh  pingping.4   pingping  alpine  Preparing 20 seconds ago  Running        lindenau
85811cca8e2kvlztn23ty6re1  pingping.5   pingping  alpine  Preparing 20 seconds ago  Running        lindenau
99zqigh5lv9c4wrn4plfa8afl  pingping.6   pingping  alpine  Running 20 seconds ago    Running        pirita
8s2bpm3tzr5cjh1sgeb4objip  pingping.7   pingping  alpine  Preparing 20 seconds ago  Running        kaditz
94z47hmv83vte7vvk52weu3hg  pingping.8   pingping  alpine  Running 20 seconds ago    Running        tondi
8lo0g0f1bjrkll26i6lhbwkv3  pingping.9   pingping  alpine  Preparing 20 seconds ago  Running        lausen
3y9z5l21psjctt17ozlt7p59e  pingping.10  pingping  alpine  Running 20 seconds ago    Running        connewitz


geschke@connewitz:~$ docker service tasks pingping
ID                         NAME         SERVICE   IMAGE   LAST STATE             DESIRED STATE  NODE
0vzbr535s4po81o4bdeb8fuzf  pingping.1   pingping  alpine  Running 6 minutes ago  Running        pirita
0s3t480ifto7uajcu2mi1qn8u  pingping.2   pingping  alpine  Running 2 minutes ago  Running        tolkewitz
e9shm3bdvxlfbz2w07a7p3vu4  pingping.3   pingping  alpine  Running 2 minutes ago  Running        miltitz
5pwbxnk7ff38syqnprjvc1shh  pingping.4   pingping  alpine  Running 2 minutes ago  Running        lindenau
85811cca8e2kvlztn23ty6re1  pingping.5   pingping  alpine  Running 2 minutes ago  Running        lindenau
99zqigh5lv9c4wrn4plfa8afl  pingping.6   pingping  alpine  Running 2 minutes ago  Running        pirita
8s2bpm3tzr5cjh1sgeb4objip  pingping.7   pingping  alpine  Running 2 minutes ago  Running        kaditz
94z47hmv83vte7vvk52weu3hg  pingping.8   pingping  alpine  Running 2 minutes ago  Running        tondi
8lo0g0f1bjrkll26i6lhbwkv3  pingping.9   pingping  alpine  Running 2 minutes ago  Running        lausen
3y9z5l21psjctt17ozlt7p59e  pingping.10  pingping  alpine  Running 2 minutes ago  Running        connewitz

Die umgekehrte Richtung geht natürlich auch:

geschke@connewitz:~$ docker service scale pingping=1
pingping scaled to 1
geschke@connewitz:~$ docker service tasks pingping
ID                         NAME        SERVICE   IMAGE   LAST STATE             DESIRED STATE  NODE
0s3t480ifto7uajcu2mi1qn8u  pingping.2  pingping  alpine  Running 5 minutes ago  Running        tolkewitz

Hier wurden alle Container bis auf die Nr. 2 beendet, Docker sorgt für die Einhaltung der Vereinbarung, denn es soll nur genau ein Task laufen. An dieser Stelle wird auch klar, dass die jeweiligen Tasks und somit zugrunde liegenden Images für derartige Aktionen ausgelegt sein müssen. Docker gewährleistet hier die Einhaltung der Deklaration, aber es ist nicht festgelegt, in welcher Reihenfolge die Container gestartet werden bzw. dass der zuerst gestartet auch derjenige ist, der beim Herunterskalieren übrig bleibt.

Der Service kann genauso einfach wieder beendet werden:

geschke@connewitz:~$ docker service tasks pingping
ID                         NAME        SERVICE   IMAGE   LAST STATE             DESIRED STATE  NODE
0s3t480ifto7uajcu2mi1qn8u  pingping.2  pingping  alpine  Running 5 minutes ago  Running        tolkewitz
geschke@connewitz:~$ docker service rm pingping
pingping
geschke@connewitz:~$ docker service ls
ID            NAME        REPLICAS  IMAGE                        COMMAND

Zwar liegt die praktische Anwendung eines solchen Beispiels in weiter Ferne, aber ich wollte dennoch zur leichteren Nachvollziehbarkeit die Kommandos in dieser Form erläutern.

Docker Swarm Visualizer

Ein sehr nettes Tool, was im Vorstellungs-Video von Docker 1.12 verwendet wurde, ist der Docker Swarm Visualizer. Damit lassen sich die neuen Docker Services in einem Swarm übersichtlich anzeigen. Die Aktualisierung geschieht nahezu in Echtzeit, somit können Änderungen in der Anzahl und Verteilung sehr gut nachvollzogen werden.

docker_swarm_visualizer

Der Start ist denkbar einfach, hier wurde auf einem der Manager Nodes folgendes Kommando verwendet:

docker run -it -d -p 8080:8080 --name="swarmvisualizer" -e HOST=connewitz -v /var/run/docker.sock:/var/run/docker.sock manomarks/visualizer

Weitere Hinweise finden sich auf der Github-Seite, auf jeden Fall lohnt sich das Ausprobieren!

Fazit

Docker 1.12 mit dem neuen Swarm mode bietet etliche neue Features, die jedoch erst einmal ausprobiert und beherrscht werden müssen. Bei den Services war ich anfangs eher skeptisch bzw. nach den ersten Versuchen ernüchtert, später jedoch umso begeisterter. Dazu später mehr…

 

2 Gedanken zu „Docker 1.12 Swarm mode – Shortcuts“

  1. Bei mir werden tasks bei einem alpine image beendet. Ich kann also quasi keine services bestehend aus mehreren tasks mit dem alpine baseimage starten und laufen lassen. Sie werden gestartet, laufen und enden dann wieder…

    1. Das kann natürlich eine Vielzahl von Ursachen haben. Ich würde hier systematisch vorgehen, z.B. erstmal versuchen, den Container nicht als Service zu starten. Falls es läuft, ist man einen Schritt weiter. Falls nicht, stellt sich die Frage, was überhaupt gestartet wird – ist ein Daemon à la Supervisord enthalten oder wird die Anwendung direkt gestartet usw.. Wenn es ganz hardcore ist, starte ich meist einen Container mit dem betreffenden Image, lasse aber eine beliebige Shell laufen, etwa:


      docker run -d -it --name test ubuntu:bionic bash

      Dann kann man in den laufenden Container „einsteigen“:

      docker exec -it test bash

      Von dort aus rufe ich dann die Anwendung so auf, wie sie ansonsten beim Start des Containers aufgerufen wird. Wenn sie sich nicht direkt beendet – ok, bestens. Wenn doch, habe ich meist nicht die richtigen Start-Parameter genutzt.

      Funktioniert das alles, liegt das Problem an anderer Stelle, dann kommt der Swarm mode ins Spiel. Hier lässt sich ohne genauere Details zu kennen, schwer raten. Ich hatte beispielsweise bereits DNS-Probleme, die dazu führten, dass die Container sich wieder beendeten, da die Dienste sich nicht gegenseitig finden konnten. Ebenfalls gab es Probleme, dass manche Nodes mit einer anderen Docker-Version bestückt waren – hier hat ein Update auf eine einheitliche Version geholfen. Ich würde auch versuchen, schnell genug zu sein (meist rennen die Container ja ein, zwei Sekunden, bis sie wieder gestoppt werden) und während der kurzen Laufzeit einen Blick ins Log zu erhaschen, oft kann man die Ursache dort herausfinden. Und dann weiter entlang hangeln.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Tags: