Ви розгортаєте Pod з іменем vpn-gateway, спрямовуєте тестовий клієнт на його адресу й бачите, як пакети зникають. У маніфесті все правильно, і kubelet не має до чого причепитися. Причина структурна, а не конфігураційна: Kubernetes дає кожному Pod власний мережевий простір імен, тому ім’я, мітка чи спільний простір імен API нічого не змінюють у тому, куди йдуть пакети. Тому рішення про те, як трафік VPN залишає кластер, починається з питання про власність, а не про образи контейнерів.

Два механізми покривають більшість реальних розгортань, і вони не взаємозамінні. Один поміщає тунель у власний мережевий простір імен робочого навантаження. Другий просить CNI спрямувати вибраний трафік через призначений вузол шлюзу. Вони відмовляють по-різному, масштабуються по-різному й підкоряються різним командам, тому питання про контейнери зазвичай породжує суперечки, які ніколи не завершуються.

Межа Pod — це простір імен, а не хост переходу

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

Тому шаблон Pod-шлюзу працює лише тоді, коли щось вище за потоком справді надсилає йому пакети: Service, статичний маршрут на вузлі або політика спрямування в CNI. Сама адреса нічого не притягує.

Що дає тунель на кожен Pod і скільки він коштує

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

Налаштування, якому потрібен лише стан ядра, може завершитися в init-контейнері й вийти. Демону в просторі користувача, який має жити весь час існування Pod, потрібна перезапускувана форма init-контейнера, запроваджена як нативний сайдкар у Kubernetes 1.29, і ця відмінність походить від реалізації тунелю, а не від смаку. Ціна цієї моделі — дублювання: кожна репліка автентифікується, отримує власну адресу тунелю й займає місце віддаленого сеансу, тож подія автомасштабування стає подією ємності на іншому кінці каналу. Копіювання одного облікового запису в усі репліки не прибирає цю ціну, воно прибирає слід аудиту. Права заслуговують такої ж перевірки, адже тунелю, якому потрібен NET_ADMIN у власному просторі імен, немає причини успадковувати повноваження всього хоста з прикладу з privileged: true.

Коли виходом володіє CNI

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

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

Тримайте твердження вузьким. Шлюз виходу вибирає й транслює шлях. Він не завершує VPN і не робить кластер клієнтом вашої віддаленої мережі без підтримуваного з’єднання за ним.

QuestionPer-Pod tunnelCNI egress gateway
Who holds the client identityEach workloadThe gateway, shared
What scaling changesEnrollment and sessions per replicaThroughput and capacity per node
What the remote side seesDistinct addressesOne translated source
Failure scopeOne DeploymentEvery workload behind the gateway

Трансляція тихо змінює те, що бачить віддалена сторона

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

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

Вирішуйте за володінням, потім перевірте обіцяну відмову

Виберіть тунель на кожен Pod, коли віддалений сервіс автентифікує окремі навантаження, коли канал потрібен лише кільком Deployment і коли відмова має залишатися локальною. Виберіть шлюз, коли мережева команда вже володіє шляхом, коли багато навантажень поділяють одне призначення і коли стабільна адреса джерела — увесь сенс вправи.

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

Схожі статті