Nutzung des BTRFS Storage Drivers
Das BTRFS Dateisystem unterstützt blockweise Operationen und Copy-on-Write Snapshots und ist damit eine natürliche Wahl für Docker. Ich folge im Wesentlichen dem offiziellen Guide und beschreibe daher nur die relevanten Schritte.
Da der Server BTRFS als Root-Dateisystem benutzt und ich für Docker auch keine eigene Partition anlegen möchte, kann das im Guide beschriebene Vorgeplänkel mit der Vorbereitung einer solchen Partition entfallen. Es geht direkt mit der Anpassung der Konfiguration des Docker Daemons los. Die Konfiguration befindet sich in der Datei /etc/docker/daemon.json. Zur Festlegung des Storage Drivers auf BTRFS muss die Datei um einen Eintrag für storage-driver erweitert werden:
{ "storage-driver" : "btrfs" }
Danach ist der Docker Daemon neu zu starten:
$ systemctl restart docker
Docker sollte BTRFS als Storage Driver melden, wenn man die allgemeinen Informationen abfragt:
$ docker info ... Storage Driver: btrfs Build Version: Btrfs v4.4 Library Version: 101 ...
Aktivierung von IPv6
Standardmäßig läuft Docker nur mit IPv4, IPv6 muss nachträglich aktiviert werden. Dazu sucht man sich innerhalb des Prefixes, das dem Server zugeteilt ist, ein kleineres Prefix aus, aus dem Docker sich bedienen kann, wenn es IPv6 Adressen für die Container allokiert. Die Größe des Prefixes sollte mindestens /80 sein, um Docker die Generierung von IPv6 Adressen aus Prefix und der (virtuellen) MAC-Adresse des Containers zu ermöglichen. Das ist wichtig, um Problemen mit dem Neighbor Cache in Docker aus dem Wege zu gehen.
Nehmen wir an, der Server hat das Prefix 2001:xxxx:xxxx:xxxx::/64 zugeteilt bekommen, dann wäre 2001:xxxx:xxxx:xxxx:d000::/80 eine mögliche Wahl. In der Konfiguration des Docker Daemons (/etc/docker/daemon.json) erfolgt die Einstellung:
{ "ipv6" : true, "fixed-cidr-v6" : "2001:xxxx:xxxx:xxxx:d000::/80", "storage-driver" : "btrfs" }
Docker aktiviert automatisch Forwarding (sofern noch nicht aktiviert) und fügt eine Route für dieses Subnetz hinzu. Manche Hosts beziehen ihre IPv6-Netzwerkeinstellungen über Router Advertisements. Die Aktivierung von Forwarding führt in diesen Fällen zum Verwerfen der Router Advertisements und damit den Verlust der Konnektivität, wenn das Netzwerkinterface seine Konfiguration über Router Advertisements bezieht. Man kann den Kernel anweisen, auch bei aktiviertem Forwarding Router Advertisements zu akzeptieren, indem man in /etc/sysctl.conf folgende Einstellung setzt/hinzufügt:
net.ipv6.conf.ens3.accept_ra = 2
Bei Netcup ist das nicht nötig, da die IPv6 Konfiguration statisch erfolgt. Wie ich leider feststellen musste, gibt es eher Probleme mit dieser Einstellung, wenn ein Router Advertisement die Netzwerkkonfiguration verstellt. Unter anderem musste ich schmerzlich den Verlust der Default-Route mit entsprechenden Konsequenzen beklagen…
Hat man die Konfiguration geändert, muss man noch die geänderte /etc/sysctl.conf neu laden:
$ sysctl -p /etc/sysctl.conf
Da Container sich mit ihren virtuellen Netzwerkinterfaces am docker0 Bridgedevice befinden, können sie nicht auf Neighbor Solicitation Requests vom ISP reagieren und daher auch keine Neighbor Advertisements senden. Der ISP nimmt damit an, dass angefragte Adressen, die sich in besagtem Subnetz befinden, vom Server nicht genutzt werden. Es werden in Folge dessen auch keine Paket für entsprechende IPv6 Adressen zum Server geroutet. Abhilfe schafft der Neighbor Discovery Protocol Proxy Daemon (ndppd). Er beantwortet Neighbor Solicitations mit entsprechenden Neighbor Advertisements gemäß seiner Konfiguration. Der ndppd lässt sich wie folgt installieren:
$ apt-get install ndppd
Unter /etc/ndppd.conf erwartet er standardmäßig seine Konfiguration. Die Konfiguration ist denkbar einfach, da ndppd mit sinnvollen Defaulteinstellungen arbeitet, und benötigt nur eine Regel, die ndppd anweist, für Dockers Default-Netzwerk Neighbor Solicitations zu beantworten:
proxy ens3 { rule 2001:xxxx:xxxx:xxxx:d000::/80 { auto } }
Der Parameter auto in der Regel bewirkt, dass ndppd in die aktuelle Routingtabelle schaut, um herauszufinden, an welches Device es die Neighbor Solicitations weiterleiten muss, um zu prüfen, ob es ein Interface gibt, das auf die betreffende IPv6 Adresse hört. Dabei wird zwar immer das docker0 Device herauskommen, es ist aber flexibler so als wenn man das Device selbst in der Konfiguration festlegt. Später wird es weitere IPv6 Prefixes geben, die von ndppd bedient werden müssen und da ist der Name des Devices nicht mehr fix.
Um ndppd beim Systemstart mit hochzufahren muss es noch aktiviert werden:
$ systemctl enable ndppd
Um ndppd in Betrieb zu nehmen und zu prüfen, ob es erfolgreich gestartet wird noch folgendes:
$ systemctl start ndppd $ systemctl status ndppd ● ndppd.service - LSB: NDP Proxy Daemon Loaded: loaded (/etc/init.d/ndppd; bad; vendor preset: enabled) Active: active (running) since Mon 2018-02-05 17:25:48 CET; 2s ago Docs: man:systemd-sysv-generator(8) Process: 2494 ExecStop=/etc/init.d/ndppd stop (code=exited, status=0/SUCCESS) Process: 2505 ExecStart=/etc/init.d/ndppd start (code=exited, status=0/SUCCESS) Tasks: 1 Memory: 452.0K CPU: 20ms CGroup: /system.slice/ndppd.service └─2513 /usr/sbin/ndppd -d -p /var/run/ndppd.pid Feb 05 17:25:48 v22018025410360775 systemd[1]: Starting LSB: NDP Proxy Daemon... Feb 05 17:25:48 v22018025410360775 ndppd[2505]: (notice) ndppd (NDP Proxy Daemon) version 0.2.4 Feb 05 17:25:48 v22018025410360775 ndppd[2505]: (notice) Using configuration file '/etc/ndppd.conf' Feb 05 17:25:48 v22018025410360775 systemd[1]: Started LSB: NDP Proxy Daemon.
Um die Funktionsfähigkeit zu prüfen kann man www.google.de anpingen:
$ docker run -it \ ubuntu:16.04 \ /bin/bash -c "apt-get -y update && apt-get -y install iputils-ping && ping6 www.google.de"