RED „Runtime Environment for Developers“ – Ein erster Blick unter die Haube

1 Kommentar

Im ersten Artikel dieser Blogserie hat mein Kollege Lukas Pustina bereits eine Einführung in RED (Runtime Environment for Developers), unserer Docker basierten Entwicklungsumgebung, gegeben. In diesem Artikel werde ich auf die ersten technischen Details von RED eingehen. Das Projekt ist auf GitHub verfügbar und wird mit jedem nachfolgenden Artikel dieser Serie erweitert.

Im Einführungsartikel wurde bereits erwähnt, dass die Grundlagen VirtualBox, Vagrant und Docker sind. Ziel dieses Artikels ist die Basiskonfiguration dieser 3 Komponenten, um die Folgenden Grundanforderungen erfüllen zu können:

  • Docker soll automatisiert installiert werden können
  • Docker Container sollen vom Host (PC / Laptop) aus erreichbar sein
  • Docker Container sollen statische IP Adressen zugewiesen bekommen können
  • Die statischen IP Adressen sollen nicht mit den automatischen von Docker zugewiesenen IP Adressen kollidieren


Vagrant

Mit Hilfe von Vagrant können wir in einer Datei – der Vagrantfile – beschreiben wie unsere virtuelle Maschine konfiguriert werden soll. Wir gehen hier nun auf die wichtigsten Bestandteile unserer Vagrantfile ein:

config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"

Wir nutzen Ubuntu 14.04 als Betriebssystem für unsere virtuelle Maschine, welches unter der angegebenen URL automatisch heruntergeladen und installiert wird.

config.vm.network "private_network", ip: "10.34.1.10", netmask: "255.255.0.0"

Die virtuelle Maschine bekommt die IP Adresse 10.34.1.10/16 zugewiesen. Diese IP Adresse ist wichtiger Bestandteil für die spätere Docker Konfiguration, da diese im selben Netz liegen muss!

config.vm.provider :virtualbox

VirtualBox wird als VM-Provider genutzt

vbox.customize ["modifyvm", :id, "--cpus", "2", "--memory", "2048"]

Hier wird die Anzahl der CPUs und die Größe des Hauptspeichers für die virtuelle Maschine gesetzt.

1.upto(8) do |nic|
vbox.customize ["modifyvm", :id, "--nicpromisc#{nic}", "allow-all"]
end

Mit diesem Befehl werden alle NICs auf promiscous mode „allow-all“ gesetzt. Standardmäßig nehmen die NICs nur Datenpakete für die virtuelle Maschine an, weil sie keine weiteren IP Adressen innerhalb der virtuellen Maschine kennen. Da die Docker Container eine andere MAC Adresse als die virtuelle Maschine haben, würden die NICs diese Datenpakete verwerfen. Somit wäre es nicht möglich Datenpakete zwischen Host (Laptop / PC) und den Docker Containern zu routen. Mit dem Parameter promiscous mode „allow-all“ werden jedoch sämtliche Frames anderer MAC Adressen akzeptiert, wodurch der Host später mit den Docker Containern kommunizieren kann.

config.vm.provision "docker", version: "1.4.0"

Vagrant bietet bereits einen eigenen Docker Provisioner an, der die Installation von Docker übernimmt. Es muss nur die Docker Version, in unserem Fall 1.4.0, angegeben werden.

config.vm.provision :shell, :path => "provisioning/run.sh"

Hier konfigurieren wir den Docker Daemon auf unsere Bedürfnisse. Wir werden im nächsten Abschnitt detailliert darauf eingehen.

config.vm.provision :unix_reboot

Nachdem die virtuelle Maschine vollständig konfiguriert wurde, muss diese nun nur noch neu gestartet werden. Hierfür benutzen wir das Folgende Vagrant Plugin.

Docker

Im provisioning Verzeichnis liegt das run.sh Skript, das von Vagrant beim Provisionieren der virtuellen Maschine ausgeführt wird. Das Skript ist dafür verantwortlich 2 Dateien an ihren richtigen Platz zu kopieren und Pipework in das /usr/local/sbin Verzeichnis herunterzuladen.

Docker Daemon mit zusätzlichen Optionen starten

Docker erlaubt es unter “/etc/default” eine Datei mit dem Namen „docker“ abzulegen, die zusätzliche Docker Parameter beinhaltet, welche beim Start von Docker berücksichtigt wird. In unserem Fall sieht die docker Datei wie folgt aus:

-bip=10.34.1.10/16

Mit diesem Parameter setzen wir die IP Adresse für die Docker Bridge auf 10.34.1.10/16. Die Docker Bridge liegt somit im selben Netz wie die virtuelle Maschine. Dies ist eine Grundvoraussetzung um später vom Host (PC / Laptop) aus mit den Docker Containern kommunizieren zu können.

--fixed-cidr=10.34.128.0/17"

Hiermit beschränken wir den IP Bereich des Docker Netzwerks und umgehen somit IP Kollisionen wenn Docker Container statische IP Adressen mit Hilfe von Pipework zugewiesen bekommen. Aus der Sicht von Docker bedeutet dies, dass IP Adressen im Bereich von 10.34.128.1 bis 10.34.255.255 vergeben werden können.

VirtualBox und Docker miteinander vereinen

Die rc.local Datei wird bei jedem Systemstart ausgeführt und stellt sicher, dass zum Einen die virtuelle Maschine in das Docker Netzwerk integriert und zum Anderen Pipework installiert wird.

/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
/sbin/iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

Mit diesen 3 Zeilen aktivieren wir NAT, damit die Docker Container mit der Außenwelt kommunizieren können, denn die IP Adressen der Container gelten nicht im Host Netz (PC / Laptop), da sie dort nicht gehostet werden.

ip addr del 10.34.1.10/16 dev eth1
ip link set eth1 master docker0

Hier löschen wir die IP Adresse an eth1 und stecken das Interface in die Dockerbridge wodurch der Host (PC / Laptop), die VM und die Docker Container miteinander verbunden werden.

Fazit

Mit der hier vorgestellten Basiskonfiguration haben wir nun Folgende Ziele erreicht:

1. Docker wird automatisiert installiert

Dies wurde mit Hilfe des Docker Provisioner erzielt.

2. Docker Container sind vom Host (PC / Laptop) aus erreichbar

Dies können wir mit einem einfachen Test beweisen. Hierfür müssen wir uns in die virtuelle Maschine einloggen und einen Docker Container starten:

docker run -it stackbrew/ubuntu /bin/bash

Wenn der Docker Container gestartet wurde kann mit Hilfe von ifconfig die IP Adresse von eth0 herausgefunden werden. Diese IP Adresse solltet ihr nun von eurem Host (PC / Laptop) aus mit einem einfachen Ping Befehl erreichen können. Falls dies der erste Docker Container war den ihr gestartet habt, sollte die IP Adresse: 10.34.128.1 lauten.

3. Docker Container können statische IP Adressen zugewiesen bekommen

Die Grundlage hierfür haben wir mit der Installation von Pipework geschaffen. Um nun beispielsweise unserem vorher gestarteten Docker Container eine von uns definierte IP Adresse zuzuweisen muss Folgender Befehl ausgeführt werden:

sudo pipework docker0 <container-id> 10.34.10.11/16

Mit diesem Befehl würde unser Docker Container nun auch unter der IP Adresse 10.34.10.11 erreichbar sein.

4. Die statischen IP Adressen sollen nicht mit den automatischen von Docker zugewiesenen IP Adressen kollidieren

Da wir das Docker Netzwerk auf 10.34.128.0/17 beschränkt haben, können wir IP Adressen von 10.34.0.1 bis 10.34.127.255 an die Docker Container vergeben, ohne dass wir Konflikte mit den von Docker automatisch vergebenen IP Adressen bekommen.

Ausblick

Wir haben nun die Grundkonfiguration für RED fertig gestellt. Der nächste Artikel wird sich dann mit den Automatismen für das Bauen, Starten und Stoppen von unseren eigenen Docker Images/Containern beschäftigen. Also bleibt dran und meldet Euch bei uns, falls Ihr Fragen oder Anregungen habt.

Alexander Berresch

Alexander Berresch ist Software Engineer für CenterDevice

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

  • Victor Volle

    29. Dezember 2014 von Victor Volle

    Hallo Andreas!

    Ich verstehe noch zu wenig vom Networking: hätte Euch auch ein einfaches Port Forwarding vom Host (Laptop) zur VM und dann zu den jeweilige Docker Containern gereicht? Die Docker-Container können ja beliebige Ports nach außen (also zunächst zur VM) durchreichen (EXPOSE) und Vagrant bietet Port Forwarding. In https://blog.codecentric.de/en/2014/01/docker-networking-made-simple-3-ways-connect-lxc-containers/ beschreibt Ihr beide Varianten, aber der entscheidende Unterschied scheint mir zu sein, dass die Docker-Container mit Pipework im Host-Network direkt integriert sind. Braucht Ihr das?

    Victor

Kommentieren

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