MTU-Mismatch in Docker und OpenStack: CI/CD-Pipelines retten
Ein Build-Fehler am Freitagabend ist selten Zufall – meist steckt ein MTU-Mismatch zwischen Docker-Containern und dem Overlay-Netzwerk von OpenStack dahinter. Das Problem taucht nur bei großen Datenübertragungen auf, wie beim Klonen eines Repos, während kleine Anfragen problemlos durchlaufen. So entsteht der trügerische Eindruck eines funktionierenden Netzwerks, bis echte Workloads kommen.
Warum kleine Anfragen klappen, große aber scheitern
Das Kennzeichen dieses Problems ist seine Selektivität. Befehle wie curl -I oder ping, die winzige Pakete senden, funktionieren immer. Probleme beginnen bei Operationen mit großen Datenmengen: git clone, docker pull, Artefakt-Downloads. Der Übeltäter? Die Maximum Transmission Unit (MTU) – die größte IP-Paketgröße, die ohne Fragmentierung übertragen werden kann.
Standard-Ethernet-Netzwerke nutzen eine MTU von 1500 Bytes. In Cloud-Umgebungen wie OpenStack erzeugen Overlay-Technologien wie VXLAN oder GRE isolierte Netzwerke, indem sie jedes Paket um ca. 50 Bytes Overhead verpacken. Selbst wenn das physische Netzwerk 1500 Bytes schafft, bleiben für VM-Pakete nur 1450 Bytes übrig.
Docker setzt standardmäßig auf ein Bridge-Netzwerk mit MTU 1500 und ignoriert Infrastruktur-Eigenheiten. Container bauen Pakete nach dieser Spezifikation. Am Host-Interface mit 1450 MTU können sie wegen des DF (Don't Fragment)-Flags nicht übertragen werden. Path MTU Discovery sollte eigentlich greifen, aber Firewalls, Security Groups oder fehlerhafte Router blockieren oft die ICMP-Nachrichten „Fragmentation Needed“.
Problem in 30 Sekunden diagnostizieren
Ein MTU-Mismatch erkennen Sie mit diesen drei Befehlen:
- MTU des Host-Netzwerk-Interfaces prüfen:
```
ip link show ens3 | grep mtu
```
In OpenStack erwarten Sie mtu 1450.
- MTU in einem Container prüfen:
```
docker run --rm alpine ip link show eth0 | grep mtu
```
Docker verwendet standardmäßig mtu 1500. Höher als beim Host? Problem gefunden.
- Ping-Test ohne Fragmentierung durchführen:
```
docker run --rm alpine ping -s 1422 -M do -c 3 gitlab.example.com
docker run --rm alpine ping -s 1423 -M do -c 3 gitlab.example.com
```
Der erste (1422 = 1450 − 28) sollte gelingen; der zweite mit „Message too long“ scheitern.
Schritt-für-Schritt-Behebung
MTU in Docker setzen
Die Kernlösung: Docker auf die richtige MTU einstellen. /etc/docker/daemon.json bearbeiten:
{
"mtu": 1450
}
Docker-Daemon neu starten:
sudo systemctl restart docker
Bestehende Netzwerke handhaben
Hinweis: Änderungen in daemon.json wirken nur bei neuen Netzwerken. Bestehende – besonders aus Docker Compose – behalten die alte MTU. Zwei Optionen:
- Alles neu erstellen:
```
docker compose down && docker compose up -d
```
- MTU explizit in Docker Compose setzen:
```yaml
networks:
app-net:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1450
```
Abschließende Schritte
GitLab Runner neu starten und testen:
sudo gitlab-runner restart
docker run --rm alpine ping -s 1422 -M do -c 3 gitlab.example.com
Test erfolgreich? Alles klar.
Häufige Fallen und Best Practices
- MTU nicht vorsorglich unterschießen. Auf 1300 runtergehen bedeutet 10–15 % weniger Durchsatz durch Extra-Pakete. Genauen diagnostizierten Wert nutzen.
- Automatisieren. MTU in Infra-Konfig (Terraform, Ansible, cloud-init) einbauen – keine manuellen Anpassungen.
- Custom-Netzwerke beachten.
daemon.jsonüberspringt Bestehende. Mitdocker network inspectprüfen. - Path MTU Discovery nicht hoffen. Cloud-Umgebungen killen es durch ICMP-Blocks.
Wichtige Erkenntnisse
- MTU-Mismatch schlägt nur bei großen Transfers zu – schwer zu entdecken.
- OpenStack-Overlays fressen 50 Bytes MTU durch Header.
- Dockers Standard-1500 kollidiert in Clouds.
- Lösung: Docker-MTU an Host-Interface anpassen.
- Setup in Deployment-Pipeline automatisieren.
— Editorial Team
Noch keine Kommentare.