Защо pod-овете на GKE не достигат до локалните хостове през VPN
Възелът достига локалната мрежа, pod-ът не. Изключенията masquerade в GKE оставят адресите на pod-овете непреведени за дестинации 10.x.
Ping работи от възела и се проваля от pod-а, а локално не пристига нищо. Тунелът и маршрутът са наред; адресът на източника по кабела не е. Това, което различава двата случая, е какво пакетът твърди, че е, когато напуска клъстера, и GKE има мнение по въпроса. Механизмът е списък с изключения masquerade и прочитането му отнема една команда.
Прочетете действащия списък, преди да промените нещо
GKE доставя агент, който за всеки диапазон на дестинация решава дали трафикът на pod-овете се пренаписва на адреса на възела при излизане. Доставената му конфигурация посочва трите блока RFC1918, 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16, като изключени дестинации. Затова всичко, което изпратите от pod към локален хост 10.x, напуска възела с все още прикачен адрес на самия pod. Трафикът на самия възел не се пренаписва и точно затова неговият ping работи.
Прочетете предвидената конфигурация и инсталираните правила, защото те може да не съвпадат. 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.
Сравнете това с това, което съобщава отсрещната страна. Заснемане локално, което показва адреса на pod-а и липса на отговор, затваря кръга: списъкът с изключения обяснява асиметрията без никаква повреда на тунела. Две наблюдения на един адрес на източник са достатъчни, за да спрете да гадаете за CNI.
Стеснете изключението до CIDR на pod-овете
Поддържаната поправка стеснява изключението, вместо да го премахва: оставете CIDR на pod-овете изключен и отхвърлете останалата част от пространството 10.x. Този списък живее в ConfigMap на агента под nonMasqueradeCIDRs, а промяната му е редакция, следвана от внедряване. Заменете широкия запис с реалния диапазон на pod-овете в клъстера, запазете другите частни блокове, ако трафикът в клъстера все още се нуждае от тях, и оставете resyncInterval на мира, освен ако имате причина. Приложете, потвърдете, че pod-овете на агента са се рестартирали, и потвърдете, че правилата в ядрото са се променили.
Това е промяна в целия клъстер с реален радиус на въздействие. След като влезе в сила, трафикът, който преди запазваше своя източник pod, сега пристига пренаписан на възела, така че всичко, което разчиташе на тези адреси на pod-ове, вижда различен подател. Жертвите са журналите, списъците с разрешения и локалните правила на защитната стена, които посочват адреси на pod-ове, и те се провалят тихо. Обявявайте промяната като промяна в поведението, не като поправка.
В клъстер с няколко пула от възли проверете дали агентът е планиран на възлите, където засегнатите pod-ове наистина работят. Пул без DaemonSet запазва старите си правила и нищо в ConfigMap няма да покаже това.
Алтернативата и нейната цена
Другият вариант оставя адресите на pod-овете непокътнати и учи маршрута за тях. CIDR на pod-овете влиза в селекторите за трафик на Cloud VPN, а локалната страна се нуждае от обратен маршрут за него, за да знаят отговорите накъде да вървят. Това запазва идентичността на pod-а, която някои модели за сигурност искат, и разширява както обхвата на маршрутизацията, така и обхвата на защитната стена, който отсрещната страна трябва да приеме.
Разменната сделка е четимост срещу обхват. Преводът кара локалната страна да вижда един адрес на възел, което е лесно за добавяне в списък с разрешения и скрива кой pod какво е изпратил. Без превод адресът на pod-а се запазва от край до край, което е по-добре за приписване и по-лошо за всяко устройство по пътя, което трябва да научи нов диапазон. Нито един вариант не е дефект на Docker или CNI; и двата са решения за маршрутизация с оперативна сметка. Изберете този, чиято сметка екипът ви може да плати, и запишете защо.
Проверете и върнете
Пуснете същото заснемане отново. Заснемане на ниво възел, което след вашата редакция все още отпечатва адреса на pod-а, означава, че правилата никога не са се променили, каквото и да казва ConfigMap. Кабелът е фактът; всичко останало е извод.
След това проверете обратната посока, защото половината от тези промени се проверяват само на изход. Потвърдете, че отговорът достига до възела или pod-а, изпратил заявката, и потвърдете, че приложението е завършило, а не само е получило SYN. Заснемане, което показва заявка без отговор, е проблем с маршрутизацията от другата страна, не проблем с masquerade от тази.
Връщането е предишният ConfigMap, приложен по същия начин, със същото потвърждение, че агентът се е рестартирал и правилата са се променили. Запазете адреса на източника преди и след за една известна заявка в записа за промени, защото точно този един ред доказва, че промяната е направила това, което казахте. Ръководството на GKE за агента IP masquerade документира стойностите по подразбиране и полетата на ConfigMap. Ако адресът на източника не се е променил след внедряването, агентът не работи на този възел и никаква редакция на YAML няма да го поправи.