Jak nesoulad MTU v Dockeru a OpenStacku narušuje CI/CD: diagnostika a oprava
Selhání sestavení v pátek večer často není náhodnou chybou, ale důsledkem rozdílu v MTU mezi kontejnery Dockeru a overlay sítí OpenStack. Problém se projevuje pouze při přenosu velkých objemů dat, například při klonování repozitáře, zatímco malé požadavky procházejí bez chyb. To vytváří iluzi funkčnosti sítě, dokud nezačne skutečná práce.
Proč malé požadavky fungují a velké ne
Klíčová vlastnost tohoto problému je jeho selektivita. Příkazy jako curl -I nebo ping, které generují malé pakety, jsou úspěšně provedeny. Problém nastává při operacích vyžadujících přenos velkých datových segmentů: git clone, docker pull, nahrávání artefaktů. Příčina spočívá v Maximum Transmission Unit – maximální velikosti IP paketu, který může být přenesen bez fragmentace.
Ve standardní Ethernet síti je MTU 1500 bajtů. Avšak v cloudových prostředích, jako je OpenStack, pro vytvoření izolovaných sítí se používají overlay technologie VXLAN nebo GRE. Přidávají ke každému paketu služební obálku o velikosti přibližně 50 bajtů. Výsledkem je, že ačkoli fyzická síť podporuje MTU 1500, pro pakety virtuálního stroje zbývá pouze 1450 bajtů.
Docker ve výchozím nastavení vytváří bridge síť s MTU 1500, neberouc v úvahu specifika infrastruktury. Kontejner vytváří pakety na základě této hodnoty. Když takový paket dosáhne síťového rozhraní hostitele s MTU 1450, nemůže být přenesen kvůli nastavenému příznaku DF (Don't Fragment). V ideálním případě by fungoval mechanismus Path MTU Discovery, ale v praxi jsou ICMP zprávy "Fragmentation Needed" blokovány firewally, security groups nebo nesprávně zpracovávány směrovači.
Diagnostika problému za 30 sekund
Určit nesoulad MTU lze pomocí tří příkazů:
- Zkontrolujte MTU síťového rozhraní hostitele:
```
ip link show ens3 | grep mtu
```
Očekávaný výsledek v OpenStack: mtu 1450.
- Zkontrolujte MTU uvnitř kontejneru:
```
docker run --rm alpine ip link show eth0 | grep mtu
```
Docker ve výchozím nastavení ukáže mtu 1500. Pokud je tato hodnota větší než na hostiteli, problém je odhalen.
- Proveďte kontrolní test s ping, zakazujícím fragmentaci:
```
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
```
První příkaz (1422 = 1450 − 28) by měl být úspěšně proveden, druhý – vrátit chybu Message too long.
Postupné řešení problému
Nastavení MTU v Dockeru
Hlavní oprava spočívá v nastavení Dockeru na použití správného MTU. Pro to upravte soubor /etc/docker/daemon.json:
{
"mtu": 1450
}
Po změně konfigurace restartujte Docker démon:
sudo systemctl restart docker
Práce s existujícími sítěmi
Je důležité pochopit, že změna daemon.json ovlivní pouze nově vytvořené sítě. Existující sítě, zejména vytvořené přes Docker Compose, si zachovají staré MTU. Řešení jsou dvě:
- Znovu vytvořit všechny sítě a kontejnery:
```
docker compose down && docker compose up -d
```
- Explicitně určit MTU v konfiguraci Docker Compose:
```yaml
networks:
app-net:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1450
```
Závěrečné kroky
Po nastavení MTU restartujte GitLab Runner a proveďte kontrolní test:
sudo gitlab-runner restart
docker run --rm alpine ping -s 1422 -M do -c 3 gitlab.example.com
Pokud test projde bez chyb, problém je vyřešen.
Běžné chyby a osvědčené postupy
- Nenastavujte MTU "s rezervou". Snížení MTU na 1300 "pro jistotu" sníží propustnost o 10-15% kvůli zvýšení počtu paketů. Použijte skutečnou hodnotu získanou při diagnostice.
- Automatizujte nastavení. Parametr MTU by měl být součástí konfigurace infrastruktury (Terraform, Ansible, cloud-init), nikoli ruční úpravou.
- Pamatujte na vlastní sítě.
daemon.jsonneaktualizuje MTU již vytvořených sítí. Použijtedocker network inspectpro kontrolu. - Nespolehejte na Path MTU Discovery. V cloudových prostředích tento mechanismus často nefunguje kvůli blokování ICMP.
Co je důležité
- Problém MTU mismatch se projevuje pouze při přenosu velkých objemů dat, což komplikuje diagnostiku.
- Overlay sítě v OpenStack snižují dostupné MTU o 50 bajtů kvůli služebním hlavičkám.
- Docker ve výchozím nastavení používá MTU 1500, což vede ke konfliktu v cloudových prostředích.
- Hlavní řešení – explicitní nastavení MTU v Dockeru, které odpovídá MTU síťového rozhraní hostitele.
- Nastavení by mělo být automatizováno a zahrnuto do procesu nasazení infrastruktury.
— Editorial Team
Zatím žádné komentáře.