Docker Overlay Network und Updates bei der Installation von Docker 1.10.x

Im letzten Artikel habe ich beschrieben, wie Docker Swarm auf KVM-basierten virtuellen Maschinen eingerichtet wurde. Von da an ist es nur noch ein kleiner Schritt zur Konfiguration eines Overlay Networks.

Mit einem Overlay Network ist es möglich, mehrere Docker Hosts so zu verbinden, dass der Eindruck entsteht, sie befinden sich im selben Netzwerk. Üblicherweise stehen die Docker Hosts für sich, auch wenn sie mittels Docker Swarm angesprochen werden, handelt es sich zunächst einmal um einzelne Komponenten, die ihre eigenen Netzwerkressourcen besitzen. Wenn nun ein Docker Container auf einem Host gestartet wird, ist es zwar möglich, dass Ports nach aussen hin frei gegeben werden, dies muss aber nicht so sein. Falls nicht, ist die Sichtbarkeit auf den jeweiligen Host beschränkt, d.h. das Verlinken mittels „–link“-Option ist auf einen einzelnen Docker-Host beschränkt.

Das Overlay Network löst dieses Problem, indem es ein gemeinsames Multi-Host-Network aufbaut. Damit wird es erreicht, dass sich Docker Container, die auf verschiedenen Hosts laufen, „sehen“. Zum Beispiel könnte ein Container unter dem Namen „db01“ als Datenbank-Container auf einem Host gestartet werden, während ein Container namens „web01“ auf einem anderen Host läuft. Das Overlay Network legt ein eigenes virtuelles Netz an, in dem die jeweiligen Container einfach über ihren Namen angesprochen werden können. Man könnte es insofern auch als „Linken“ über mehrere Hosts hinweg bezeichnen. Die Option „--link“ ist beim Start von Container jedoch nicht notwendig bzw. in dem Fall nicht erlaubt, jedoch muss das zu verwendende Netz mit „--net“ angegeben werden.

Wesentlich detaillierter, mit Skizzen etc. werden die Netzwerk-Fähigkeiten von Docker wie üblich in der Docker-Dokumentation beschrieben, es lohnt sich auch allein deshalb, einen Blick zu riskieren, da jene Features in der letzten Zeit intensiv ausgebaut wurden, so dass beinahe mit jeder neuen Version von Docker auch weitere Netzwerk-Optionen hinzu gekommen sind.

Des Weiteren gehe ich im Folgenden davon aus, dass sich alle Hosts bereits in einem Netzwerk befinden und sich alle untereinander auf beliebigen Ports ansprechen können. Sollte die Konfiguration z.B. unter Amazon AWS auf EC2-Maschinen stattfinden, müssen einige Ports in der jeweiligen Security Group zur internen Verwendung freigegeben werden. Diese Ports (Data Plane VXLAN 4789/udp, Control Plane 7946/tcp/udp) dienen zur internen Kommunikation und sollten somit nicht frei zugänglich für die Welt sein. Da sich das Beispiel auf ein internes, abgesichertes Netzwerk bezieht, sind derartige Vorarbeiten jedoch nicht notwendig.

Genug der Vorrede, denn die Einrichtung selbst ist tatsächlich mit einem einigen Kommando sehr schnell geschehen:


Wir befinden uns auf dem Host, von dem der gesamte Swarm eingerichtet wurde, d.h. es besteht Zugang zu den Docker Hosts, der Swarm hat den Namen „miltitz“, das Kommando lautet einfach „network create <overlaynetwork>

Ferner kann die Option „--driver overlay“ angegeben werden, in der verwendeten Docker Version war dies noch nicht nötig, aber vermutlich wird es in den nächsten Releases wieder einige Erweiterungen geben, so dass die genaue Angabe ratsam erscheint.

Der (gekürzte) Hash zeigt an, dass die Einrichtung erfolgreich war.

 

Zur Kontrolle lassen sich alle Netzwerke anzeigen:


Natürlich will dies noch genauer getestet werden. Dazu werden zwei Container erzeugt, einerseits ein Web-Server Nginx aus dem Standard-Image, andererseits eine Shell, von der aus der Web-Container erreichbar sein soll.

Nginx:


Shell


Zugegebenermaßen habe ich mich in dem Beispiel an diversen Blog-Beiträgen und der Docker-Dokumentation bedient. Als nächstes wird geprüft, auf welchen Hosts die soeben gestarteten Container laufen. Zwar hätte sich auch der Host über Constraints spezifizieren lassen (--env="constraint:node==kaditz"), aber die im Swarm per Default agierende Spread-Strategie hat möglicherweise bereits dafür gesorgt, dass eine Verteilung der Container auf die Hosts stattfindet.

So auch hier:


Wie leicht zu erkennen ist, wurde der „web“-Container auf dem Host „tolkewitz“ gestartet, während „shell1“ auf „miltitz“ läuft.

Für den Test kann man sich mit dem Shell-Container verbinden:


Von dort aus sollte der andere Container erreichbar sein, und zwar einfach über dessen Namen:


Natürlich können auch die im Web-Container gestarteten Dienste erreicht werden, in dem Fall Nginx:


Noch eine Anmerkung zur Weiterentwicklung von Docker: Bis zur Version 1.9 wurde in den jeweiligen Containern die Datei /etc/hosts verwendet, um die Zuordnung der Namen zu den im Overlay Network verwendeten IP-Adressen zu erreichen. Dies sah z.B. so aus:


Je mehr Container sich im Overlay Network befanden, desto länger wurde die Datei, des Weiteren musste diese beim Start oder beim Beenden von Containern jedes Mal aktualisiert werden.

Mit der Version 1.10 ist nun ein in Docker eingebetteter DNS-Server hinzu gekommen, der für die Namensauflösung zuständig ist. Damit bleibt die /etc/hosts von Änderungen befreit:


Auch darauf weist Docker in der entsprechenden Dokumentation hin, nur könnte es u.U. beim Umstieg von Versionen vor 1.10 zur Verwunderung führen, dass keine Einträge in der hosts-Datei mehr vorhanden sind, die Verbindung jedoch dennoch funktioniert.

Natürlich war dies nur ein kleines, vielleicht wenig praxisrelevantes Beispiel eines Overlay-Networks mit Docker. Tatsächlich sind die Netzwerk-Features inzwischen sehr mächtig geworden und werden ständig weiter ausgebaut. Die auf einzelnen Docker-Hosts mögliche Verknüpfung via „Linken“ ist dabei fast komplett ersetzt worden. In der Praxis setzen wir momentan eine Docker-Installation ein, die aus mehreren Datenbank-Container, mehreren Application-Containern, mehreren Worker-Containern und einem Redis-Container besteht, dazu kommen noch diverse Container für die Management-Funktionen, nebst Docker Swarm inkl. Consul betrifft dies auch Container für das Monitoring, Logging und UIs wie z.B. resque-web. Mit Docker Swarm werden die Container auf die jeweiligen Hosts verteilt, teilweise mittels Constraints auf die für den jeweiligen Zweck vorgesehene Maschine. Bei anderen ist es hingegen irrelevant, auf welchem Host sie laufen, denn dank der Ansprechbarkeit über ihren Namen innerhalb des Overlay-Networks benötigen sie keine strikte Abhängigkeit wie eine IP-Adresse. Die gesamte Installation läuft auf einem EC2-Cluster innerhalb von Amazon AWS, siehe dazu die Anmerkungen zur Security Group. Evtl. gehe ich in einem späteren Artikel noch genauer auf die Konfiguration ein, auch hier gilt, dass Docker grundsätzlich noch relativ neu ist und es noch einige Änderungen geben wird, mit denen man rechnen und auf die man reagieren muss.

Docker Engine 1.10 mit Systemd unter Ubuntu

Eine der Änderungen ist z.B. die nun vereinfachte Installation unter Ubuntu. Im Artikel über die Einrichtung des Docker Swarm hatte ich den Workaround beschrieben, der notwendig war, damit die Docker Engine unter Ubuntu 15.10 mit Systemd läuft.

Die gute Nachricht – dies ist ab Docker 1.10 nicht mehr notwendig. So bringt Docker alles mit, was für eine funktionierende Startsequenz benötigt wird. Die Optionen sind nun in der Datei /etc/systemd/system/docker.service vorhanden, diese Datei wird auch aus dem Docker-Paket angelegt bzw. bei der Einrichtung  mittels Docker Machine konfiguriert.

Die schlechte Nachricht – falls bereits der Workaround oder andere Wege eingesetzt wurden, damit Docker unter Systemd gestartet wird, sorgt die neue Service-Datei für einen Konflikt, so dass Docker evtl. gar nicht mehr gestartet wird.

Mit Docker Machine 0.6 ist auch eine neue Option hinzu gekommen, und zwar das Kommando „provision“. Damit lässt sich die Provisionierung, also Einrichtung von Docker Swarm etc. erneut auf einem bestehenden Docker Host durchführen. In der Praxis ist dies ein sehr sinnvolles Kommando, tatsächlich habe ich durch diverse Experimente mit Consul mal einen laufenden Docker Swarm so „zerschossen“, dass nahezu nichts mehr lief und ein neuer Aufbau des Swarm Clusters notwendig war. Die erneute Provisionierung hat dabei einigen Aufwand erspart.

Bei Ausführung der Provisionierungs-Kommandos oder auch durch das Generieren neuer TLS-Zertifikate versucht docker-machine Docker so einzurichten, dass die neue Systemd-Service-Datei benutzt wird. Sollte dabei der Workaround vorhanden sein, geht dies schief.

 

Um Abhilfe zu schaffen, sollte zunächst das Kommando ausgeführt werden, auch wenn der nicht erfolgreiche Abschluss bereits bekannt ist:


Das heißt nichts anderes, als dass der Docker-Daemon nicht (mehr) läuft, da es beim Restart zu Problemen kam.

Die entsprechende Systemd-Service-Datei wurde jedoch bereits erzeugt. Daher kann man sich nun auf dem Docker-Host einloggen und den Workaround aufräumen:


Da docker-machine dafür gesorgt hat, dass die Konfiguration in der neuen Datei „docker.service“ abgelegt wurde, sollte der Restart genügen, um Docker wieder zum Laufen zu bringen. Danach laufen jedoch zunächst die Container, die zuvor ebenfalls gestartet wurden. Bei der Provisionierung hingegen erzeugt docker-machine normalerweise neue swarm- bzw. neue swarm-master-Container. Falls die alten noch laufen, bricht der Vorgang ab – docker-machine erkennt somit nicht, dass man evtl. gerne den bestehenden Swarm neu aufbauen möchte:


Einerseits eine aus Docker-Engine-Sicht logische Verfahrensweise, da derselbe Name „swarm-agent“ ja bereits auf dem Docker Host existiert, andererseits mutet es auch ein wenig merkwürdig an, da man die Provisionierung ja gerade aus dem Grund durchführen könnte, den Swarm neu aufzubauen. Evtl. wäre hier eine Abfrage des gewünschten Verhaltens eine sinnvolle Option. Natürlich ist die Lösung einfach – es genügt, den swarm-agent auf dem jeweiligen Host zu stoppen und zu entfernen, womit der Namenskonflikt gelöst ist. Danach kann docker-machine wieder aktiv werden.

Soviel für heute mit den Geschichten aus dem Docker-Land, wobei das Buch noch lange nicht geschlossen ist und noch Platz für einige mehr oder minder spannende Episoden bietet…

Ähnliche Beiträge

Tags:

Schreibe einen Kommentar

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