Новинка Виртуальный VDS сервер в Финляндии от 390р
Выберите продукт

Kubernetes Service и kube-proxy: ClusterIP, NodePort, LoadBalancer и отладка сетевых проблем

Разбираем, как kube-proxy реализует Kubernetes Service в режиме iptables, чем отличаются ClusterIP/NodePort/LoadBalancer и как быстро дебажить типовые симптомы: clusterIP unreachable, nodeport not working, пустые Endpoints и эффекты externalTrafficPolicy.
Kubernetes Service и kube-proxy: ClusterIP, NodePort, LoadBalancer и отладка сетевых проблем

Зачем вообще нужен Service и при чём тут kube-proxy

Pod’ы в Kubernetes живут недолго: пересоздаются, меняют IP, переезжают на другие ноды. Если ходить к Pod’ам напрямую по их IP, приложение развалится при первом же рескейле или рестарте. Поэтому в Kubernetes есть абстракция Service — стабильная точка входа (виртуальный IP и порт), за которой прячется динамический набор Pod’ов.

За «приземление» этой абстракции на реальные сетевые правила обычно отвечает kube-proxy. В большинстве кластеров он делает это, программируя правила на нодах: чаще всего через iptables (режим iptables), реже через IPVS (режим ipvs). Дальше фокус — на сценарии kube-proxy iptables, потому что именно там чаще всего приходится разбираться руками.

Важно: kube-proxy не является прокси в привычном смысле (не «слушает порт» и не форвардит трафик пользовательским процессом). Он настраивает dataplane (iptables/ipvs), чтобы пакеты, идущие на Service IP/порт, перенаправлялись на один из Pod’ов.

Три базовых типа Service: ClusterIP, NodePort, LoadBalancer

ClusterIP

ClusterIP — сервис доступен только внутри кластера. Kubernetes выделяет виртуальный IP из диапазона Service CIDR (например, 10.96.0.0/12), и весь трафик на этот IP перенаправляется на backend Pod’ы.

Типичный кейс: внутренние API, базы, кэши, микросервисы.

NodePort

NodePort — открывает порт на каждой ноде (обычно диапазон 30000-32767). При обращении к nodeIP:nodePort трафик попадает в Service и дальше — в Pod.

Типичный кейс: простой внешний доступ без облачного балансировщика, тестовые стенды, bare metal.

LoadBalancer

LoadBalancer — поверх Service появляется внешний балансировщик. В managed-кластерах это обычно интеграция с облачным LB. В on-prem/bare metal часто используют MetalLB или другие контроллеры. С точки зрения kube-proxy, LoadBalancer почти всегда опирается на механику NodePort/ClusterIP, а внешний балансировщик лишь доставляет трафик внутрь.

Схема потока трафика Kubernetes Service: ClusterIP, NodePort и LoadBalancer

Как kube-proxy «сшивает» Service с Pod’ами

У Service есть селектор (labels), по которому выбираются Pod’ы. По факту Kubernetes создаёт объект Endpoints (или EndpointSlice), где перечислены IP:port реальных backend’ов. kube-proxy смотрит на Endpoints и строит правила, чтобы трафик на Service уходил в один из этих адресов.

Базовая проверка, которую делают первой при отладке Service:

kubectl get svc -n NAMESPACE
kubectl describe svc SERVICE -n NAMESPACE
kubectl get endpoints SERVICE -n NAMESPACE -o wide
kubectl get endpointslice -n NAMESPACE -l kubernetes.io/service-name=SERVICE -o wide

Если у Service нет Endpoints, kube-proxy обычно не сможет направить трафик «в никуда». Это одна из самых частых причин симптома clusterip unreachable.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

kube-proxy и iptables: что именно он добавляет

В режиме iptables kube-proxy создаёт цепочки и правила NAT/фильтрации. На ноде можно увидеть «фирменные» цепочки вида KUBE-SERVICES, KUBE-NODEPORTS, KUBE-SVC-*, KUBE-SEP-*.

Диагностика на ноде (нужен root):

iptables -t nat -S | grep KUBE | head
iptables -t nat -S KUBE-SERVICES | head
iptables -t nat -S KUBE-NODEPORTS | head

На что смотреть:

  • есть ли правила для нужного Service (по ClusterIP:port и/или по NodePort);
  • есть ли привязка к цепочкам endpoint’ов (обычно KUBE-SEP-*), иначе трафик будет «проваливаться»;
  • не перехватывают ли пакеты другие правила (локальный firewall, политики безопасности, nftables-совместимость).

Если вы как раз упёрлись в нюансы совместимости, полезно держать под рукой шпаргалку по iptables/nftables на Linux: как читать правила iptables и где мешает nftables-обвязка.

Практика: быстрая шпаргалка для kubernetes service debug

Когда «сервис не открывается», важно разделить проблему по слоям: DNS, Service/Endpoints, kube-proxy dataplane, CNI/маршрутизация, firewall, приложение в Pod’е.

1) Проверяем, что backend вообще жив

Сначала убедитесь, что Pod слушает порт и readiness зелёный:

kubectl get pods -n NAMESPACE -o wide
kubectl describe pod POD -n NAMESPACE
kubectl logs -n NAMESPACE POD --tail=200

Если readiness probe не проходит, Pod не попадёт в Endpoints — Service будет пустым.

2) Проверяем Endpoints и соответствие селектора

kubectl get svc SERVICE -n NAMESPACE -o yaml
kubectl get endpoints SERVICE -n NAMESPACE -o yaml

Частая ошибка: селектор Service не совпадает с labels Pod’ов. Тогда Endpoints пустой, а вы получаете «как будто сеть сломалась».

3) Проверяем доступ к ClusterIP изнутри кластера

Запускаем временный Pod и тестируем:

kubectl run -n NAMESPACE netshoot --rm -it --image=nicolaka/netshoot -- sh

Внутри:

nslookup SERVICE
nc -vz SERVICE PORT
curl -sS -m 3 http://SERVICE:PORT/

Если DNS не резолвит — это уже история про CoreDNS. Если DNS резолвит, но ClusterIP не отвечает — смотрим Endpoints, kube-proxy и CNI.

4) Проверяем kube-proxy и его режим

kubectl -n kube-system get ds kube-proxy -o wide
kubectl -n kube-system logs ds/kube-proxy --tail=200

Полезно понять, что используется: iptables или ipvs. В логах kube-proxy обычно видно, какой proxier активен. Если ожидали iptables, а включён IPVS (или наоборот), диагностика будет другой.

Симптом: clusterip unreachable

Под «ClusterIP недоступен» обычно скрывается один из сценариев:

  • Нет Endpoints: селектор не совпал, readiness не проходит, Pod’ы не в Running.
  • kube-proxy не применил правила: kube-proxy не запущен на ноде, упал, конфликтует с nftables-режимом, проблемы с conntrack.
  • Проблема маршрутизации/overlay: CNI не поднялся, нет маршрутов между нодами, MTU/encapsulation, dropped пакеты.
  • NetworkPolicy режет трафик к Pod’ам.

Если Service существует, DNS резолвит имя в ClusterIP, но TCP connect зависает или получает timeout — чаще всего проблема не в DNS, а в цепочке Service → Endpoints → правила dataplane → достижимость Pod IP.

Минимальный план действий:

kubectl get endpoints SERVICE -n NAMESPACE -o wide
kubectl get pods -n NAMESPACE -o wide --show-labels
kubectl describe svc SERVICE -n NAMESPACE

Дальше — тест напрямую до Pod IP (минуя Service). Если Pod IP недоступен с другой ноды, это CNI/маршрутизация/политики, а не kube-proxy:

kubectl get pod POD -n NAMESPACE -o wide

Затем из netshoot:

nc -vz POD_IP POD_PORT

Симптом: nodeport not working

Когда nodeport not working, часто путают два разных «не работает»:

  • не доступно снаружи (ваша сеть/интернет) до nodeIP:nodePort;
  • внутри кластера NodePort тоже не открывается.

Если изнутри кластера NodePort работает, а снаружи нет — в большинстве случаев виноваты security group/ACL/iptables на нодах, маршрутизация до nodeIP или отсутствие публичного IP.

Проверка на ноде: слушать процесс NodePort не будет (это нормально), но правила должны быть:

iptables -t nat -S KUBE-NODEPORTS | grep NODEPORT

Ещё одна классика: NodePort открыт на всех нодах, но вы пытаетесь подключаться к ноде, которая недоступна извне (например, internal-only). Тогда корректнее использовать внешний LB или выносить точку входа на edge.

NodePort и health checks

Если вы используете внешний балансировщик (включая on-prem решения) поверх NodePort, проверьте, как он делает health check. Часто проверки приходят с адресов, которые попадают под ограничения firewall или не учтены в allowlist.

Просмотр цепочек iptables KUBE-SERVICES и KUBE-NODEPORTS на ноде Kubernetes

LoadBalancer: где заканчивается kube-proxy и начинается инфраструктура

Service типа LoadBalancer обычно создаёт:

  • ClusterIP (как базу);
  • часто — NodePort (как точку входа для внешнего LB);
  • объект статуса с внешним адресом.

kube-proxy отвечает за доставку трафика после того, как он попал на ноду (через NodePort или напрямую). А вот «попасть на ноду» — это уже зона ответственности облачного провайдера/MetalLB/вашей сети.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Endpoints и EndpointSlice: почему это важно в реальной отладке

Исторически Service опирался на объект Endpoints. В новых версиях активно используются EndpointSlice — это более масштабируемый вариант, особенно при большом количестве Pod’ов.

В отладке это полезно так:

  • Если Endpoints пустой, но EndpointSlice есть — проверьте версии компонентов и корректность контроллеров (обычно они синхронизированы, но в проблемных кластерах встречаются несостыковки).
  • Если в EndpointSlice адреса есть, но трафик не ходит — ищите проблему ниже: dataplane, CNI, политики.

ExternalTrafficPolicy: Local vs Cluster — что меняется и почему ломается доступ

Ключ externalTrafficPolicy (поле externalTrafficPolicy в Service) особенно важен для NodePort/LoadBalancer.

Два режима:

  • Cluster (по умолчанию): трафик, пришедший на ноду, может быть отправлен на Pod’ы на других нодах. Это повышает шанс успешной доставки, но часто «прячет» реальный клиентский IP (в зависимости от схемы и SNAT).
  • Local: трафик будет направлен только на Pod’ы, которые локально есть на той ноде, куда пришёл запрос. Клиентский IP сохраняется чаще, но появляется риск 503/timeout, если LB шлёт трафик на ноды без локальных endpoint’ов.

Если включили externalTrafficPolicy: Local и внезапно получили «частично не работает», проверьте: есть ли backend Pod’ы на каждой ноде, куда направляет трафик внешний балансировщик.

Что делать на практике:

kubectl describe svc SERVICE -n NAMESPACE | grep -i ExternalTrafficPolicy -n
kubectl get endpoints SERVICE -n NAMESPACE -o wide
kubectl get pods -n NAMESPACE -o wide

Если LB балансирует по всем нодам, а Pod’ы есть только на части — либо меняйте политику обратно на Cluster, либо настраивайте LB так, чтобы он слал трафик только на «здоровые» ноды, либо обеспечьте присутствие Pod’ов на всех нодах (DaemonSet/anti-affinity/реплики).

Частые причины «всё настроено, но всё равно не ходит»

Конфликт iptables и nftables

На современных дистрибутивах iptables может быть «обёрткой» над nftables. В некоторых комбинациях версий ядра/iptables/nft и Kubernetes-компонентов возникают странные эффекты: правила как будто есть, но трафик не соответствует ожиданиям. Если вы подозреваете это, зафиксируйте, какой backend используется:

update-alternatives --display iptables

И проверьте, что в кластере выбран поддерживаемый путь для вашей версии Kubernetes и ОС. Если нужно навести порядок с firewall на ноде, пригодится отдельный разбор: практическое руководство по nftables для серверов.

Conntrack и перегрузка таблицы соединений

При большой нагрузке или сетевых штормах может упираться conntrack. Симптомы похожи на «случайные таймауты» к Service/Pod. Смотрите счётчики и лимиты на ноде:

sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count

Если nf_conntrack_count стабильно близок к максимуму — это инфраструктурная задача: тюнинг, снижение количества коротких соединений, keepalive, правильные таймауты.

NetworkPolicy блокирует трафик

Если вы используете CNI с поддержкой NetworkPolicy, убедитесь, что разрешён входящий трафик к Pod’ам со стороны нужных источников (namespaceSelector/podSelector/ports). При включённом default-deny Service будет существовать, Endpoints будут, но пакеты будут дропаться на уровне dataplane CNI.

Мини-чеклист: что собрать в тикет/инцидент

Если вы дебажите не в одиночку (или передаёте в поддержку/сетевикам), соберите минимум артефактов:

  • kubectl get svc, kubectl get endpoints, kubectl get endpointslice по проблемному сервису;
  • пример Pod IP и нода, где он запущен (kubectl get pod -o wide);
  • как именно тестировали (изнутри кластера или снаружи), к какому адресу/порту;
  • логи kube-proxy за момент проблемы;
  • фрагменты iptables -t nat -S KUBE-SERVICES и iptables -t nat -S KUBE-NODEPORTS по нужному Service/NodePort.

Итоги

Service в Kubernetes — это не «магия», а довольно конкретная связка: Service IP/порт + Endpoints/EndpointSlice + правила, которые на нодах настраивает kube-proxy. Когда возникают симптомы вроде clusterip unreachable или nodeport not working, быстрее всего двигаться сверху вниз: Endpoints → проверка доступа к Pod IP → kube-proxy rules (iptables) → CNI/маршрутизация → firewall/политики → особенности externalTrafficPolicy для внешнего трафика.

Если хотите углубиться, в следующем материале можно разобрать типовые дампы iptables для Service и показать, как по цепочкам быстро понять: куда именно должен уйти пакет и на каком шаге он теряется.

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...