Docker Swarm через VPN: задачи работают, вызовы служб не проходят
Задачи работают в обеих площадках, а вызовы между службами завершаются по тайм-ауту. Overlay нужны маршруты между узлами, непереведённые адреса и место для 50 байт VXLAN.
Три менеджера и пять рабочих в двух площадках, соединённых туннелем, и docker service ls показывает задачи, работающие с обеих сторон, тогда как вызовы между службами завершаются по тайм-ауту. В журналах Swarm ничего не выглядит неправильным. Это сочетание — подпись проблемы плоскости данных: плоскость управления нашла узлы, а инкапсулированные кадры так и не проделали путь.
Сеть должна существовать раньше overlay
Overlay Swarm толкает инкапсулированные кадры напрямую между адресами узлов, то есть каждому узлу нужен адрес, до которого каждый другой узел доходит без трансляции, на интерфейсе, который предоставляет туннель. Туннель, который везёт только клиентов к опубликованному порту, недостаточен. Нижний уровень должен маршрутизировать от узла к узлу в обе стороны.
Проверьте это до того, как трогать Swarm. С каждого узла проверьте маршрут до туннельного адреса партнёра, пропингуйте его и затем проверьте порт управления. Если ping работает, а порт нет, туннель в порядке и на пути стоит фильтр.
ip -brief address
ip route get 10.20.0.12
ping -c3 10.20.0.12
nc -vz 10.20.0.12 2377
Если маршрут указывает на физический интерфейс вместо tun0 или wg0, overlay инкапсулирует на адрес, до которого удалённая площадка не дотянется, и симптом будет выглядеть как потеря пакетов.
Проверьте, какой адрес объявляет каждый узел
Демон объявляет один адрес, и партнёры используют его для плоскости данных. На хосте с несколькими сетями легко объявить адрес LAN или публичный, пока туннель несёт что-то другое. Проверьте его, а не предполагайте, и закрепите при вступлении через --advertise-addr, если значение по умолчанию неверно. Узел, объявляющий адрес, доступный только ему, всё равно вступает в swarm, и отказ позже проявляется как службы, которые не могут общаться между площадками.
Изменение объявленного адреса позже — не правка конфигурации, потому что узел должен выйти и вступить заново.
Запишите объявленный адрес для каждого узла в заметки, потому что это объясняет большинство асимметричных отказов.
Masquerade — обычный виновник
Когда шлюз стоит между узлами и туннелем, частая ошибка — применять masquerade ко всему, что выходит из физического интерфейса. Это переписывает и внутренние адреса overlay, поэтому каждый партнёр выглядит приходящим от шлюза, и партнёры VXLAN перестают узнавать друг друга. Результат — пропавший или односторонний инкапсулированный трафик, тогда как обычные ping ещё работают.
Маршрутизируйте префикс overlay через шлюз и оставьте его без трансляции. Если трансляция действительно нужна для другого префикса, ограничьте её им и никогда — диапазоном, который использует overlay.
ip route add 172.16.0.0/22 via 10.20.0.1
iptables -t nat -I POSTROUTING -o tun0 -s 172.16.0.0/22 -j ACCEPT
Проверьте порядок правил, а также их текст, потому что широкое MASQUERADE раньше в цепочке побеждает узкое исключение позже.
VXLAN нужен запас в пакете
VXLAN добавляет 50 байт к переносимым кадрам. Нижний уровень в 1500 байт, несущий внутренний кадр в 1500 байт, порождает инкапсулированный пакет, который ни один путь не доставит, и отказ выглядит как прерывистое обнаружение служб, а не как проблема размера. Либо снизьте MTU туннеля на обоих концах, либо задайте MTU overlay так, чтобы драйвер объявлял помещающуюся полезную нагрузку.
docker network create --driver overlay --attachable --opt com.docker.network.driver.mtu=1400 swarm-overlay
Сеть ingress создаётся автоматически, поэтому её изменение означает удаление и повторное создание, а не правку на месте.
Если исправить только одну сторону туннеля, меньший MTU всё равно остаётся тем, что имеет значение.
Следите за плоскостью данных, а не за журналами
Захватите порт VXLAN на обоих концах. Кадры, уходящие с одной стороны и приходящие на другую, означают, что нижний уровень в порядке, а проблема внутри overlay. Кадры, уходящие и никогда не приходящие, означают маршрут или фильтр. Кадры, которые вообще не уходят, означают, что адрес источника неверен.
Отказы обнаружения служб, исчезающие через несколько секунд, обычно указывают на бюджет пакетов или нестабильный путь, а не на кворум raft.
Сохраните захват из работающего окна, потому что сравнить его со сломанным быстрее, чем перечитывать конфигурацию.