Модуль 3.8: Шлях даних мережі кластера
Складність:
[MEDIUM]— основна тема з діагностики.Час на проходження: ~40 хвилин.
Передумови: Модуль 3.1 (Сервіси), Модуль 3.6 (Мережеві політики), Модуль 3.7 (CNI)
Результати навчання
Розділ «Результати навчання»- Простежити шлях запиту від клієнтського Пода через DNS, трансляцію Сервісу, conntrack, маршрутизацію та доставку CNI до того моменту, коли він досягає бекенд-Пода.
- Розрізнити обов’язки kube-proxy від обов’язків CNI, а потім використати цю межу, щоб обрати правильну діагностичну команду, замість того щоб налагоджувати не той рівень.
- Налагодити збої міжвузлового з’єднання та з’єднання через Сервіс, порівнюючи результати DNS, об’єкти Endpoints або EndpointSlices, стан iptables чи nftables, маршрути, тунельні інтерфейси та захоплення пакетів.
- Оцінити проєкти оверлейної та нативної маршрутизації, пояснивши, як інкапсуляція, MTU, складність маршрутизації, source NAT та застосування політик змінюють шлях даних.
- Застосувати відтворювану ментальну модель діагностики до конкретного збою виробничого типу, перш ніж розв’язувати схоже завдання з трасування пакетів у практичній вправі.
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»О 03:00 інженеру платформи надходить виклик, бо запити на оформлення замовлення завершуються тайм-аутом між двома робочими навантаженнями Kubernetes, які годину тому були справними. Деплойменти запущені, об’єкт Сервісу досі існує, CoreDNS не перебуває в циклі аварійних перезапусків, а логи застосунку показують лише загальні тайм-аути з’єднання. Ніщо на першому екрані kubectl get pods не підказує, чи це збій DNS, kube-proxy, NetworkPolicy, conntrack, маршрутизації вузла чи проблема тунелю CNI.
Саме в такій ситуації мережа Kubernetes перетворюється з набору визначень на операційну навичку. Учень, який лише пам’ятає, що Сервіси мають ClusterIP, продовжуватиме пробувати випадкові команди, тоді як учень, який вміє простежити пакет, зможе розбити проблему на менші перевірки. Питання стає таким: чи розв’язалося ім’я, чи Сервіс обрав ендпоінти, чи вузол переписав призначення, чи conntrack зберіг зворотний шлях, і чи CNI доставив пакет між вузлами?
Цей модуль навчає шляху даних як послідовності рішень, які ухвалюють компоненти Linux та Kubernetes. Спочатку ви побачите простий шлях, а потім додасте балансування навантаження Сервісу, DNS, source NAT для NodePort, потоки «шпильки» (hairpin), оверлейну інкапсуляцію та стан для діагностики. Мета — не запам’ятати кожну деталь реалізації кожного CNI; мета — побудувати ментальну модель, достатньо міцну, щоб передбачити, де має з’явитися доказ, коли щось ламається.
Гіпотетичний сценарій: під час міграції кластера команда переходить від нативної маршрутизованої мережі Подів до оверлейного режиму CNI. Невеликі перевірки справності й далі проходять, готовність залишається зеленою, короткі виклики API працюють, але більші відповіді від одного сервісу до іншого зависають, поки клієнт не отримає тайм-аут. Зламані запити не випадкові; це саме ті, що достатньо великі, аби перевищити реальний MTU шляху після додавання накладних витрат на інкапсуляцію, тож доказ міститься нижче за застосунок і нижче за абстракцію Сервісу.
У цьому сценарії виправлення почалося б не з DNS і не з маніфесту Деплойменту. Команда платформи порівняла б MTU Пода, MTU тунелю та MTU підлеглої мережі (underlay), а потім перевірила б шлях даних за допомогою захоплення пакетів та прямих тестів «Под-до-Пода», перш ніж змінювати налаштування CNI. Kubernetes 1.35 досі залежить від того самого фундаментального шляху пакетів Linux, тож практична навичка — навчитися, де зупиняється кожна абстракція і де починається наступний рівень.
Частина 1: Побудова ментальної моделі «прогулянки» пакета
Розділ «Частина 1: Побудова ментальної моделі «прогулянки» пакета»Сервіс Kubernetes ховає мінливість бекенд-Подів за одним стабільним віртуальним IP, але пакет усе одно проходить через звичайну машинерію ядра. Перше важливе осяяння полягає в тому, що більшість пакетів не обробляє довготривалий процес-проксі в просторі користувача. kube-proxy спостерігає за Kubernetes API і програмує правила, тоді як мережевий стек Linux застосовує ці правила до пакетів, коли вони рухаються через вузол.
Почнімо з клієнтського Пода, який звертається до Сервісу типу ClusterIP. Клієнт вважає, що під’єднується до IP Сервісу, але бекенд-Под отримує пакет, адресований його власному IP. Цей перезапис — це destination NAT, який зазвичай називають DNAT, а таблиця відстеження з’єднань (connection-tracking) запам’ятовує достатньо стану, щоб відповідь виглядала коректно з боку клієнта.
+----------------------------------------------------------------------------+| ClusterIP Packet Walk: client pod to backend pod || || Node A Node B || +-------------------+ +-------------------+ || | Pod A | | Pod B | || | 10.244.1.5 | | 10.244.2.8 | || | curl 10.96.0.50 | | nginx :80 | || +---------+---------+ +---------^---------+ || | | || v | || +-------------------+ | || | veth pair | | || | pod netns to host | | || +---------+---------+ | || | | || v | || +-------------------+ PREROUTING / Service rules | || | kube-proxy rules | 10.96.0.50:80 | || | in kernel tables | -> 10.244.2.8:80 | || +---------+---------+ | || | | || v | || +-------------------+ NAT mapping saved so the | || | conntrack | reply can be translated | || | flow state | back for the client | || +---------+---------+ | || | | || v | || +-------------------+ same node: local veth | || | route lookup | other node: CNI path | || +---------+---------+ | || | remote node | || v | || +-------------------+ overlay or routed | +----------------+ || | CNI delivery +------------------------------->+ | CNI receive | || | tunnel or route | | | and decap | || +-------------------+ | +-------+--------+ || | | || +----------v----------+| v || Backend pod receives || traffic on port 80 |+----------------------------------------------------------------------------+Пакет залишає Под A через віртуальну пару Ethernet, яку зазвичай називають veth-парою, що з’єднує мережевий простір імен Пода з мережевим простором імен вузла. Звідти пакет потрапляє до гачків ядра, де правила, керовані kube-proxy, можуть зіставити IP призначення Сервісу. У режимі iptables це зазвичай задіює ланцюжки на кшталт KUBE-SERVICES, KUBE-SVC-* та KUBE-SEP-*, хоча точні назви залежать від режиму та реалізації.
Після того як призначення переписано на IP бекенд-Пода, вузол виконує звичайний пошук маршруту. Якщо бекенд-Под локальний, пакет можна доставити через іншу veth-пару на тому самому вузлі. Якщо бекенд-Под віддалений, наданий CNI шлях даних вирішує, чи інкапсулювати пакет у тунель, переслати його за допомогою нативної маршрутизації, чи передати його програмі eBPF, яка виконує еквівалентну роботу з пересилання.
Conntrack — це той елемент, який не дає відповіді заскочити клієнта зненацька. Под B відповідає Поду A, бо Под B бачив Под A як джерело, а не IP Сервісу. Коли відповідь повертається, conntrack розпізнає її як частину наявного потоку з NAT і обертає трансляцію назад, тож сокет Пода A все ще бачить відповідь, пов’язану зі з’єднанням Сервісу, яке він відкрив.
Зробіть паузу і передбачте: якщо Под A під’єднується до
10.96.0.50:80, але Под B бачить пакет як призначений для10.244.2.8:80, що зламалося б, якби conntrack забув відображення до повернення відповіді? Запишіть, чи побачив би клієнт чисту відмову, тайм-аут чи несподівану адресу джерела, перш ніж читати далі.
Найкорисніша відповідь полягає в тому, що симптом залежить саме від того, який стан зник і як стек обробляє пакет, що повертається. На практиці застарілий або відсутній стан conntrack часто проявляється як зависання, скидання (reset) або асиметричний трафік, через який одна сторона вважає, що з’єднання існує, тоді як інша не може завершити потік. Саме тому conntrack належить до моделі діагностики, а не до примітки внизу сторінки.
1.1 Що kube-proxy робить насправді
Розділ «1.1 Що kube-proxy робить насправді»Попри назву, kube-proxy зазвичай не сидить посередині кожного пакета Сервісу як проксі в просторі користувача. Його основне завдання — спостерігати за Сервісами та EndpointSlices, а потім програмувати вузол так, щоб ядро могло транслювати віртуальний трафік Сервісу до реального трафіку бекенд-Подів. Шлях пакета швидкий, бо пакет із даними залишається в просторі ядра, але коректність цього шляху залежить від того, чи тримає kube-proxy правила синхронізованими з API.
Коли Сервіс має два готові бекенд-Поди, kube-proxy створює правила або еквівалентний стан, що можуть обрати будь-який із бекендів. У режимі iptables вибір ендпоінта можна представити через ймовірнісні зіставлення та ланцюжки DNAT для кожного ендпоінта. У режимі nftables представлення змінюється, але концептуальне завдання залишається тим самим: зіставити віртуальне призначення Сервісу, обрати ендпоінт, переписати призначення та покластися на conntrack для зворотного шляху.
# Check the kube-proxy mode configured for this cluster.kubectl get configmap kube-proxy -n kube-system -o yaml | grep -E "mode:|strictARP|clusterCIDR"
# Inspect kube-proxy health and recent logs.kubectl get pods -n kube-system -l k8s-app=kube-proxy -o widekubectl logs -n kube-system -l k8s-app=kube-proxy --tail=40Вивід команди найкорисніший, коли ви пов’язуєте його назад із симптомом. Якщо трафік «Под-до-Пода» працює за прямим IP Пода, але трафік через Сервіс зазнає збою, стан kube-proxy стає головним підозрюваним. Якщо і прямий IP Пода, і трафік через Сервіс зазнають збою, kube-proxy все ще може бути справним, а збій може лежати нижче — у CNI, політиці, брандмауері вузла чи шляху маршрутизації.
1.2 NodePort додає рішення про source-NAT
Розділ «1.2 NodePort додає рішення про source-NAT»NodePort починається поза кластером, тож перший пакет прибуває на IP вузла й високий порт, а не безпосередньо на Под чи ClusterIP. Правила kube-proxy зіставляють NodePort, транслюють його до Сервісу, а потім до бекенд-ендпоінта, і можуть також застосувати source-NAT до пакета залежно від політики трафіку Сервісу. Це рішення про source-NAT змінює те, що бачить бекенд-Под, і те, як повертається відповідь.
+----------------------------------------------------------------------------+| NodePort Packet Walk || || External client || +-------------------+ || | curl node:30080 | || +---------+---------+ || | || v || +-------------------+ Node receives packet on node IP and NodePort || | node interface | before Kubernetes Service translation occurs || +---------+---------+ || | || v || +-------------------+ NodePort rule maps port to Service backend || | kube-proxy rules | and chooses one ready endpoint || +---------+---------+ || | || v || +-------------------+ externalTrafficPolicy: Cluster may SNAT || | source NAT choice | externalTrafficPolicy: Local preserves source || +---------+---------+ || | || v || +-------------------+ packet now follows the ClusterIP-style path || | CNI or local veth | toward the chosen backend pod || +-------------------+ |+----------------------------------------------------------------------------+З externalTrafficPolicy: Cluster Kubernetes може надіслати запит до будь-якого готового ендпоінта в кластері. Компроміс у тому, що бекенд зазвичай бачить IP вузла як джерело, бо SNAT тримає зворотний шлях симетричним через вузол, який отримав пакет. Це просто й забезпечує високу доступність, але це приховує оригінальний IP клієнта, доки інший рівень не збереже його через заголовки чи проксі-протокол.
З externalTrafficPolicy: Local Kubernetes зберігає оригінальний IP клієнта, надсилаючи трафік лише до локальних ендпоінтів на вузлі, який отримав пакет. Це цінно для журналів аудиту та застосунків, що враховують клієнта, але створює операційну умову: вузли без локального готового ендпоінта не повинні отримувати трафік для цього Сервісу. Тому перевірки справності хмарного балансувальника навантаження та розподіл ендпоінтів стають частиною проєкту.
| Вибір NodePort | Що бачить бекенд | Операційний компроміс | Коли його зазвичай обирають |
|---|---|---|---|
externalTrafficPolicy: Cluster | Часто IP вузла, бо застосовано SNAT | Гнучкіший вибір бекенда, але IP джерела може бути прихований | Загальні сервіси, яким не потрібен IP клієнта на рівні Пода |
externalTrafficPolicy: Local | Реальний зовнішній IP клієнта | Потребує локальних ендпоінтів на вузлах, що отримують трафік | Контролери Ingress, застосунки, чутливі до аудиту, та робочі навантаження, що враховують джерело |
| LoadBalancer із використанням NodePort | Залежить від політики трафіку та поведінки провайдера | Додає хмарні перевірки справності та правила маршрутизації провайдера | Керовані кластери, де зовнішній трафік входить через хмарну інфраструктуру |
| Слухач HostNetwork | Под використовує мережевий простір імен вузла | Обходить звичайні припущення щодо ізоляції Подів | Спеціалізовані агенти та низькорівневі мережеві компоненти |
1.3 Трафік «шпилька» (hairpin) — це петля назад через вузол
Розділ «1.3 Трафік «шпилька» (hairpin) — це петля назад через вузол»Трафік «шпилька» (hairpin) виникає, коли Под надсилає трафік до Сервісу, а kube-proxy обирає цей самий Под як бекенд. З погляду застосунку це виглядає як Под, який звертається до власного стабільного імені Сервісу. З погляду мережі пакет може бути змушений залишити простір імен Пода, пройти DNAT, а потім повернутися тим самим містком (bridge) або veth-шляхом назад у той самий Под.
+----------------------------------------------------------------------------+| Hairpin Flow || || +----------------------+ || | Pod A | || | app curls web-svc | || +----------+-----------+ || | || v || +----------------------+ || | node Service rules | Service chooses Pod A itself as the endpoint || +----------+-----------+ || | || v || +----------------------+ || | bridge or veth path | hairpin mode must allow the frame to return || +----------+-----------+ || | || v || +----------------------+ || | Pod A receives the | successful loopback through the Service path || | request on app port | || +----------------------+ |+----------------------------------------------------------------------------+Збої «шпильки» збивають з пантелику, бо Сервіс може працювати з інших Подів, а застосунок може працювати, коли його викликають безпосередньо за IP Пода. Зламаний випадок — це конкретно петля, де обраний ендпоінт є викликачем. Якщо ваш застосунок викликає сам себе через ім’я свого Сервісу, несправний шлях «шпильки» може виглядати як збій Сервісу, навіть якщо більшість інших клієнтів почуваються добре.
# Inspect the pod's network devices and routes from inside the pod.kubectl exec <pod-name> -- ip link showkubectl exec <pod-name> -- ip route
# On a node, hairpin settings are usually inspected through the veth or bridge path.# The exact interface name depends on the CNI and runtime, so find it before reading.cat /sys/devices/virtual/net/<veth-name>/brport/hairpin_modeНе варто починати сеанс діагностики з припущення, що проблема саме у «шпильці». Використовуйте її як цільову гілку, коли симптом вузький: Под не може дістатися до власного Сервісу, але інші Поди можуть дістатися до того самого Сервісу, а прямий доступ до порту застосунку Пода працює. Цей патерн дає достатньо доказів, щоб перевірити містки, veth, CNI та налаштування «шпильки» в kubelet.
Частина 2: Розмежування обов’язків CNI, kube-proxy, DNS та політики
Розділ «Частина 2: Розмежування обов’язків CNI, kube-proxy, DNS та політики»Найшвидший спосіб згаяти час у мережі Kubernetes — звинуватити не той рівень. kube-proxy не створює інтерфейси Подів, CoreDNS не обирає ендпоінти Сервісу, а більшість CNI не реалізують базові правила віртуального IP Сервісу, якщо тільки вони навмисно не замінюють kube-proxy. Вашим першим діагностичним кроком має бути визначення того, який обов’язок зачіпає симптом.
+----------------------------------------------------------------------------+| Responsibility Boundaries in the Data Path || || +----------------------------+ +----------------------------+ || | CNI plugin | | kube-proxy or replacement | || | | | | || | Creates pod network path | | Implements Service VIPs | || | Assigns and routes pod IPs | | Chooses Service endpoints | || | Builds veth and tunnels | | Programs DNAT and NodePort | || | May enforce NetworkPolicy | | Handles session affinity | || | May use BGP, VXLAN, eBPF | | May use iptables/nft/eBPF | || +----------------------------+ +----------------------------+ || || +----------------------------+ +----------------------------+ || | CoreDNS | | NetworkPolicy controller | || | | | and CNI enforcement | || | Answers Service names | | Allows or denies pod flows | || | Uses Service for its own IP| | Often enforced by the CNI | || | Forwards external queries | | Does not create endpoints | || +----------------------------+ +----------------------------+ |+----------------------------------------------------------------------------+Гарне діагностичне питання — не «чи зламана мережа?», а «яку обіцянку порушено?». Kubernetes обіцяє, що Поди можуть спілкуватися з Подами без NAT, Сервіси можуть маршрутизувати до готових ендпоінтів, Поди можуть розв’язувати DNS-записи Сервісів, а політики можуть обмежувати обраний трафік. Це пов’язані обіцянки, але не одна й та сама обіцянка, і кожна з них вказує на різні докази.
| Симптом, видимий із клієнтського Пода | Прямий наступний тест | Найімовірніше задіяний рівень, якщо тест зазнає невдачі | Чому цей рівень стає підозрілим |
|---|---|---|---|
| Ім’я Сервісу не розв’язується | kubectl exec client -- nslookup service | DNS або доступність CoreDNS | Клієнт не може навіть отримати віртуальний IP Сервісу |
| Ім’я Сервісу розв’язується, але curl до Сервісу зазнає невдачі | kubectl get endpoints service | Вибір Сервісу або kube-proxy | DNS спрацював, тож збій перейшов за межі розв’язання імені |
| ClusterIP зазнає невдачі, але IP ендпоінт-Пода працює | Перевірте правила та логи kube-proxy | kube-proxy або стан Сервісу | Маршрутизація Подів працює, тоді як трансляція віртуального IP — ні |
| IP ендпоінт-Пода зазнає невдачі між вузлами | kubectl exec client -- curl http://pod-ip | CNI, політика, маршрут, MTU або брандмауер вузла | Абстракцію Сервісу більше не задіяно |
| IP Пода на тому самому вузлі працює, але між вузлами — ні | Порівняйте розміщення вузлів та маршрути | Тунель CNI, BGP, брандмауер або MTU | Локальна veth-доставка працює, тоді як міжвузлова доставка зазнає невдачі |
| DNS працює, але зовнішні імена повільні | Перевірте /etc/resolv.conf та час запитів | Поведінка пошуку резолвера або апстріми CoreDNS | Мережа може працювати, тоді як розширення імені спричиняє затримку |
2.1 Трафік «Под-до-Пода» — це обіцянка CNI
Розділ «2.1 Трафік «Под-до-Пода» — це обіцянка CNI»Мережева модель Kubernetes вимагає, щоб кожен Под міг дістатися до кожного іншого Пода без видимого для застосунку NAT. Сам Kubernetes не налаштовує всю цю мережу. Середовище виконання контейнерів викликає плагіни CNI під час створення Подів, а плагін CNI під’єднує інтерфейси, призначає адреси, встановлює маршрути та готує будь-який механізм пересилання на рівні вузла, який використовує реалізація.
Прямий тест за IP Пода — це найчистіший спосіб запитати, чи працює сама мережа Подів. Якщо Под A може дістатися до Пода B за IP та портом, CNI проніс потік достатньо далеко, щоб застосунок міг відповісти. Якщо Под A не може дістатися до Пода B за IP Пода, налагодження об’єктів Сервісу спочатку зазвичай марнує час, бо збій лежить під рівнем Сервісу.
# Get backend pod IPs and node placement so you know whether the test crosses nodes.kubectl get pods -o wide
# Test direct pod-to-pod connectivity from a client pod.kubectl exec <client-pod> -- wget -qO- --timeout=5 http://<backend-pod-ip>:<port>
# Compare the direct test with the Service test.kubectl exec <client-pod> -- wget -qO- --timeout=5 http://<service-name>:<port>Варто також перевірити, чи не NetworkPolicy навмисно змінює відповідь. CNI з підтримкою політик може відкинути прямий тест за IP Пода, бо політика забороняє потік, а не тому, що зламана маршрутизація. Симптом усе ще живе на рівні CNI та політики, але виправлення відрізняється від зміни тунелів чи маршрутів вузла.
2.2 Трафік через Сервіс — це обіцянка kube-proxy
Розділ «2.2 Трафік через Сервіс — це обіцянка kube-proxy»Об’єкт Сервісу корисний лише тоді, коли він обирає готові ендпоінти і кожен вузол має правила, потрібні для трансляції віртуального IP Сервісу. Порожні ендпоінти означають, що kube-proxy не має до чого маршрутизувати, навіть коли об’єкт Сервісу існує. Застарілі чи відсутні правила вузла означають, що Сервіс може мати ендпоінти в API, тоді як окремі вузли не можуть коректно транслювати трафік.
# Check whether the Service has a ClusterIP and which selector it uses.kubectl get svc <service-name> -o widekubectl describe svc <service-name>
# Check [EndpointSlices because modern clusters use them as the scalable endpoint source](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/).kubectl get endpointslice -l kubernetes.io/service-name=<service-name> -o wide
# The legacy Endpoints object is still a quick exam-friendly view in many clusters.kubectl get endpoints <service-name>Якщо ендпоінти порожні, залишайтеся на рівні Kubernetes API, перш ніж перевіряти iptables. Підтвердьте, що селектор Сервісу збігається з мітками Подів, що Поди в тому самому просторі імен, що й Сервіс, і що Поди готові (Ready). Под може бути в стані Running і все ж бути виключеним з ендпоінтів, бо готовність не пройшла — це одна з найпоширеніших пасток у діагностиці Сервісів.
Якщо ендпоінти коректні, переходьте до трансляції Сервісу на рівні вузла. На вузлі kind ви можете перевірити правила з хоста через контейнер вузла. На реальному вузлі вам потрібен доступ до оболонки вузла з привілеями, відповідними до кластера. Команда змінюється залежно від режиму kube-proxy, але питання залишається тим самим: чи отримав і запрограмував цей вузол стан Сервісу?
# kind example: inspect Service-related kernel rules inside the control-plane node.docker exec kind-control-plane iptables-save | grep <service-name>
# A generic node example when iptables mode is in use.iptables-save | grep -E "KUBE-SVC|KUBE-SEP|<service-name>"
# For nftables mode, inspect the Kubernetes-related ruleset instead.nft list ruleset | grep -i <service-name>2.3 Оверлейна та нативна маршрутизація змінюють режими збоїв
Розділ «2.3 Оверлейна та нативна маршрутизація змінюють режими збоїв»Оверлейна мережа загортає оригінальний пакет Пода в інший пакет, тож наявній підлеглій мережі (underlay) потрібно лише маршрутизувати між IP вузлів. Це зручно, бо уникає потреби навчати фізичну мережу про CIDR Подів, але інкапсуляція додає накладні витрати й створює специфічні для тунелю проблеми з брандмауером та MTU. VXLAN, Geneve та IP-in-IP різняться деталями, але мають спільну операційну тему: пакет може бути справним до інкапсуляції й завеликим або заблокованим після інкапсуляції.
Нативна маршрутизація уникає оверлейної обгортки, змушуючи мережу маршрутизувати CIDR Подів безпосередньо. Це може поліпшити продуктивність та спростити поведінку MTU, але вимагає, щоб мережа вузлів, хмарні маршрути, шлюзи хостів чи BGP-пери знали, як дістатися до CIDR Подів. Тому збої нативної маршрутизації часто виглядають як звичайні збої маршрутизації, а не як збої тунелю.
| Проєкт маршрутизації | Що вузол надсилає через мережу | Сильна сторона | Поширений режим збою |
|---|---|---|---|
| Оверлей VXLAN | UDP-інкапсульований пакет між IP вузлів | Працює поверх багатьох наявних мереж | Невідповідність MTU або заблокований тунельний трафік |
| Оверлей Geneve | UDP-інкапсульований пакет із розширюваними метаданими | Гнучкий для просунутих площин даних | Ті самі проблеми інкапсуляції та брандмауеру, що й в інших оверлеїв |
| Оверлей IP-in-IP | Пакет з IP Пода, загорнутий у зовнішній IP-пакет | Проста маршрутизація поверх досяжності IP вузлів | Фільтрація протоколу або накладні витрати MTU |
| Нативна маршрутизація з BGP | Звичайний пакет з IP Пода, маршрутизований мережею | Висока продуктивність і відсутність накладних витрат тунелю | Відсутні маршрути або зламаний BGP-пірінг |
| Маршрутизація host-gateway | Звичайний пакет з IP Пода через шлюзи вузлів | Проста у пласких середовищах L2 | Зазнає невдачі, коли вузли не в сумісній мережі |
| Площина даних eBPF | Пересилання та трансляція, залежні від програми | Може замінити кілька систем правил ядра | Потребує специфічних для реалізації інструментів та спостережуваності |
Не сприймайте назви CNI як вичерпні пояснення. Calico може працювати в різних режимах, Cilium може використовувати оверлей або нативну маршрутизацію і може замінити kube-proxy, а поведінка Flannel залежить від вибору бекенда. Завжди перевіряйте фактично налаштований режим, перш ніж вирішувати, який режим збою є правдоподібним.
# Look at CNI pods and node placement.kubectl get pods -n kube-system -o wide | grep -E "calico|cilium|flannel|weave|antrea"
# Inspect common tunnel interfaces on a node when your CNI uses overlays.ip link show | grep -E "vxlan|flannel|cilium|geneve|tunl"
# Inspect pod and node routes when native routing or host-gateway behavior is expected.ip routeЗупиніться й вирішіть: бекенд-Сервіс зазнає невдачі лише тоді, коли клієнтський Под і бекенд-Под на різних вузлах. Той самий Сервіс працює, коли обидва Поди потрапляють на той самий вузол. Який рівень слід досліджувати першим, і який доказ відрізнив би проблему MTU від заблокованого тунелю чи відсутнього маршруту?
Ключ у тому, що успіх на тому самому вузлі доводить: застосунок, готовність та локальна veth-доставка можуть працювати. Збій між вузлами переносить підозру на міжвузловий шлях: інкапсуляцію, нативні маршрути, хмарні правила безпеки, правила брандмауеру вузла чи політику, яка різниться залежно від розміщення вузла. Проблеми MTU часто зачіпають більші пакети сильніше, ніж крихітні зонди, тоді як заблокований тунельний трафік чи відсутні маршрути зазвичай ламають навіть малі міжвузлові запити.
Частина 3: DNS — теж клієнт Сервісу
Розділ «Частина 3: DNS — теж клієнт Сервісу»DNS у Kubernetes здається відокремленим, бо користувачі вводять імена, але сам шлях DNS — це шлях через Сервіс. Под надсилає DNS-пакет до IP кластерного DNS-Сервісу, kube-proxy чи його заміна транслює цей пакет до ендпоінта CoreDNS, а CoreDNS повертає запис. Якщо шлях даних кластерного Сервісу зламано, DNS може зазнавати невдачі навіть тоді, коли Поди CoreDNS запущені.
+----------------------------------------------------------------------------+| DNS Resolution Path || || +----------------------+ || | Client pod | || | curl http://web-svc | || +----------+-----------+ || | || v || +----------------------+ || | /etc/resolv.conf | nameserver points at the CoreDNS ClusterIP || | search domains | search list expands short names || | options ndots:5 | resolver decides query order || +----------+-----------+ || | || v || +----------------------+ || | DNS packet to | usually UDP or TCP port 53 toward Service IP || | kube-dns ClusterIP | || +----------+-----------+ || | || v || +----------------------+ || | Service translation | kube-proxy chooses a CoreDNS backend pod || +----------+-----------+ || | || v || +----------------------+ || | CoreDNS pod | kubernetes plugin answers Service records || | returns A or AAAA | forward plugin handles external names || +----------+-----------+ || | || v || Client connects to the returned Service IP, then Part 1 begins again |+----------------------------------------------------------------------------+Найважливіший поділ у діагностиці DNS — між «ім’я не розв’язалося» та «ім’я розв’язалося, але з’єднання зазнало невдачі». Якщо nslookup trace-svc повертає правильний ClusterIP, DNS виконав свою роботу для цього імені. Пізнішу невдачу curl слід перевіряти через ендпоінти Сервісу, трансляцію kube-proxy, політику, маршрутизацію CNI чи застосунок.
# Inspect the resolver configuration as the pod actually sees it.kubectl exec <client-pod> -- cat /etc/resolv.conf
# Resolve a short Service name from inside the pod.kubectl exec <client-pod> -- nslookup <service-name>
# Resolve the fully qualified Service name to remove namespace ambiguity.kubectl exec <client-pod> -- nslookup <service-name>.<namespace>.svc.cluster.local
# Check CoreDNS pods and logs if resolution itself fails.kubectl get pods -n kube-system -l k8s-app=kube-dns -o widekubectl logs -n kube-system -l k8s-app=kube-dns --tail=603.1 Домени пошуку та ndots можуть створювати затримку
Розділ «3.1 Домени пошуку та ndots можуть створювати затримку»Поди Kubernetes зазвичай отримують список пошуку та ndots:5, що означає: ім’я з менш ніж п’ятьма крапками спершу пробують через домени пошуку, перш ніж запитати абсолютне ім’я. Це корисно для коротких внутрішньокластерних імен на кшталт web, але може зашкодити робочим навантаженням, що здебільшого звертаються до зовнішніх доменів. Ім’я на кшталт api.example.com може згенерувати кілька невдалих кластерно-локальних запитів, перш ніж реальний абсолютний запит увінчається успіхом.
# Observe resolver configuration inside a pod.kubectl exec <client-pod> -- cat /etc/resolv.conf
# Compare an external name without and with a trailing dot.kubectl exec <client-pod> -- nslookup api.example.comkubectl exec <client-pod> -- nslookup api.example.com.Кінцева крапка повідомляє резолверу, що ім’я є абсолютним, тож його не слід розширювати через список пошуку. Для конфігурації застосунку, який раз у раз звертається до зовнішніх сервісів, кінцева крапка або нижче значення ndots може прибрати зайву роботу DNS. Правильний вибір залежить від того, чи звертається робоче навантаження переважно до кластерно-локальних Сервісів, зовнішніх імен, чи й до тих, і до інших.
apiVersion: v1kind: Podmetadata: name: dns-optimized-clientspec: dnsConfig: options: - name: ndots value: "2" containers: - name: client image: busybox:1.36 command: - sleep - "3600"| Симптом DNS | Доказ для збору | Імовірна причина | Наступна дія |
|---|---|---|---|
| Усі імена Сервісів зазнають невдачі | nslookup kubernetes.default зазнає невдачі | CoreDNS недоступний або зламано шлях DNS-Сервісу | Перевірте Поди CoreDNS, Сервіс kube-dns та правила kube-proxy |
| Зовнішні імена зазнають невдачі, але імена Сервісів працюють | Кластерно-локальний пошук успішний, зовнішній — ні | Апстрім-пересилання CoreDNS або проблема DNS вузла | Перевірте ConfigMap CoreDNS та досяжність апстріму |
| Короткі зовнішні імена повільні | Перед успіхом з’являється кілька спроб домену пошуку | Накладні витрати ndots та розширення пошуку | Використайте кінцеві крапки або налаштуйте dnsConfig для цього навантаження |
| Ім’я Сервісу між просторами імен зазнає невдачі | FQDN працює, а коротке ім’я — ні | Невідповідність списку пошуку простору імен | Використайте service.namespace.svc.cluster.local |
| DNS успішний, але curl зазнає невдачі | nslookup повертає очікуваний ClusterIP | Проблема Сервісу, політики, CNI чи застосунку | Перейдіть до перевірок ендпоінтів та шляху даних |
| Періодичні тайм-аути DNS | Логи CoreDNS показують затримки чи тайм-аути | перевантаження, політика або нестабільність апстріму | Перевірте ресурси CoreDNS, політики та апстрім-DNS |
3.2 DNS залежить і від NetworkPolicy
Розділ «3.2 DNS залежить і від NetworkPolicy»CoreDNS — це просто ще один набір Подів за Сервісом, тож політики можуть блокувати DNS-трафік, якщо вони обирають клієнтів надто широко. Політика egress із типовою забороною (default-deny), яка забуває дозволити DNS-трафік UDP та TCP до kube-system, може зробити застосунки несправними на вигляд, навіть якщо їхні шляхи Сервісу та мережі Подів інакше справні. Саме тому перевірки DNS належать до верхівки моделі діагностики.
Коли DNS заблоковано політикою, прямі тести за IP Пода все ще можуть працювати, якщо політика дозволяє ці потоки або якщо тест обходить заборонений крок DNS. Це може ввести команди в оману, змусивши казати «мережа працює», тоді як застосунки все ще зазнають невдачі, бо вони використовують імена. Завжди відокремлюйте розв’язання імен від транспортної зв’язності, коли задіяна політика.
# Look for policies in both the client namespace and kube-system.kubectl get networkpolicy -A
# Test DNS and direct connectivity separately.kubectl exec <client-pod> -- nslookup kubernetes.defaultkubectl exec <client-pod> -- wget -qO- --timeout=5 http://<backend-pod-ip>:<port>Частина 4: Ментальна модель діагностики, яку можна застосувати
Розділ «Частина 4: Ментальна модель діагностики, яку можна застосувати»Корисна модель діагностики має зменшувати вгадування, а не додавати церемоніал. Модель у цьому модулі починається з імені, переходить до Сервісу, потім до прямої досяжності ендпоінта, і нарешті перевіряє стан на рівні вузла, коли прості тести ізолюють несправний рівень. Ви маєте вміти зупинитися рано, коли доказ ідентифікує проблему, і вміти зануритися глибше, коли симптом залишається неоднозначним.
+----------------------------------------------------------------------------+| Three-Layer Diagnosis for Service Failures || || Symptom: client pod cannot reach a Service by name || | || v || +-------------------------------+ || | Layer 1: DNS | || | Does the name resolve? | || | nslookup service.namespace | || +-----------+-------------------+ || no | yes || v v || Check CoreDNS, resolver, +-------------------------------------+ || DNS policy, and kube-dns | Layer 2: Service selection | || Service translation | Does the Service have ready endpoints? || | endpointslice or endpoints | || +-----------+-------------------------+ || no | yes || v v || Check selector, +--------------------------+ || namespace, labels, | Layer 3: Endpoint reach | || readiness probes | Can client reach pod IP? | || | curl endpoint IP and port| || +-----------+--------------+ || no | yes || v v || CNI, policy, Service translation,|| route, MTU, app listener, or || node firewall conntrack branch |+----------------------------------------------------------------------------+Модель починається з DNS, бо застосунки зазвичай використовують імена, а невдалий пошук імені не дає решті з’єднання навіть розпочатися. Наступна гілка перевіряє, чи має Сервіс дійсні готові ендпоінти, бо порожній набір ендпоінтів — це не загадка пересилання пакетів. Лише після того, як ці тести пройдено, варто витрачати час на iptables, nftables, інструменти eBPF, conntrack, таблиці маршрутів, MTU чи захоплення пакетів.
Цей підхід також захищає вас від метушні з командами під час іспиту. На CKA ви рідко маєте необмежений час, щоб перевірити кожен рівень. Коротка послідовність розрізнювальних тестів краща за довгий перелік команд, бо кожен результат каже вам, що робити далі й що ігнорувати.
4.1 Мінімальна корисна послідовність команд
Розділ «4.1 Мінімальна корисна послідовність команд»Мінімальна послідовність збирає один факт на кожен рівень. Ви можете запустити її з налагоджувального Пода або з наявного клієнтського Пода, залежно від того, що дозволяє сценарій. Ключ — записати кожну відповідь, перш ніж рухатися глибше, бо пропущені спостереження — це те, як команди опиняються в ситуації, коли налагоджують CoreDNS заради проблеми селектора Сервісу.
# Layer 1: Does the client resolve the intended Service name?kubectl exec <client-pod> -- nslookup <service-name>.<namespace>.svc.cluster.local
# Layer 2: Does the Service point to ready endpoints?kubectl get svc <service-name> -n <namespace> -o widekubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> -o wide
# Layer 3: Can the client reach a selected endpoint by pod IP?kubectl exec <client-pod> -- wget -qO- --timeout=5 http://<endpoint-pod-ip>:<port>
# Node state: inspect translation and connection state only after the layer tests justify it.iptables-save | grep -E "KUBE-SVC|KUBE-SEP|<service-name>"conntrack -L -d <service-cluster-ip> 2>/dev/nullЯкщо прямий тест ендпоінта успішний, а тест ClusterIP зазнає невдачі, доказ вказує на трансляцію Сервісу або стан з’єднання. Якщо прямий тест ендпоінта зазнає невдачі, а ендпоінт-Под на іншому вузлі, перевірте справність CNI, політику, маршрути, тунелі та брандмауери вузлів. Якщо прямий тест ендпоінта зазнає невдачі на тому самому вузлі, політика чи слухач застосунку стають імовірнішими, ніж проблема міжвузлового тунелю.
4.2 Розбір прикладу: checkout не може дістатися до inventory
Розділ «4.2 Розбір прикладу: checkout не може дістатися до inventory»Розбір прикладу робить ментальну модель конкретною, перш ніж ви самостійно розв’яжете схожу проблему. Уявіть виробничий простір імен під назвою shop із клієнтом checkout та бекендом inventory. Розробники повідомляють, що checkout отримує тайм-аут під час виклику http://inventory:8080, але лише після викочування, яке змінило перевірки готовності та додало NetworkPolicy.
Неправильний підхід — почати зі зміни CNI чи перезапуску CoreDNS. Дисциплінований підхід — простежити шлях. Спершу перевірте DNS із клієнта. Якщо DNS повертає IP Сервісу, розв’язання імені наразі не є блокувальником. Якщо DNS зазнає невдачі, зупиніться й перевірте CoreDNS, конфігурацію резолвера та політику egress для DNS, перш ніж торкатися ендпоінтів.
# Step 1: Test name resolution from the failing client context.kubectl exec -n shop deploy/checkout -- nslookup inventory.shop.svc.cluster.localПрипустімо, що пошук повертає 10.96.88.20. Це означає, що клієнт може розв’язати ім’я Сервісу, і CoreDNS разом зі шляхом DNS-Сервісу спрацювали для цього запиту. Наступне питання — чи має Сервіс готові ендпоінти. Сервіс без ендпоінтів прийме пошук імені, але не має бекенд-призначення, яке kube-proxy міг би обрати.
# Step 2: Inspect Service selection and ready endpoints.kubectl get svc -n shop inventory -o widekubectl get endpointslice -n shop -l kubernetes.io/service-name=inventory -o widekubectl get pods -n shop -l app=inventory -o wideПрипустімо, що EndpointSlice не показує готових ендпоінтів, тоді як kubectl get pods показує два Поди inventory у стані Running із 0/1 READY. Цей доказ змінює діагноз. Збій — це не тунель CNI, не kube-proxy і не DNS; Сервіс не має готових бекендів, бо готовність зазнає невдачі. Ви перевірили б перевірку готовності, логи Подів та порт застосунку, а не пересилання пакетів на вузлі.
# Step 3: Confirm why the pods are excluded from endpoints.kubectl describe pod -n shop -l app=inventorykubectl logs -n shop -l app=inventory --tail=80Тепер трохи змінімо сценарій. Припустімо, що EndpointSlice показує два готові ендпоінти, і один IP ендпоінта — 10.244.3.22. Сервіс має бекенди, тож наступний тест — пряма досяжність ендпоінта з клієнта. Це усуває трансляцію Сервісу з тесту й запитує, чи дозволяють потік мережа Подів та політика.
# Step 4: Test direct endpoint reachability.kubectl exec -n shop deploy/checkout -- wget -qO- --timeout=5 http://10.244.3.22:8080Якщо прямий доступ за IP Пода зазнає невдачі, перевірте NetworkPolicy, перш ніж припускати, що маршрутизація зламана, бо викочування додало політику. Політика ingress із типовою забороною, що обирає inventory, може дозволяти трафік від старої мітки на кшталт role=frontend, тоді як Поди checkout тепер використовують app=checkout і більше не збігаються з правилом дозволу. Це збій шляху даних, але виправлення — це узгодження політики, а не ремонт CNI.
# Step 5: Inspect policies that select either side of the flow.kubectl get networkpolicy -n shopkubectl describe networkpolicy -n shopkubectl get pods -n shop --show-labelsЯкщо прямий доступ за IP Пода успішний, але Сервіс усе одно отримує тайм-аут, перевірте трансляцію Сервісу та conntrack. Ендпоінт може відповідати, тож нижча мережа Подів здатна нести потік. Залишені підозрювані — це правила kube-proxy, застарілий стан conntrack, невідповідність між портом Сервісу та targetPort або локальна, специфічна для вузла проблема програмування.
# Step 6: Compare Service port configuration with the backend container port.kubectl describe svc -n shop inventorykubectl get pods -n shop -l app=inventory -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.podIP}{"\n"}{end}'
# Step 7: On the node, inspect translation and connection state when justified.iptables-save | grep inventoryconntrack -L -d 10.96.88.20 2>/dev/nullЦей приклад демонструє звичку, яку варто скопіювати у вправі. Кожна команда відповідає на одне питання й звужує гілку. Метод працює, бо поважає шлях пакета: розв’язання імені, вибір Сервісу, трансляція Сервісу, досяжність ендпоінта, політика та стан вузла пов’язані, але роздільні.
Що сталося б, якби Сервіс
inventoryобирав правильні Поди, але йогоtargetPortвказував на9090, тоді як застосунок слухає на8080? Вирішіть, чи кожне з цього — DNS, EndpointSlices, прямий доступ за IP Пода до8080та доступ через Сервіс до8080— увінчалося б успіхом чи зазнало невдачі.
Очікуваний патерн тонкий. DNS може спрацювати, бо Сервіс існує. EndpointSlices можуть показувати готові ендпоінти, бо готовність може перевіряти інший шлях чи порт. Прямий доступ за IP Пода до 8080 може спрацювати, бо застосунок слухає там. Доступ через Сервіс до порту Сервісу може зазнати невдачі, бо kube-proxy робить DNAT на неправильний цільовий порт — саме тому порт Сервісу й targetPort заслуговують на перевірку, коли досяжність ендпоінта та досяжність Сервісу не збігаються.
4.3 Conntrack — це прихований стан, а не магія
Розділ «4.3 Conntrack — це прихований стан, а не магія»Conntrack записує стан потоку, щоб NAT можна було коректно обернути, а пакети розпізнати як частину наявного з’єднання. Цей стан критичний, але він може створювати заплутані збої під час мінливості бекендів, змін політики чи навантаження на вузол. Нові з’єднання можуть працювати, тоді як старі з’єднання зависають, бо вони прив’язані до різних записів conntrack.
# Count current conntrack entries on a node.conntrack -C
# Inspect entries for a specific Service IP when debugging NAT behavior.conntrack -L -d <service-cluster-ip> 2>/dev/null
# Delete only targeted stale entries when you understand the impact.conntrack -D -d <service-cluster-ip> -p tcp --dport <service-port>Будьте обережні з широким видаленням записів conntrack у виробництві. Очищення надто великого обсягу стану може зламати активні з’єднання для непов’язаних робочих навантажень і створити новий інцидент, поки ви намагаєтеся розв’язати старий. У навчальному середовищі цільове видалення корисне, бо показує, як NAT Сервісу залежить від стану, але у виробництві його слід поєднувати з контекстом інциденту та контролем змін.
4.4 Захоплення пакетів підтверджує історію
Розділ «4.4 Захоплення пакетів підтверджує історію»Захоплення пакетів — це не перша команда, яку ви запускаєте, але вона чудова, коли тести рівнів суперечать один одному або коли вам потрібен доказ. Захоплення може показати, чи SYN залишає клієнтський Под, чи вузол переписує призначення, чи пакет перетинає тунель і чи повертається відповідь. Хитрість у тому, щоб захоплювати в точці, яка відповідає вашому питанню.
Якщо ви захоплюєте лише всередині клієнтського Пода, ви бачите те, що бачить застосунок до DNAT Сервісу. Якщо ви захоплюєте на вузлі з -i any, ви можете побачити як вид до трансляції, так і після неї, залежно від гачка та часу інтерфейсу. Якщо ви захоплюєте на тунельному інтерфейсі, ви можете перевірити, чи входить трафік в оверлейний шлях. Жоден із цих видів не є універсально найкращим; кожен відповідає на інше питання.
# From a debug pod, generate a request with a short timeout.kubectl exec <client-pod> -- curl -sS --connect-timeout 5 http://<service-name>:<port>
# On a node, capture packets related to a client and backend test.tcpdump -i any -nn host <client-pod-ip> and port <port>
# For DNS specifically, capture DNS packets rather than app packets.tcpdump -i any -nn port 53 and host <client-pod-ip>Захоплення найсильніше, коли поєднане з передбаченням. Перш ніж запускати tcpdump, запишіть, що ви очікуєте побачити, якщо DNS зламано, якщо DNAT Сервісу зламано, якщо політика відкидає потік ендпоінта чи якщо бекенд-застосунок не слухає. Потім порівняйте захоплення з вашим передбаченням. Ця звичка перетворює tcpdump зі стіни пакетів на доказ.
Частина 5: Міжвузлові збої, MTU та ідентичність джерела
Розділ «Частина 5: Міжвузлові збої, MTU та ідентичність джерела»Міжвузлові збої заслуговують на власний розділ, бо вони часто проходять базові тести на тому самому вузлі. Планування Kubernetes може ховати ці збої, доки викочування не перенесе Поди на різні вузли. Сервіс може здаватися нестабільним лише тому, що деякі пари «клієнт–бекенд» локальні, а інші перетинають мережу вузлів.
Перше міжвузлове питання — чи залежить збій від розміру. Якщо крихітні запити працюють, а більші відповіді зависають, підозрюйте MTU перш ніж випадкову поведінку застосунку. Інкапсуляція споживає байти для зовнішніх заголовків, тож MTU інтерфейсу Пода має враховувати менший ефективний шлях. Якщо пакет не можна фрагментувати або фрагментацію заблоковано, великі пакети можуть зникати у спосіб, що виглядає як тайм-аути.
# Check pod interface MTU from inside a pod.kubectl exec <pod-name> -- ip link show eth0
# Check common node interfaces and tunnel devices.ip link showip link show | grep -E "mtu|vxlan|geneve|tunl|flannel|cilium"Друге питання — чи дозволяє підлегла мережа (underlay) трафік CNI. Оверлейні режими потребують міжвузлового трафіку для протоколу інкапсуляції, тоді як нативна маршрутизація потребує, щоб мережа знала маршрути CIDR Подів. Хмарні групи безпеки, брандмауери вузлів, брандмауери хостів та ACL фізичної мережі — усе це може зламати інакше коректну конфігурацію Kubernetes.
Третє питання — чи змінилася ідентичність джерела. Трафік NodePort та LoadBalancer може зазнавати source-NAT, а NetworkPolicy зіставляє мітки й простори імен Подів, а не ідентичність зовнішнього клієнта. Бекенд, який раптом бачить IP вузлів замість IP клієнтів, може взагалі не мати збою маршрутизації; у нього може бути проблема політики трафіку чи проєкту ingress.
| Підказка про міжвузловий збій | Найкорисніша наступна перевірка | Чому це важливо | Поширений напрямок виправлення |
|---|---|---|---|
| На тому самому вузлі працює, між вузлами — ні | Порівняйте розміщення Подів за вузлами через kubectl get pods -o wide | Підтверджує, що межа вузла є змінною | Перевірте справність CNI, маршрути, брандмауери та тунелі |
| Малі відповіді працюють, великі — ні | Порівняйте MTU на інтерфейсах Пода й тунелю | Інкапсуляція може зменшити придатний розмір пакета | Налаштуйте MTU CNI та безпечно перезапустіть мережеві агенти |
| Бекенд NodePort бачить IP вузла | Перевірте externalTrafficPolicy | SNAT може бути очікуваною поведінкою | Використовуйте Local, лише коли розміщення ендпоінтів це підтримує |
| Лише один вузол не пропускає трафік Сервісу | Перевірте kube-proxy та агента CNI на цьому вузлі | Програмування правил на локальному вузлі може бути застарілим | Перезапустіть чи відремонтуйте агента ураженого вузла після діагностики |
| Прямий IP Пода зазнає невдачі лише в один бік | Захопіть обидва напрямки та перевірте політику | Асиметрична політика чи маршрути можуть ламати відповіді | Виправте зворотний шлях, вибір політики чи анонсування маршрутів |
| DNS отримує тайм-аут лише на деяких вузлах | Перевірте розміщення ендпоінтів CoreDNS та шлях вузла | DNS — це теж потік через Сервіс | Порівняйте трансляцію Сервісу kube-dns та досяжність Подів |
Тепер ви маєте достатньо повну модель, щоб діагностувати без запам’ятовування кожної реалізації плагіна. Почніть із доведення того, де шлях пакета перестає відповідати очікуванням. Потім оберіть інструмент, що бачить цю частину шляху, чи то nslookup, EndpointSlices, правила kube-proxy, conntrack, маршрути, MTU інтерфейсу, специфічні для CNI команди стану чи захоплення пакетів.
Патерни та антипатерни
Розділ «Патерни та антипатерни»Гарна діагностика мережі Kubernetes виглядає дисциплінованою, бо кожен тест прибирає гілку з дерева пошуку. Найсильніший патерн — тримати обіцянку площини управління окремо від доказу площини даних: DNS відповідає на імена, Сервіси обирають готові ендпоінти, kube-proxy чи заміна на eBPF транслює віртуальні IP, а CNI рухає пакети Подів. Коли ці обов’язки залишаються окремими у ваших нотатках, ви менш імовірно перезапустите CoreDNS заради проблеми селектора Сервісу чи зміните налаштування CNI заради порожнього EndpointSlice.
Другий корисний патерн — порівнювати два шляхи, які відрізняються рівно на один рівень. Виклик через Сервіс та прямий виклик ендпоінт-Пода відрізняються здебільшого трансляцією Сервісу; прямий виклик Пода на тому самому вузлі та прямий виклик Пода між вузлами відрізняються здебільшого міжвузловим шляхом CNI; короткий зовнішній DNS-запит та те саме ім’я з кінцевою крапкою відрізняються розширенням пошуку резолвера. Саме таке парне порівняння — це те, як досвідчені інженери перетворюють розпливчастий тайм-аут на конкретну наступну команду.
| Патерн | Коли його застосовувати | Чому він працює | Міркування щодо масштабування |
|---|---|---|---|
| «Прогулянка» пакета за рівнями | Будь-який інцидент зв’язності Сервісу чи Пода | Він розділяє DNS, вибір Сервісу, трансляцію, політику, CNI та поведінку застосунку | Стандартизуйте послідовність у ранбуках, щоб команди збирали порівнянні докази |
| Парне порівняння шляхів | Симптоми різняться за розміщенням вузлів, формою імені чи Сервісом проти IP Пода | Він ізолює один рівень, що змінився між тестами | Записуйте IP Подів, імена вузлів та готовність ендпоінтів, щоб порівняння були відтворюваними |
| Діагностика Сервісу «спершу ендпоінти» | Сервіс існує, але трафік зазнає невдачі | Він доводить, чи має kube-proxy реальні бекенди для трансляції | Надавайте перевагу EndpointSlices у великих кластерах, бо це масштабований API ендпоінтів |
| Цільова перевірка стану вузла | Доказ вказує на один вузол чи один VIP Сервісу | Він уникає широких захоплень пакетів та широкого видалення conntrack | Обмежте перевірку одним вузлом, одним IP Сервісу та одним портом, перш ніж змінювати стан |
Антипатерни зазвичай постають із сприйняття «мережі» як одного великого компонента. Перезапуск кожного мережевого Пода може ненадовго приховати симптом, але він знищує докази й може створити ширший збій. Краща реакція — використати найменший тест, який може спростувати гіпотезу, а потім спускатися на один рівень глибше лише тоді, коли попередній рівень поводиться як очікувано.
| Антипатерн | Що йде не так | Краща альтернатива |
|---|---|---|
| Перезапуск CoreDNS щоразу, коли ім’я Сервісу зазнає невдачі | DNS може бути справним, тоді як трансляція Сервісу kube-dns, політика egress чи шлях бекенд-Сервісу зламано | Перевірте nslookup, ендпоінти kube-dns та політику egress для DNS окремо, перш ніж щось перезапускати |
| Сприйняття збою прямого IP Пода як помилки kube-proxy | kube-proxy не відповідає за створення інтерфейсів Подів чи міжвузлову маршрутизацію Подів | Налагоджуйте справність CNI, NetworkPolicy, маршрути, MTU та брандмауери вузлів, коли пряма досяжність ендпоінта зазнає невдачі |
| Очищення всіх записів conntrack, щоб «розблокувати» Сервіс | Активні непов’язані потоки можуть перерватися, а оригінальна причина залишиться невідомою | Перевіряйте цільові записи для IP Сервісу й видаляйте лише обмежені записи в контрольованих ситуаціях |
| Припущення, що оверлейні та нативно-маршрутизовані кластери зазнають збоїв однаково | Інкапсуляція, MTU, правила брандмауеру, поширення маршрутів та інструменти спостережуваності різняться | Оцініть налаштований режим CNI, перш ніж обирати перевірки MTU, маршрутів чи тунелів |
Рамка прийняття рішень
Розділ «Рамка прийняття рішень»Використовуйте цю рамку, коли клієнтський Под не може дістатися до бекенда за іменем Сервісу. Читайте її згори донизу й зупиняйтеся, щойно доказ ідентифікує рівень. Якщо пізніша команда видається спокусливою, запитайте, чи вже доведено справність попереднього рівня; ця звичка тримає робочий процес швидким під час іспиту й обґрунтованим під час інциденту.
+----------------------------------------------------------------------------+| Service Connectivity Decision Framework || || 1. Resolve name from client pod || fails -> inspect resolver config, DNS policy, kube-dns Service, CoreDNS || works -> record the returned ClusterIP and continue || || 2. Inspect Service and EndpointSlices || empty -> fix selector, namespace, readiness, or target workload health || ready -> compare Service access with direct endpoint access || || 3. Compare Service call with endpoint pod-IP call || endpoint fails -> inspect NetworkPolicy, CNI, routes, MTU, node path || endpoint works -> inspect Service port, kube-proxy or eBPF translation || || 4. Add node context only after the layer tests justify it || one node bad -> inspect that node's agent, rules, routes, conntrack || cross-node bad -> inspect tunnel, BGP, firewall, or MTU evidence |+----------------------------------------------------------------------------+| Точка рішення | Доказ, що рухає вас уперед | Найімовірніший наступний інструмент | Чого ще не варто робити |
|---|---|---|---|
| Розв’язання DNS зазнає невдачі | Клієнт не може отримати очікуваний ClusterIP | kubectl exec -- nslookup, логи CoreDNS, перегляд політики DNS | Не перевіряйте логи застосунку як основний доказ шляху |
| EndpointSlices порожні | Сервіс не має готових бекенд-адрес | kubectl describe svc, kubectl get pods --show-labels, події готовності | Не налагоджуйте iptables для Сервісу без ендпоінтів |
| Прямий доступ до ендпоінта зазнає невдачі | Шлях мережі Подів чи політика зазнають невдачі без трансляції Сервісу | Перегляд NetworkPolicy, стан CNI, перевірки маршрутів і MTU, захоплення пакетів | Не припускайте, що kube-proxy зламано |
| Прямий ендпоінт працює, але Сервіс зазнає невдачі | Нижча досяжність Подів доведена, але трансляція віртуального IP підозріла | Перегляд порту Сервісу, логи kube-proxy, nftables чи iptables, conntrack | Не змінюйте MTU CNI, поки не доведено симптоми, залежні від розміру при міжвузловій передачі |
| Зазнають невдачі лише більші міжвузлові навантаження | Крихітні зонди успішні, тоді як більші потоки отримують тайм-аут | Порівняння MTU та контрольовані тести з різним розміром пакетів | Не сприймайте тайм-аут застосунку як випадковий без доказу про розмір |
Чи знали ви?
Розділ «Чи знали ви?»-
kube-proxy зазвичай програмує шлях даних, а не сам несе пакети з даними. У поширених режимах Linux kube-proxy спостерігає за Сервісами та EndpointSlices, записує правила ядра чи еквівалентний стан і дозволяє ядру пересилати пакети, що збігаються.
-
Пошуки DNS для Сервісів Kubernetes самі є трафіком через Сервіс. Под зазвичай надсилає DNS-запити до ClusterIP kube-dns, а це означає, що зламана трансляція Сервісу може виглядати як збій DNS, навіть коли Поди CoreDNS справні.
-
Оверлейна інкапсуляція змінює придатний розмір пакета. Шлях, який працював із нативною маршрутизацією, може почати відкидати більші навантаження після ввімкнення оверлейного режиму, якщо MTU Пода та накладні витрати тунелю не сплановано разом.
-
Под у стані Running не є автоматично ендпоінтом Сервісу. Сервіси маршрутизують лише до готових ендпоінтів, тож невдала перевірка готовності може створити порожній набір ендпоінтів, навіть коли кожен обраний Под здається живим.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому вона виникає | Як її виправити |
|---|---|---|
| Почати з tcpdump перед перевіркою DNS та ендпоінтів | Захоплення пакетів стають галасливими, коли несправний рівень не звужено | Спершу перевірте розв’язання імен, ендпоінти Сервісу та пряму досяжність за IP Пода |
| Сприйняття kube-proxy як компонента, що створює мережу Подів | Досліджується неправильний власник, коли трафік за прямим IP Пода зазнає невдачі | Використовуйте прямі тести за IP Пода, щоб відокремити досяжність CNI від трансляції Сервісу |
| Припущення, що бекенд-Под у стані Running придатний для трафіку Сервісу | Невдала готовність прибирає Поди з EndpointSlices, навіть поки контейнери запущені | Перевіряйте EndpointSlices, стан готовності та селектори Сервісу разом |
| Ігнорування NetworkPolicy під час прямих тестів за IP Пода | Заборонений потік може виглядати як зламаний маршрут чи тунель | Перевірте політики, що обирають простір імен клієнта та бекенд-Поди, перш ніж змінювати налаштування CNI |
| Забути, що DNS використовує шлях через Сервіс | Поди CoreDNS можуть бути справними, тоді як ClusterIP kube-dns недосяжний | Перевіряйте справність Подів CoreDNS та трансляцію Сервісу kube-dns окремо |
| Пропущений MTU після ввімкнення оверлейної мережі | Малі зонди проходять, тоді як більші відповіді зависають або отримують тайм-аут | Порівнюйте MTU Пода, MTU тунелю та MTU підлеглої мережі щоразу, коли змінюється інкапсуляція |
| Очищення всього стану conntrack під час інциденту | Широке видалення порушує непов’язані активні з’єднання | Перевіряйте та видаляйте лише цільові записи, коли застарілий стан NAT сильно ймовірний |
Використання externalTrafficPolicy: Local без балансування навантаження з урахуванням ендпоінтів | Вузли без локального готового ендпоінта відкидають трафік, зберігаючи IP джерела | Поєднуйте Local із перевірками справності та плануванням, що тримає ендпоінти на вузлах, які отримують трафік |
Тест
Розділ «Тест»1. Ваша команда повідомляє, що checkout не може викликати http://inventory, але kubectl exec checkout -- nslookup inventory повертає очікуваний ClusterIP. Сервіс має два готові EndpointSlices, і прямий wget до одного IP ендпоінт-Пода успішний із Пода checkout. Який рівень тепер найбільш підозрілий і що ви перевірите далі?
Відповідь
Найсильніша підозра — це шлях трансляції Сервісу або конфігурація порту Сервісу, а не DNS і не базова досяжність CNI. DNS розв’язав ім’я, EndpointSlices містять готові бекенди, а прямий доступ за IP Пода з клієнта доводить, що мережа Подів може дістатися щонайменше до одного бекенда. Перевірте порт Сервісу та targetPort, справність kube-proxy на вузлі клієнта, правила Сервісу на вузлі на кшталт iptables чи nftables та цільові записи conntrack для ClusterIP Сервісу.
2. Кластер переходить від нативної маршрутизованої мережі Подів до оверлейного режиму. Запити на тому самому вузлі досі працюють, міжвузлові запити з малими навантаженнями працюють, але міжвузлові запити з більшими відповідями JSON отримують тайм-аут. Який імовірний механізм і як команда платформи має його підтвердити, перш ніж змінювати конфігурацію?
Відповідь
Імовірний механізм — невідповідність MTU, спричинена накладними витратами інкапсуляції. Трафік на тому самому вузлі не використовує міжвузловий тунель, а малі пакети можуть поміститися навіть тоді, коли ефективний MTU шляху завеликий для більших відповідей. Команда має порівняти MTU інтерфейсу Пода, MTU тунельного інтерфейсу та MTU підлеглої мережі, а потім використати контрольовані тести з різним розміром пакетів чи захоплення пакетів, щоб підтвердити, що великі пакети зникають на міжвузловому шляху. Після підтвердження налаштуйте MTU CNI відповідно до обраного оверлейного режиму та контрольовано перезапустіть мережеві агенти.
3. Розробник створює Сервіс для reports, і DNS повертає ClusterIP, але kubectl get endpoints reports не показує адрес. Обрані Поди в стані Running і мають очікувані мітки. Що слід оцінити, перш ніж перевіряти правила kube-proxy?
Відповідь
Оцініть готовність та узгодження простору імен, перш ніж перевіряти правила kube-proxy. Поди в стані Running не додаються до EndpointSlices, доки вони не готові (Ready), тож невдала перевірка готовності може залишити Сервіс без придатних бекендів. Також підтвердьте, що Сервіс і Поди в тому самому просторі імен, і порівняйте точний селектор за допомогою kubectl describe svc reports та kubectl get pods --show-labels. kube-proxy не може маршрутизувати Сервіс до ендпоінтів, які Kubernetes API не позначає готовими.
4. Сервіс контролера Ingress використовує externalTrafficPolicy: Local, щоб зберегти IP клієнтів. Після викочування деякі вузли досі отримують трафік балансувальника навантаження, але не мають локальних Подів ingress, а клієнти бачать періодичні збої. Чому це відбувається і яку зміну проєкту ви б порекомендували?
Відповідь
З externalTrafficPolicy: Local вузол має пересилати зовнішній трафік лише до локальних готових ендпоінтів. Якщо балансувальник навантаження надсилає трафік на вузол без локального ендпоінта, вузол не може зберегти IP джерела й переслати до віддаленого бекенда у звичайній моделі Local, тож з’єднання може зазнати невдачі. Проєкт має поєднувати Local із перевірками справності балансувальника навантаження, які націлені лише на вузли з локальними ендпоінтами, або планувати Поди ingress так, щоб кожен вузол, що отримує трафік, мав готовий локальний ендпоінт. Якщо збереження IP клієнта не потрібне, Cluster може бути простішим.
5. Простір імен має політику egress NetworkPolicy з типовою забороною. Застосунки можуть під’єднуватися до IP бекенд-Подів, дозволених політикою, але всі виклики з використанням імен Сервісів зазнають невдачі до початку TCP-з’єднання. Яку конкретну залежність політика, імовірно, забула, і як би ви це довели?
Відповідь
Політика, імовірно, забула дозволити egress для DNS до CoreDNS, зазвичай порт 53 UDP та TCP до DNS-Подів kube-system чи шляху Сервісу kube-dns, залежно від того, як написана політика. Доведіть це, запустивши nslookup kubernetes.default чи FQDN Сервісу з ураженого Пода, перевіривши /etc/resolv.conf на наявність nameserver та переглянувши політики, що обирають клієнтський Под. Якщо пряма зв’язність за IP Пода працює, а розв’язання імені зазнає невдачі, збій у досяжності DNS, а не в самому бекенд-Сервісі.
6. Сервіс працює з Подів на Вузлі A, але зазнає невдачі з Подів на Вузлі B. EndpointSlices коректні, а прямі тести за IP Пода від клієнтів на Вузлі B до віддалених бекендів зазнають невдачі, тоді як прямі тести до бекендів на тому самому вузлі успішні. Який доказ ви б зібрали далі й чому?
Відповідь
Зберіть розміщення вузлів, справність агента CNI на Вузлі B, маршрути, тунельні інтерфейси, правила брандмауеру вузла та захоплення пакетів на межі вузла. Успіх на тому самому вузлі доводить, що локальна мережа Подів та застосунок можуть працювати, тоді як невдача прямого віддаленого IP Пода вказує нижче за kube-proxy — на міжвузловий шлях CNI чи політику. Корисний доказ — це чи залишають пакети Вузол B, чи входять вони в очікуваний тунель чи маршрут, чи прибуває зворотний трафік і чи якась політика чи брандмауер забороняють міжвузловий потік.
7. Після викочування бекенда нові з’єднання через Сервіс успішні, але частина довготривалих клієнтських з’єднань зависає, доки вони повторно не під’єднаються. Поди готові, DNS у порядку, а Сервіс має ендпоінти. Який прихований стан міг би пояснити різницю між новими та старими з’єднаннями?
Відповідь
Стан conntrack міг би пояснити різницю. Наявні потоки можуть залишатися прив’язаними до старих відображень NAT, тоді як нові потоки отримують свіжий вибір ендпоінта та свіжі записи відстеження з’єднань. Правильне дослідження — перевірити цільові записи conntrack для ClusterIP та порту Сервісу, скорелювати уражених клієнтів із часом викочування й використати плавне завершення (graceful termination) чи зливання з’єднань (connection draining), щоб зменшити вплив застарілих потоків. Цільове видалення conntrack може допомогти в лабораторії чи контрольованому інциденті, але широке видалення може порушити непов’язані з’єднання.
Практична вправа: випробування з трасування пакетів
Розділ «Практична вправа: випробування з трасування пакетів»Мета: простежити шлях запиту від клієнтського Пода через DNS, вибір Сервісу, трансляцію Сервісу, conntrack та доставку до Пода. Ви використаєте модель діагностики з Частини 4, перш ніж застосовувати низькорівневі інструменти, тож вправа практикує ту саму послідовність, якої навчає модуль.
Середовище: кластера kind чи minikube достатньо для основної вправи. Багатовузловий кластер кращий для необов’язкових міжвузлових спостережень, але обов’язкові кроки працюють на одновузловому кластері розробки.
Підготовка
Розділ «Підготовка»Створіть бекенд-Деплоймент, відкрийте його через Сервіс та створіть довготривалий налагоджувальний Под. Налагоджувальний образ містить інструменти, зручніші за мінімальний образ застосунку, що тримає вправу зосередженою на шляху даних, а не на встановленні пакетів.
# Create a backend deployment and expose it with a ClusterIP Service.kubectl create deployment trace-backend --image=nginx --replicas=2kubectl expose deployment trace-backend --port=80 --name=trace-svc
# Wait until both backend pods are ready and therefore eligible as endpoints.kubectl wait --for=condition=ready pod -l app=trace-backend --timeout=90s
# Create a debug client with networking tools.kubectl run trace-client --image=nicolaka/netshoot --restart=Never -- sleep 3600kubectl wait --for=condition=ready pod/trace-client --timeout=90s
# Capture the objects you will inspect throughout the exercise.kubectl get pods -o widekubectl get svc trace-svc -o widekubectl get endpointslice -l kubernetes.io/service-name=trace-svc -o wideКрок 1: тестуйте DNS перед транспортом
Розділ «Крок 1: тестуйте DNS перед транспортом»Почніть з імені, бо реальні застосунки зазвичай починають саме там. Розв’яжіть коротке ім’я, потім розв’яжіть повне доменне ім’я й порівняйте результат із ClusterIP Сервісу. Якщо ці значення не збігаються, зупиніться й виправте проблему DNS чи простору імен, перш ніж продовжувати.
# Inspect resolver settings inside the client pod.kubectl exec trace-client -- cat /etc/resolv.conf
# Resolve the short Service name from the default namespace.kubectl exec trace-client -- nslookup trace-svc
# Resolve the fully qualified name to remove search-domain ambiguity.kubectl exec trace-client -- nslookup trace-svc.default.svc.cluster.local
# Compare against the Service ClusterIP.kubectl get svc trace-svc -o jsonpath='{.spec.clusterIP}{"\n"}'Запишіть ClusterIP Сервісу й напишіть одне речення, яке пояснює, чи DNS спрацював. Правильна відповідь має відокремлювати розв’язання DNS від зв’язності застосунку, бо успішний пошук не доводить, що працює шлях Сервісу чи бекенд-застосунок.
Крок 2: перевірте вибір Сервісу
Розділ «Крок 2: перевірте вибір Сервісу»Тепер перевірте, чи має Сервіс готові ендпоінти. Кількість адрес ендпоінтів має збігатися з кількістю готових бекенд-Подів, а не просто з кількістю створених реплік. Якщо Сервіс не має ендпоінтів, перевірте мітки й готовність, перш ніж торкатися конфігурації kube-proxy чи CNI.
# Show Service selector and ports.kubectl describe svc trace-svc
# Show endpoint addresses selected by the Service.kubectl get endpoints trace-svckubectl get endpointslice -l kubernetes.io/service-name=trace-svc -o wide
# Show backend readiness, labels, pod IPs, and node placement.kubectl get pods -l app=trace-backend -o wide --show-labelsЗапишіть, скільки адрес ендпоінтів існує і які IP бекенд-Подів вони представляють. Потім поясніть, чи має запит через Сервіс мати дійсну бекенд-ціль згідно зі станом Kubernetes API.
Крок 3: порівняйте доступ через Сервіс із прямим доступом до ендпоінта
Розділ «Крок 3: порівняйте доступ через Сервіс із прямим доступом до ендпоінта»Цей крок ізолює трансляцію Сервісу від прямої досяжності Пода. Спершу викличте Сервіс за іменем, потім викличте один IP ендпоінт-Пода безпосередньо. Якщо обидва працюють, базовий шлях справний. Якщо прямий доступ до ендпоінта працює, а доступ через Сервіс зазнає невдачі, перевірте трансляцію Сервісу. Якщо прямий доступ до ендпоінта зазнає невдачі, перевірте політику, CNI, маршрут чи бекенд-застосунок.
# Call the Service by name from the client pod.kubectl exec trace-client -- curl -sS --connect-timeout 5 http://trace-svc
# Pick one endpoint IP and call it directly.ENDPOINT_IP="$(kubectl get pod -l app=trace-backend -o jsonpath='{.items[0].status.podIP}')"kubectl exec trace-client -- curl -sS --connect-timeout 5 "http://${ENDPOINT_IP}"Запишіть результат обох викликів. Ваше пояснення має ідентифікувати, який рівень був би найбільш підозрілим, якби виклик через Сервіс зазнав невдачі, тоді як виклик до ендпоінта успішний, і який рівень був би найбільш підозрілим, якби обидва виклики зазнали невдачі.
Крок 4: перевірте трансляцію Сервісу на вузлі
Розділ «Крок 4: перевірте трансляцію Сервісу на вузлі»Використовуйте перевірку на рівні вузла лише після того, як ви довели, що Сервіс та ендпоінти існують. У kind вузол — це контейнер Docker, тож docker exec дозволяє перевірити мережевий стан вузла. У minikube використовуйте minikube ssh для еквівалентного виду вузла.
# kind: inspect Service-related iptables rules on the control-plane node.docker exec kind-control-plane iptables-save | grep -E "trace-svc|KUBE-SVC|KUBE-SEP" | head -60
# minikube alternative:# minikube ssh "sudo iptables-save | grep -E 'trace-svc|KUBE-SVC|KUBE-SEP' | head -60"Шукайте правила, що з’єднують шлях Сервісу з адресами бекенд-ендпоінтів. Вам не потрібно запам’ятовувати кожну згенеровану назву ланцюжка; вам потрібно розпізнати, що трафік Сервісу транслюється на IP та порти ендпоінт-Подів.
Крок 5: спостерігайте за захопленням пакетів
Розділ «Крок 5: спостерігайте за захопленням пакетів»Запустіть захоплення пакетів на вузлі, генеруючи один запит із клієнтського Пода. Захоплення на any є широким, але воно корисне для навчання, бо ви можете бачити пакети на кількох інтерфейсах. Під час виробничого інциденту ви звузили б захоплення після того, як вирішили, який інтерфейс відповідає на ваше питання.
# In one terminal, start a capture filtered to the client pod and HTTP port.CLIENT_IP="$(kubectl get pod trace-client -o jsonpath='{.status.podIP}')"docker exec kind-control-plane tcpdump -i any -nn "host ${CLIENT_IP} and port 80"
# In another terminal, generate one request.kubectl exec trace-client -- curl -sS --connect-timeout 5 http://trace-svcПерш ніж зупинити захоплення, визначте, чи бачите ви IP клієнтського Пода, IP Сервісу та IP бекенд-Пода. Залежно від часу та інтерфейсу ви можете не побачити кожен ракурс в одному захопленні, але ви маєте змогти пов’язати побачене з «прогулянкою» пакета з Частини 1.
Крок 6: перевірте conntrack для потоку Сервісу
Розділ «Крок 6: перевірте conntrack для потоку Сервісу»Перевірку conntrack найлегше робити одразу після генерування трафіку. Точний вивід різниться залежно від ядра та образу кластера, але ви шукаєте стан потоку, пов’язаний із ClusterIP Сервісу, IP клієнтського Пода, IP бекенд-Пода та портом призначення.
# Get the ClusterIP and inspect matching conntrack entries on a kind node.SVC_IP="$(kubectl get svc trace-svc -o jsonpath='{.spec.clusterIP}')"docker exec kind-control-plane conntrack -L -d "${SVC_IP}" 2>/dev/null || true
# If no entries appear, generate several requests and try again.for i in 1 2 3 4 5; do kubectl exec trace-client -- curl -sS --connect-timeout 5 http://trace-svc >/dev/nulldonedocker exec kind-control-plane conntrack -L -d "${SVC_IP}" 2>/dev/null || trueПоясніть, що conntrack робить для цього потоку. Сильна відповідь згадує, що призначення Сервісу переписується на бекенд-ендпоінт, а conntrack запам’ятовує відображення NAT, щоб трафік відповіді можна було пов’язати з оригінальним з’єднанням клієнта.
Крок 7: введіть збій через NetworkPolicy
Розділ «Крок 7: введіть збій через NetworkPolicy»Тепер створіть контрольований збій, який блокує ingress до бекенд-Подів. Це дозволяє попрактикуватися в розрізненні успіху DNS від транспортного збою. Ім’я Сервісу досі має розв’язуватися, бо політика обирає бекенд-Поди, а не CoreDNS, але HTTP-запит має зазнати невдачі, бо ingress до бекенда заборонено.
cat <<'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-trace-backendspec: podSelector: matchLabels: app: trace-backend policyTypes: - Ingress ingress: []EOF
# DNS should still resolve the Service name.kubectl exec trace-client -- nslookup trace-svc
# HTTP should fail or time out because backend ingress is denied.kubectl exec trace-client -- curl -sS --connect-timeout 5 http://trace-svc || true
# Direct endpoint access should also fail because the policy blocks backend ingress.ENDPOINT_IP="$(kubectl get pod -l app=trace-backend -o jsonpath='{.items[0].status.podIP}')"kubectl exec trace-client -- curl -sS --connect-timeout 5 "http://${ENDPOINT_IP}" || trueВикористайте трирівневу модель, щоб пояснити збій. DNS досі працює, Сервіс досі має ендпоінти, а прямий тест ендпоінта зазнає невдачі, тож доказ вказує на політику чи застосування CNI, а не на kube-proxy.
Крок 8: відновіть зв’язність та приберіть за собою
Розділ «Крок 8: відновіть зв’язність та приберіть за собою»Видаліть політику, переконайтеся, що Сервіс знову працює, і видаліть ресурси вправи. Прибирання важливе, бо залишені політики та налагоджувальні Поди можуть несподівано змінити майбутні мережеві тести.
# Remove the controlled failure.kubectl delete networkpolicy deny-trace-backend
# Verify connectivity is restored.kubectl exec trace-client -- curl -sS --connect-timeout 5 http://trace-svc
# Cleanup exercise resources.kubectl delete pod trace-client --force --grace-period=0kubectl delete deployment trace-backendkubectl delete svc trace-svcКритерії успіху:
- Ви можете визначити ClusterIP Сервісу, повернутий DNS, і пояснити, чому успіх DNS не доводить успіх HTTP.
- Ви можете перевірити, що Сервіс має готові ендпоінти, перевіривши EndpointSlices чи Endpoints.
- Ви можете порівняти запит через Сервіс із прямим запитом за IP ендпоінт-Пода й визначити, який рівень ізолює це порівняння.
- Ви можете знайти доказ трансляції Сервісу на рівні вузла для Сервісу вправи в iptables чи еквівалентному наборі правил для режиму вашого кластера.
- Ви можете спостерігати доказ у пакетах за допомогою tcpdump і пов’язати захоплення з «прогулянкою» пакета з Частини 1.
- Ви можете перевірити чи обґрунтувати записи conntrack для потоку Сервісу, не сприймаючи conntrack як чорну скриньку.
- Ви можете пояснити, чому збій через NetworkPolicy блокує бекенд-трафік, тоді як розв’язання DNS досі працює.
- Ви можете застосувати відтворювану ментальну модель діагностики до конкретного випробування з трасування пакетів, замість того щоб перестрибувати між непов’язаними командами.
- Ви можете сформулювати порядок діагностики: DNS, вибір Сервісу, пряма досяжність ендпоінта, політика чи CNI, потім стан на рівні вузла.
Джерела
Розділ «Джерела»- Virtual IPs and Service Proxies — Підкріплює обов’язки kube-proxy, реалізацію ClusterIP Сервісу, спостереження за EndpointSlice та твердження про шлях даних щодо перезапису пакетів у мережі сервісів, керованій kube-proxy.
- Virtual IPs and Service Proxies — Канонічний довідник щодо поведінки kube-proxy, віртуальних IP Сервісу, політик трафіку та режимів проксі в Linux.
- Cluster Networking — Пояснює мережеву модель Kubernetes та обов’язки щодо IP Подів, сервісів та вузлів, які стоять за шляхом даних кластера.
- DNS for Services and Pods — Охоплює DNS-записи Сервісів, конфігурацію резолвера Пода, домени пошуку та поведінку DNS, розглянуту в модулі.
- Using Source IP — Показує, як source NAT та
externalTrafficPolicyвпливають на трафік NodePort та LoadBalancer на практиці. - Services, Load Balancing, and Networking — Визначає типи Сервісів, селектори, порти, поведінку віртуального IP та політики трафіку, що використовуються протягом усієї «прогулянки» пакета.
- EndpointSlices — Документує масштабований API ендпоінтів, за яким kube-proxy та його заміни спостерігають для отримання стану бекенда Сервісу.
- Network Policies — Пояснює, як CNI з підтримкою політик застосовують рішення ingress та egress, що можуть блокувати прямий трафік Подів чи DNS.
- Debug Services — Надає настанови Kubernetes з діагностики Сервісів, селекторів, ендпоінтів, DNS та правил проксі.
- CNI Specification — Визначає контракт інтерфейсу мережі контейнерів, який плагіни використовують для під’єднання мережевих інтерфейсів Подів та налаштування адрес.
- Cilium Kubernetes Without kube-proxy — Документація постачальника для площини даних Сервісу на eBPF, що замінює поведінку kube-proxy.
- Calico IP autodetection and node addressing — Документація постачальника, релевантна для маршрутизованої мережі Подів та вибору адреси вузла в кластерах Calico.
Наступний модуль
Розділ «Наступний модуль»Модуль 3.3: DNS у Kubernetes — Поглиблений розгляд конфігурації CoreDNS, користувацьких політик DNS та просунутої діагностики.