Пинг работает с узла и не работает с пода, а на локальную сторону ничего не приходит. Туннель и маршрут в порядке; адрес источника на проводе — нет. Эти два случая различает то, кем пакет себя объявляет при выходе из кластера, и у GKE на этот счёт есть мнение. Механизм — список исключений masquerade, и чтобы его прочитать, нужна одна команда.

Прочитайте действующий список, прежде чем что-то менять

GKE поставляет агент, который для каждого диапазона назначения решает, будет ли трафик подов при выходе переписан на адрес узла. Его конфигурация по умолчанию называет три блока RFC1918, 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16, как исключённые назначения. Поэтому всё, что вы отправите с пода на локальный хост 10.x, покидает узел с всё ещё прикреплённым адресом самого пода. Трафик самого узла не переписывается, и именно поэтому его пинг работает.

Прочитайте задуманную конфигурацию и установленные правила, потому что они могут не совпадать. kubectl -n kube-system get configmap ip-masq-agent -o yaml показывает, что сказали агенту, а kubectl -n kube-system get pods -l k8s-app=ip-masq-agent показывает, работает ли что-то, чтобы это применить. На узле iptables-save | grep -i masq показывает правила, которые действительно есть в ядре. Когда ConfigMap говорит одно, а правила другое, подозреваемый — агент, а не сеть.

Подтвердите адрес источника перехватом

Сделайте перехват до того, как менять список. Фильтр по одному назначению оставляет вывод читаемым: tcpdump -ni any host 10.20.30.40.

Сравните это с тем, что сообщает противоположная сторона. Перехват на локальной стороне, показывающий адрес пода и отсутствие ответа, замыкает круг: список исключений объясняет асимметрию без какой-либо неисправности туннеля. Двух наблюдений одного адреса источника достаточно, чтобы перестать гадать о CNI.

Сузьте исключение до CIDR подов

Поддерживаемое исправление сужает исключение, а не удаляет его: оставьте CIDR подов исключённым и отбросьте остальную часть пространства 10.x. Этот список живёт в ConfigMap агента под ключом nonMasqueradeCIDRs, и его изменение — это правка, за которой следует развёртывание. Замените широкую запись реальным диапазоном подов кластера, сохраните другие частные блоки, если трафику внутри кластера они всё ещё нужны, и не трогайте resyncInterval без причины. Примените, подтвердите, что поды агента перезапустились, и подтвердите, что правила ядра изменились.

Это изменение в масштабе всего кластера с реальным радиусом воздействия. После его применения трафик, который раньше сохранял источник пода, теперь приходит переписанным на узел, поэтому всё, что опиралось на эти адреса подов, видит другого отправителя. Пострадавшие — журналы, списки разрешений и локальные правила брандмауэра, где указаны адреса подов, и они отказывают молча. Объявляйте изменение как изменение поведения, а не как исправление.

В кластере с несколькими пулами узлов проверьте, что агент запланирован на узлах, где действительно работают затронутые поды. Пул без DaemonSet сохраняет свои старые правила, и ничто в ConfigMap это не покажет.

Альтернатива и её цена

Другой вариант оставляет адреса подов нетронутыми и учит маршрут о них. CIDR подов попадает в селекторы трафика Cloud VPN, а локальной стороне нужен для него обратный маршрут, чтобы ответы знали, куда идти. Это сохраняет идентичность пода, которой хотят некоторые модели безопасности, и расширяет как область маршрутизации, так и область брандмауэра, которую должна принять противоположная сторона.

Обмен — читаемость против охвата. Трансляция заставляет локальную сторону видеть один адрес на узел, что легко внести в список разрешений и что скрывает, какой под что отправил. Без трансляции адрес пода сохраняется от края до края, что лучше для атрибуции и хуже для каждого устройства на пути, которому нужно выучить новый диапазон. Ни один вариант не является дефектом Docker или CNI; оба — решения о маршрутизации с операционным счётом. Выберите тот, чей счёт ваша команда может оплатить, и запишите почему.

Проверьте и откатите

Запустите тот же перехват снова. Перехват на уровне узла, который после вашей правки всё ещё печатает адрес пода, означает, что правила так и не изменились, что бы ни говорил ConfigMap. Провод — это факт; всё остальное — вывод.

Затем проверьте обратное направление, потому что половина таких изменений проверяется только на выход. Подтвердите, что ответ доходит до узла или пода, отправившего запрос, и подтвердите, что приложение завершилось, а не просто получило SYN. Перехват, показывающий запрос без ответа, — это проблема маршрутизации на той стороне, а не проблема masquerade на этой.

Откат — это предыдущий ConfigMap, применённый тем же способом, с тем же подтверждением, что агент перезапустился и правила изменились. Сохраните адрес источника до и после для одного известного запроса в записи об изменении, потому что именно эта одна строка доказывает, что изменение сделало то, что вы сказали. Руководство GKE по агенту IP masquerade описывает значения по умолчанию и поля ConfigMap. Если адрес источника после развёртывания не изменился, агент не работает на этом узле, и никакая правка YAML это не исправит.

Похожие статьи