Die hybride Cloud mit Docker Swarm und Ansible (2/2)

Seite 2: HTTP-basierte Docker-Registries erlauben

Inhaltsverzeichnis

Der letzte Schritt des Playbooks prepare-docker-nodes.yml – und damit in der Konfiguration von Docker auf allen Cluster- Nodes – kann im ersten Moment für Verwunderung sorgen. Wie bereits erwähnt, soll der finale Docker Swarm für das spätere Applikations-Deployment vorbereitet sein. Der im Vorartikel "Docker-Windows-Container mit Ansible managen" verwendete Ansatz sorgt im aktuellen Kontext allerdings für viel Zusatzaufwand. Er basiert nämlich darauf, die Docker-Images auf einer Windows-Vagrant-Box zu bauen. In einer hybriden Cloud-Umgebung sind allerdings viel mehr als eine Maschine im Einsatz, wie im vorliegenden Beispielszenario mit vier Vagrant-Boxen. Die Docker-Images auf jeder Maschine neu zu bauen, ist nicht praktikabel.

Besser gelingt das Bereitstellen der Docker-Images für jeden Cluster-Node mit einer lokalen Docker Registry. Mit ihr muss man das Docker-Image nur einmal bauen und allen anderen Cluster-Nodes über die Registry verfügbar machen.

Eine lokale Docker Registry als Docker Swarm Service zu starten, benötigt an dieser Stelle etwas Vorbereitung. Die einfachste Art, eine lokale Docker Registry bereitzustellen, ist die sogenannte plain-htp-Registry. Sie sollte im vorliegenden isoliert deployten Beispiel kein großes Sicherheitsrisiko darstellen – genauso wie in vielen On-Premise-Installationen. Wichtig ist allerdings das Update auf eine per TLS-Zertifikate gesicherte Registry, sobald diese von außen zugreifbar sein soll, und etwa das Deployment des Docker Swarm auf den Systemen eines Cloud-Providers stattfindet.

Für den einfachen Fall einer plain-http-Registry muss jede Docker-Engine auf jedem Cluster-Node die Ausführung solcher "ungesicherter" Registries erlauben. Die Konfiguration ist mit der Datei daemon.json möglich, die die folgenden Zeilen enthalten muss:

 {
"insecure-registries" : ["172.16.2.10:5000"]
}

Da die Ausführung der Docker Swarm Registry später auf dem Linux-Manager-Node stattfindet, enthält die Zeile dessen IP-Adresse 172.16.2.10. Zur Erinnerung: die IP-Adresse ist explizit im Vagrantfile für diese Maschine konfiguriert.

Natürlich ist die korrekte Ablage der Datei im vorliegenden Beispielprojekt per Ansible automatisiert. Das dafür inkludierte Playbook allow-http-docker-registry.yml gibt dann auch die für das jeweilige Betriebssystem passenden Pfade der Datei daemon.json preis:

- name: Template daemon.json to /etc/docker/daemon.json on Linux nodes for later Registry access
template:
src: "templates/daemon.j2"
dest: "/etc/docker/daemon.json"
become: yes
when: inventory_hostname in groups['linux']

- name: Template daemon.json to C:\ProgramData\docker\config\daemon.json on Windows nodes for later Registry access
win_template:
src: "templates/daemon.j2"
dest: "C:\\ProgramData\\docker\\config\\daemon.json"
when: inventory_hostname in groups['windows']

Damit sind die Docker-Engines auf allen Cluster-Nodes bereit für den Einsatz im Docker Swarm.

Nachdem sichergestellt ist, dass die Docker-Engines auf allen Nodes korrekt konfiguriert und lauffähig sind, kann nun die Initialisierung des Docker Swarm beginnen. Dazu enthält das Beispiel-Repository auf GitHub das Ansible-Playbook initialize-docker-swarm.yml mit allen Schritten, die für einen vollständig lauffähigen Docker Swarm notwendig sind. Wieder sollte sich das Playbook ohne tiefergehende Kenntnisse der Details erschließen:

- hosts: all
vars:
masterwindows_ip: 172.16.2.12

tasks:
- name: Checking Ansible connectivity to Windows nodes
win_ping:
when: inventory_hostname in groups['windows']

- name: Checking Ansible connectivity to Linux nodes
ping:
when: inventory_hostname in groups['linux']

- name: Open Ports in firewalls needed for Docker Swarm
include: prepare-firewalls-for-swarm.yml

- name: Initialize Swarm and join all Swarm nodes
include: initialize-swarm-and-join-all-nodes.yml

- name: Label underlying operation system to each node
include: label-os-specific-nodes.yml

- name: Run Portainer as Docker and Docker Swarm Visualizer
include: run-portainer.yml

- name: Run Docker Swarm local Registry
include: run-swarm-registry.yml

- name: Display the current Docker Swarm status
include: display-swarm-status.yml

Vor der genauen Betrachtung der Inhalte des Playbooks empfiehlt sich dessen Ausführung. So sind alle weiteren Schritte wieder lokal nachvollziehbar. Das geht am Einfachsten im bekannten Verzeichnis step4- windows-linux-multimachine-vagrant-docker-swarm-setup mit dem Befehl:

 ansible-playbook -i hostsfile initialize-docker-swarm.yml 

Am Ende der Ausführung des Playbooks steht ein vollständig initialisierter Docker Swarm für das Applikations-Deployment bereit. Wie gewohnt bietet ein Playbook immer eine genaue Beschreibung der notwendigen Schritte zur Installation, die selbst ohne Ansible-Kenntnisse durchführbar sind. Die ersten zwei tasks des Playbooks initialize-docker-swarm.yml sind nicht unbekannt. Sie überprüfen zu Beginn, ob Ansible mit allen Cluster-Nodes einwandfrei kommunizieren kann.

Direkt danach folgt der Aufruf des Playbooks prepare-firewalls-for-swarm.yml, das für den Swarm notwendige Ports öffnet. Innerhalb der Docker-Dokumentation findet der Punkt erst weit am Ende Erwähnung – auch wenn die geöffneten Ports eine Voraussetzung für den späteren Docker-Swarm-Betrieb sind. Über den geöffneten TCP-Port 2377 können die Docker-Swarm-Nodes mit dem Windows-Manager-Node kommunizieren und sich damit zu einem funktionierenden Schwarm zusammenfügen. Dazu verwendet man im Playbook die Bedingung when: inventory_hostname in groups['masterwindows']. Sie stellt sicher, dass der Port nur auf dem Windows-Manager-Node eine Freigabe erhält.

Die zwei folgenden Portfreischaltungen beschreibt die Dokumentation ebenfalls als essenziell für einen funktionierenden Docker Swarm: "[...] you need to have the following ports open between the swarm nodes before you enable swarm mode."

Verwunderlich, dass sie dort erst am Ende auftauchen. Denn die Freischaltungen müssen vor der Initialisierung des Docker Swarm passieren. Dabei ist der TCP/UDP-Port 7946 für die gegenseitige Erreichbarkeit der Container im Docker-Swarm-Netzwerk notwendig. Das Docker-Swarm-Overlay-Netzwerk benötigt den UDP-Port 4789.