Die hybride Cloud mit Docker Swarm und Ansible, Teil 1

Seite 2: Windows Vagrant Box mit Packer

Inhaltsverzeichnis

Egal für welche Lösung man sich entscheidet: Ein vollständig nachvollziehbares und automatisiertes Setup sollte das Ziel sein. Denn gerade bei neuen Technologien wie den nativen Docker-Windows-Containern kann es immer mal wieder zu unvorhergesehenen Problemen kommen. Wenn jedoch einfach alles wieder automatisiert bereitstellbar ist, sind Fehler leichter zu beheben.

Für eine solche Vorgehensweise ist der Einsatz eines der zahlreichen "Infrastructure-as-Code"-Werkzeuge von Nöten. Im Artikel zu Docker-Windows-Containern hat sich das Tool Vagrant bewährt. Es kann nicht nur einzelne Maschinen verwalten, denn mit dem Vagrant-Multi-Machine-Setup lassen sich mehrere virtuelle Maschinen mit dem einfachen Kommando vagrant up hochfahren. Das Vorgehen hat den Vorteil, dass das entstehende Setup überall lokal nachvollziehbar und danach leicht auf das jeweilige Deployment-Szenario zu adaptieren ist – sei es eine On-Premise-Installation oder einer der zahlreichen Cloud-Provider.

Für das Aufsetzen eines hybriden Clusters benötigt man neben einer Linux Vagrant Box eine entsprechende mit Windows Server 2016. Da es keine offizielle Vagrant Box für den Docker-Windows-Container-Betrieb von Microsoft gibt, ist sie selbst zu erstellen. Wie das geht zeigt der Artikel "Docker-Windows-Container mit Ansible managen". Das dort verwendete Setup mit Packer.io lässt sich nahezu vollständig wiederverwenden. Es gilt nur einen kleinen Unterschied im Vagrantfile-Template von Packer abzubilden. Im Vorartikel ist direkt eine konkrete Virtual-Box-Instanz sowie ein passendes Port-Forwarding konfiguriert. Beides führt aber bei mehreren Windows-Servern zu Problemen, denn es kann immer nur eine Virtual-Box-Instanz mit dem gleichen Namen geben, und es lässt sich nur ein bestimmter Port an einen Host binden. Ein eigenes Vagrantfile-Template kann das Dilemma jedoch elegant umgehen. Das vagrantfile-windows_2016- multimachine.template, das das aus dem Vorartikel bekannte GitHub-Repository ansible-windows-dockerspringboot bereithält, fällt im Vergleich etwas kleiner aus:

Vagrant.configure("2") do |config|
config.vm.box = "windows_2016_docker_multi"
config.vm.guest = :windows

config.windows.halt_timeout = 15

# Configure Vagrant to use WinRM instead of SSH
config.vm.communicator = "winrm"

# Configure WinRM Connectivity
config.winrm.username = "vagrant"
config.winrm.password = "vagrant"
end

Um Packer ein anderes Vagrantfile-Template unterschieben zu können, ist eine Anpassung der Packer-Konfigurationsdatei erforderlich, was in der Datei windows_server_2016_docker.json geschieht, die nun das Mitgeben eines Vagrantfile-Template-Namens mit dem Parameter template_url sowie zusätzlich die Definition des Namens der Vagrant Box von außen per box_output_prefix unterstützt. Jetzt lassen sich die für das vorliegende Setup benötigten Windows-Server-Vagrant-Boxen erzeugen.

Dazu ist das GitHub-Repository ansible-windows-dockerspringboot zu klonen und der folgende Packer-Befehl innerhalb des Ordners step0-packer-windows-vagrantbox auszuführen. Wichtig ist nur, dass aktuelle Packer- sowie Virtual-Box-Versionen installiert sind.

packer build -var iso_url=14393.0.161119
1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO -var
iso_checksum=70721288bbcdfe3239d8f8c0fae55f1f -var
template_url=vagrantfile-windows_2016-multimachine.template -var
box_output_prefix=windows_2016_docker_multimachine
windows_server_2016_docker.json

Die Befehlsausführung kann sich etwas in die Länge ziehen. Danach sollte die Vagrant-Box windows_2016_docker_multimachine_virtualbox.box im Verzeichnis step0-packer-windowsvagrantbox vorliegen. Das sollte man danach der lokalen Vagrant-Installation bekannt machen:

vagrant box add --name windows_2016_multimachine
windows_2016_docker_multimachine_virtualbox.box

Jetzt lässt sich das Vagrant-Multi-Machine-Setup aufbauen. Dazu liegt im Verzeichnis step4-windowslinux- multimachine-vagrant-docker-swarm-setup das Vagrantfile bereit. Es beschreibt die Grundstruktur der lokalen Cloud-Infrastruktur. Zu Gunsten der Lesbarkeit sind die Details etwas gekürzt:

Vagrant.configure("2") do |config|

# One Master / Manager Node with Linux
config.vm.define "masterlinux" do |masterlinux|
masterlinux.vm.box = "ubuntu/trusty64"
...
end

# One Worker Node with Linux
config.vm.define "workerlinux" do |workerlinux|
workerlinux.vm.box = "ubuntu/trusty64"
...
end

# One Master / Manager Node with Windows Server 2016
config.vm.define "masterwindows" do |masterwindows|
masterwindows.vm.box = "windows_2016_multimachine"
...
end

# One Worker Node with Windows Server 2016
config.vm.define "workerwindows" do |workerwindows|
workerwindows.vm.box = "windows_2016_multimachine"
...
end
end


# One Worker Node with Linux
config.vm.define "workerlinux" do |workerlinux|
workerlinux.vm.box = "ubuntu/trusty64"
workerlinux.vm.hostname = "workerlinux01"
workerlinux.ssh.insert_key = false
workerlinux.vm.network "forwarded_port", guest: 22,
host: 2232, host_ip: "127.0.0.1", id: "ssh"

workerlinux.vm.network "private_network", ip: "172.16.2.11"

workerlinux.vm.provider :virtualbox do |virtualbox|
virtualbox.name = "WorkerLinuxUbuntu"
virtualbox.gui = true
virtualbox.memory = 2048
virtualbox.cpus = 2
virtualbox.customize ["modifyvm", :id, "--ioapic", "on"]
virtualbox.customize ["modifyvm", :id, "--vram", "16"]
end
end

Grundsätzlich entsprechen die Konfigurationsparameter denen einer einzelnen Maschine, beispielsweise der Parameter box, der auf die zu nutzende Vagrant Box verweist. Interessanter ist die Netzwerkkonfiguration: Da später Ansible den hybriden Cluster provisioniert, muss der jeweilige Port der Maschine im Cluster bekannt sein. Dazu setzt man ihn mit dem Schlüsselwort "forwarded_port". Ohne den Konfigurationsparameter ist das Vagrant-eigene Port-Correction-Feature aktiv und weist zufällig einen anderen Port zu, denn auf dem Host-System kann ein Port nur einmalig belegt sein. Mit der expliziten Konfiguration ist sichergestellt, dass sich Ansible immer auf den konfigurierten Port verlassen kann und es zu keinen bösen Überaschungen kommt.

Dem Parameter id kommt eine besondere Rolle zu, denn Vagrant definiert standardmäßig Ports für SSH beziehungsweise WinRM, die es zu überschreiben gilt. Das klappt mit id: "ssh" für Linux- und id: "winrm-ssl" für Windows-Boxen.