Территориальный конфликт: война за 172.19.0.0/16
— Когда контейнер ищет внешний сервер у себя под носом —
TL;DR
Кто‑то скажет — сделал из мухи слона! Да у меня каждый день такие приключения! Но для меня получился интересный кейс, и я лучше зафиксирую его для потомков.
Случилось страшное – из
WTF?!
Диагностика. Раунд первый
Для начала проверяем подсети, которые создал
В моём случае обнаружились:
В целом, картина уже ясна – видим пересечение сетей
Для пущей убедительности проверяем маршрут в сетевом пространстве
Бинго!
Cреда
Первое лечение. Неудачное
Перенёс сеть
Тут надо сказать, что
Остановил использующие сеть проекты, удалил старые сети, поднял сети заново.
И… внешний сервер снова недоступен.
WTF?!
Диагностика. Раунд второй
Смотрим подсети ещё раз:
Постоянству
Лечение. Теперь окончательное
После повторного конфликта стало понятно: доверять
И поэтому сети создаём с явным указанием подсетей:
Проверяем итоговую адресацию:
Получаем:
Проверяем доступность внешнего сервера:
И вот теперь всё заработало как надо!
Для кого-то это база, а для меня кирпичик опыта!
Полезное открытие: nicolaka/netshoot
У минималистичных
Но самое интересное — возможность подключиться к сетевому пространству уже работающего контейнера:
Теперь мы находимся в отдельном диагностическом контейнере, но используем сетевые интерфейсы, IP-адреса и маршруты
При этом исходный контейнер не пересобирается, а после выхода диагностический контейнер автоматически удалится благодаря
Отличная DevOps-выручалочка. Крайне рекомендую.
#docker #dockercompose #networking #devops
— Когда контейнер ищет внешний сервер у себя под носом —
TL;DR
Разбираемся, куда пропадают пакеты, при чём тут маршрутизация и как закончить войну за IP-адреса.
Кто‑то скажет — сделал из мухи слона! Да у меня каждый день такие приключения! Но для меня получился интересный кейс, и я лучше зафиксирую его для потомков.
Случилось страшное – из
docker-контейнера недоступен удалённый хост. При этом с хост-машины никаких проблем с доступность нет – что надо пингуется, что пингуется, то роутится. Хост для определённости - 172.19.10.50.WTF?!
Диагностика. Раунд первый
Для начала проверяем подсети, которые создал
docker:
docker network inspect $(docker network ls -q) \
--format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}} {{end}}'
В моём случае обнаружились:
bridge: 172.17.0.0/16
traefik: 172.19.0.0/16
app-backend: 172.23.0.0/16
app-notifications: 172.29.0.0/16
В целом, картина уже ясна – видим пересечение сетей
docker и внешнего хоста. Для пущей убедительности проверяем маршрут в сетевом пространстве
docker:
docker run --rm --network host \
nicolaka/netshoot \
ip route get 172.19.10.50
Бинго!
172.19.10.50 dev br-caf585119744 src 172.19.0.1
Cреда
docker считает, что внешний сервер находится непосредственно в локальной сети.Первое лечение. Неудачное
Перенёс сеть
traefik в другой диапазон – 10.250.10.0/24, предварительно убедившись, что подсеть не используется где-то ещё.
networks:
traefik:
name: traefik
driver: bridge
ipam:
config:
- subnet: 10.250.10.0/24
Тут надо сказать, что
app-backend и app-notifications используют общие external-сети. Поэтому сети создавались отдельно, а не средствами docker compose.
docker network create app-backend
docker network create app-notifications
Остановил использующие сеть проекты, удалил старые сети, поднял сети заново.
И… внешний сервер снова недоступен.
WTF?!
Диагностика. Раунд второй
Смотрим подсети ещё раз:
traefik: 10.250.10.0/24
app-backend: 172.18.0.0/16
app-notifications: 172.19.0.0/16
Постоянству
docker можно позавидовать – не отпускает подсеть 172.19.0.0/16.Лечение. Теперь окончательное
После повторного конфликта стало понятно: доверять
docker автоматическое распределение адресов конкретно в этом окружении — идея так себе. И поэтому сети создаём с явным указанием подсетей:
docker network create \
--driver bridge \
--subnet 10.250.11.0/24 \
app-backend
docker network create \
--driver bridge \
--subnet 10.250.12.0/24 \
app-notifications
Проверяем итоговую адресацию:
docker network inspect traefik app-backend app-notifications \
--format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}'
Получаем:
traefik: 10.250.10.0/24
app-backend: 10.250.11.0/24
app-notifications: 10.250.12.0/24
Проверяем доступность внешнего сервера:
docker run --rm \
--network container:notifications-php \
nicolaka/netshoot \
ping -c 3 172.19.10.50
И вот теперь всё заработало как надо!
Для кого-то это база, а для меня кирпичик опыта!
Полезное открытие: nicolaka/netshoot
У минималистичных
docker-образов, таких как alpine, debian:slim часто отсутствуют даже базовые сетевые утилиты: ping, curl, nslookup, ip. Когда возникает необходимость разобраться с сетевыми проблемами, то удобнее использовать образ nicolaka/netshoot с целым арсеналом сетевых инструментов.Но самое интересное — возможность подключиться к сетевому пространству уже работающего контейнера:
docker run --rm -it \
--network container:notifications-php \
nicolaka/netshoot
Теперь мы находимся в отдельном диагностическом контейнере, но используем сетевые интерфейсы, IP-адреса и маршруты
notifications-php.При этом исходный контейнер не пересобирается, а после выхода диагностический контейнер автоматически удалится благодаря
--rm.Отличная DevOps-выручалочка. Крайне рекомендую.
#docker #dockercompose #networking #devops
Просмотры: 6