Ваш контейнер досі відповідає на своєму керівному мосту, але кожен вихідний пакет виходить через офісний macvlan. Нічого не зламалося. Два підключення дають по одному шлюзу, і єдиний маршрут за замовчуванням пішов до мережі, яку ви не мали на увазі, тож служба продовжує працювати, а її трафік іде довшим шляхом. Коли хтось це помітить, доказом буде таблиця маршрутизації, а не повідомлення про помилку.

Звичне пояснення — Docker вибрав мережу випадково. На практиці старе рішення йшло за абетковим порядком назв підключених мереж, що перетворювало маршрутизацію на побічний ефект мітки. gw_priority замінює це числом, яке ви обираєте навмисно, і перехід займає близько хвилини після того, як схему записано.

Чому маршрут за замовчуванням потрапляє в неправильну мережу

Кожна мережа, до якої приєднується служба, може запропонувати власний шлюз, а контейнер усе одно отримує рівно один маршрут за замовчуванням. До Compose 2.33.1 нічию вирішували сортуванням назв мереж, тож мітка на кшталт control, що йде перед office, визначала, куди піде трафік. Ніщо всередині контейнера не фіксує, що рішення було довільним, і саме тому воно проходить рев'ю коду й пізніше виринає як дивний шлях. Записати політику у файл compose — єдиний спосіб зробити вибір перевірюваним.

Яка мережа переможе, справді змінюють дві речі: значення gw_priority, які ви призначаєте, і те, які мережі взагалі підключені. Додайте третю мережу — набір кандидатів зросте; приберіть macvlan — і з мостом більше нічому змагатися. Жоден із кроків не видно в журналах застосунку, бо неправильний маршрут за замовчуванням рідко повністю розриває з'єднання. Він лише змушує відповіді приходити з адреси, якої інша сторона може не чекати.

Закріпіть шлюз через gw_priority

Compose показує gw_priority на кожному підключенні служби до мережі від версії 2.33.1, і перемагає найбільше число. Окремого ключа шлюзу для служби немає, тому значення належить блоку networks цієї служби. Приклад нижче віддає маршрут за замовчуванням control, залишаючи office доступною для її прямо підключеної LAN.

services:
  vpn:
    networks:
      control:
        gw_priority: 1
      office:
        gw_priority: 0

networks:
  control:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.50.0/24
  office:
    driver: macvlan
    driver_opts:
      parent: eno1.120
      macvlan_mode: bridge
    ipam:
      config:
        - subnet: 192.168.120.0/24
          ip_range: 192.168.120.192/27
          gateway: 192.168.120.1

Читайте блок як два окремі керування: gw_priority вирішує маршрут за замовчуванням, а розділ ipam — адресацію. Зміна лише subnet залишає вибір виходу недоторканим, і це найпоширеніший спосіб застосувати це виправлення наполовину. Тримайте пріоритети поруч із мережею, якою вони керують, щоб наступний читач не мусив шукати рішення.

Не плутайте gw_priority зі звичайною властивістю priority поруч. Вона впорядковує створення з'єднань і нічого не каже про маршрутизацію, тому не може вибрати шлюз за замовчуванням і не виправляє назви інтерфейсів. Якщо хтось радить підняти priority, щоб спрямувати трафік, порада хибна, навіть коли отриманий порядок випадково виглядає правильно.

Перевірте, яка мережа насправді несе маршрут за замовчуванням

Перевіряйте всередині працюючого контейнера, бо таблиця маршрутизації хоста описує хост, а не простір імен, який використовує служба. Спершу запустіть перевірку конфігурації, щоб друкарська помилка виявилася до перезапуску, а тоді прочитайте маршрут, який контейнер справді встановив.

docker compose config --quiet
docker exec vpn ip -4 route show default
docker exec vpn cat /proc/net/route

Правильний результат називає пристрій мосту та 172.30.50.1; неправильний називає 192.168.120.1 і пристрій macvlan. Якщо образ не містить пакета iproute2, файл /proc усе одно повідомляє маршрут за замовчуванням, із призначенням 00000000 і байтами шлюзу в зворотному порядку. Порівняйте стовпець інтерфейсу з docker inspect, коли назви пристроїв незрозумілі.

Macvlan — це фізичний порт, а не клон мосту

Macvlan дає контейнеру другу ідентичність у кабелі, і саме це робить працездатним доступ до локальних пристроїв. Це також означає, що порт комутатора й гіпервізор мають прийняти додаткову MAC-адресу, і багато хмарних мереж мовчки відмовляють у цьому. Перевірте один контейнер, перш ніж планувати флот, бо відхилена MAC зазвичай виглядає як зв'язок, який піднято і який нічого не пропускає.

Налаштування macvlan_mode: bridge — це режим драйвера macvlan, а не програмний міст Docker, а passthru — окремий спеціалізований режим, а не типове значення. Linux також не дає контейнеру macvlan дістатися до власного хоста через той самий батьківський інтерфейс, і саме тому керівний міст зберігають, а не сподіваються, що одне підключення виконає обидві задачі.

Назвіть батьківський інтерфейс VLAN до того, як Compose його побачить

Docker трактує батьківський інтерфейс із точкою, як eno1.120, як субоінтерфейс 802.1Q і сам створює пристрій VLAN. Ця зручність має межі: похідне ім'я залежить від імені фізичного інтерфейсу, а довгі імена можуть вивести результат за межі очікувань інструментів навколо. Створення іменованого інтерфейсу VLAN у мережевій конфігурації хоста й спрямування parent на нього робить обидва кінці передбачуваними.

Пам'ятайте, що ключ під networks — це ім'я Compose, а не пристрій Linux. Пошук на хості інтерфейсу з назвою office не вдасться, бо ядро бачить лише батьківський інтерфейс і пару veth за контейнером.

Звільніть місце для VPN зверху

Клієнт VPN підключається після того, як ці мережі існують, тож може додати конкретніші маршрути, правила політики й фільтри незалежно від gw_priority. Плануйте віддалені префікси щодо обох локальних підмереж, включно з відповідями, потрібними керівному шляху. Коли віддалений префікс перекриває офісну LAN, виправте план адрес, а не виривайте цілий приватний діапазон із тунелю.

Перевірте ще раз адреси, маршрути й шлях служби після запуску VPN і ще раз після його повторного підключення, бо саме під час повторного підключення зникає маршрут, доданий вручну. Запишіть очікувану таблицю до першого тесту, щоб подальше порівняння було diff, а не вправою на пам'ять. Тримайте постійне володіння мережею в Compose, а конфігурація VPN нехай володіє лише власною політикою.

Схожі статті