Ingress Controller и сетевой путь трафика в Kubernetes
Service и Ingress в Kubernetes
В Kubernetes каждый Pod получает свой IP. Этот адрес может измениться после пересоздания Pod, поэтому его не используют как постоянную точку интеграции.
Чтобы сервисы не зависели от "живых" адресов Pod, в кластере используют:
Service— стабильный виртуальный IP (ClusterIP) и DNS-имя для доступа внутри кластера;Ingress— правила внешнего HTTP/HTTPS-доступа по host/path;Ingress Controller— реальный компонент, который читает объектIngressи применяет маршрутизацию.
Без установленного Ingress Controller ресурс Ingress сам по себе не проксирует трафик.
Подробнее:
Как Pod связывается с Service
Типовой поток внутри кластера:
- Вы создаете
Serviceсselector, напримерapp: backend. - Kubernetes находит подходящие Pod и публикует их адреса в
EndpointSlice(исторически —Endpoints). kube-proxyна каждой ноде получает изменения через API и обновляет правила в сетевом стеке ОС (iptablesилиIPVS).- Клиентский Pod отправляет запрос на
ClusterIPили DNS-имя сервиса. - Ядро Linux на ноде применяет DNAT: виртуальный адрес сервиса подменяется на реальный IP одного из Pod-бэкендов.
Итог: приложение ходит на стабильное имя сервиса, а реальная балансировка по Pod происходит прозрачно.
Расшифровка терминов
ClusterIP— внутренний IP сервиса, который доступен только внутри кластера;DNS-имя сервиса— имя видаmy-backend-service.default.svc.cluster.local, по которому сервис находят другие Pod;DNAT— подмена адреса назначения пакета, чтобы пакет дошел до конкретного Pod;EndpointSlice— объект Kubernetes со списком "живых" Pod, которые готовы принимать трафик.
Мини схема сетевых объектов
Маршрут внутри Kubernetes удобно читать как цепочку:
Podс клиентом отправляет запрос;Serviceпринимает запрос на свойClusterIP;EndpointSliceхранит список целевых Pod;kube-proxyна ноде применяет правила и отправляет пакет в один из Pod сервиса.
Эта цепочка работает одинаково для HTTP, gRPC, Redis, PostgreSQL и других TCP-сервисов.
Пример манифеста Service (YAML)
apiVersion: v1
kind: Service
metadata:
name: my-backend-service
namespace: default
spec:
type: ClusterIP
selector:
app: my-web-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
Что означает
kind: Service— сетевой объект доступа к группе Pod;type: ClusterIP— доступ только внутри кластера;selector— какие Pod включить в балансировку;port— порт сервиса;targetPort— порт контейнера в Pod.
Полезная команда для разбора конкретного сервиса:
kubectl describe svc my-backend-service
Команды, которые обычно запускают рядом:
kubectl get svc my-backend-service -o wide
kubectl get endpointslice -l kubernetes.io/service-name=my-backend-service
kubectl get pods -l app=my-web-app -o wide
Они показывают:
- какой
ClusterIPвыдан сервису; - какие Pod попали в
EndpointSlice; - на какие IP реально уйдет трафик.
Основные типы Service
Поле spec.type определяет модель доступа:
-
ClusterIP(по умолчанию)
Внутренний IP, доступ только внутри кластера. -
NodePort
Открывает порт на каждой ноде (30000-32767) и проксирует внутрь наClusterIP. -
LoadBalancer
В облаке создает внешний балансировщик, который ведет трафик в кластер (обычно на NodePort/узлы). -
ExternalName
Не проксирует трафик, а возвращает DNS CNAME на внешний адрес.
Подробный справочник типов
Входящий и исходящий трафик Pod
Egress из Pod во внешний мир
Когда Pod вызывает внешний API:
- пакет выходит из сетевого namespace Pod на ноду;
- нода обычно делает SNAT (подмена адреса источника на адрес ноды);
- ответ возвращается обратно через ноду в Pod.
Термин SNAT означает подмену адреса источника. Внешний сервис видит адрес ноды, а не внутренний адрес Pod.
Ingress из внешнего мира в Pod
Типовой production-путь:
- Клиент приходит на внешний балансировщик (
Service type: LoadBalancerу ingress-контроллера). - Трафик попадает в Pod Ingress Controller.
- Контроллер читает
HostиPathзапроса. - По правилам
Ingressвыбирается нужныйService. - Запрос отправляется в один из Pod целевого сервиса.
Что именно проверяется в HTTP-запросе:
Hostиз заголовка;- путь URL, например
/apiили/shop; - порт и протокол;
- TLS-сертификат, если используется HTTPS.
Для наглядности:
- запрос
https://app.example.com/api/usersможет уйти вbackend-service; - запрос
https://app.example.com/может уйти вfrontend-service.
Нужно ли приложениям в Pod обращаться к API Server
Для обычной бизнес-логики — нет.
Микросервисы обычно общаются друг с другом через Service (HTTP/gRPC), а не через Kubernetes API.
Когда обращение к API Server действительно нужно:
- операторы и контроллеры (включая Ingress Controller);
- CI/CD-агенты внутри кластера;
- инфраструктурные компоненты, которым нужно читать состояние кластера.
Kubernetes подготавливает in-cluster доступ автоматически:
- переменные среды
KUBERNETES_SERVICE_HOSTиKUBERNETES_SERVICE_PORT; - токен и CA сертификат в
/var/run/secrets/kubernetes.io/serviceaccount/; - ограничения доступа через RBAC и
ServiceAccount.
Расшифровка
RBAC— модель прав доступа в Kubernetes, определяет, что можно читать и изменять;ServiceAccount— учетная запись Pod для обращения к API Kubernetes;CA сертификат— файл для проверки, что Pod подключается к правильному API Server.
Официальные ссылки
Ingress Controller в архитектуре
Ingress — это декларация правил, а Ingress Controller — исполняющий компонент.
В контроллере обычно две части:
- control plane: следит за изменениями
Ingress,Service,Secret,EndpointSliceчерез API Server; - data plane: принимает реальный HTTP/HTTPS-трафик и проксирует его в кластер.
Что дает Ingress Controller:
- маршрутизацию по доменам и путям;
- TLS-терминацию;
- L7-балансировку;
- дополнительные политики (лимиты, redirect, CORS, auth и т.д. в зависимости от контроллера).
Термины
TLS-терминация— расшифровка HTTPS на входе в контроллер;L7— прикладной уровень, где важныHost,Path, заголовки и cookies;Secret— объект Kubernetes для сертификатов и других чувствительных данных.
Какие контроллеры используют чаще всего
ingress-nginxдля универсальных production-сценариев;Traefikдля динамической конфигурации и встроенных интеграций;HAProxy Ingressдля сценариев с очень высоким трафиком;- API gateway решения, когда нужен расширенный контроль авторизации и политик.
Пример Ingress для NGINX Ingress Controller
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "20m"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-backend-service
port:
number: 80
Здесь ingressClassName: nginx явно говорит, что правила должен обработать класс nginx.
Рекомендуемый параметр в новых манифестах — ingressClassName.
Старая аннотация kubernetes.io/ingress.class встречается, но считается legacy-подходом.
Пример маршрутизации по нескольким путям
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-multi-route
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
Как читать этот манифест:
- все запросы на
app.example.com/api...идут вbackend-service; - остальные запросы идут в
frontend-service; - приложение разделено на публичный фронтенд и отдельный API.
Подробнее по правилам:
Установка NGINX Ingress Controller через Helm
Стандартный путь установки:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace
Что создается под капотом:
- Deployment/Pod контроллера;
- Service (часто
LoadBalancer) как внешняя точка входа; ServiceAccount,ClusterRole,ClusterRoleBindingдля чтения нужных ресурсов API;- admission-компоненты (в зависимости от версии чарта и настроек).
Проверка:
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
kubectl get ingressclass
После установки можно применять собственные Ingress-манифесты.
Команды для диагностики установки:
kubectl describe ingressclass nginx
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=200
Официальная документация:
Что происходит во время установки пошагово
helmскачивает шаблоны чарта и рендерит YAML.kubectl-эквивалент отправляется в API Server.- API Server сохраняет ресурсы в
etcd. - Scheduler назначает Pod контроллера на ноду.
- kubelet запускает контейнеры контроллера.
- Контроллер начинает смотреть
Ingress,Service,Secret,EndpointSlice. - Появляется внешний адрес сервиса контроллера.
После этого любые новые Ingress-объекты начинают применяться автоматически.
Обновление ingress-nginx
helm repo update
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx
Перед обновлением полезно проверить:
- версию Kubernetes в кластере;
- совместимость версии чарта;
- наличие backup значений
helm get values ingress-nginx -n ingress-nginx.
Что такое kube-proxy и почему он на нодах
kube-proxy — сетевой агент Kubernetes, который работает как DaemonSet: по одному экземпляру на ноду, а не на Pod.
Почему не "на каждом Pod":
- задача kube-proxy — настраивать сетевые правила уровня ноды в ядре ОС;
- это системная функция маршрутизации/балансировки, общая для всех Pod на ноде;
- запуск отдельного прокси в каждом Pod был бы избыточен и дорог по ресурсам.
Как он работает:
- Подписывается на
ServiceиEndpointSliceчерез API Server. - Обновляет правила
iptablesили таблицыIPVS. - При обращении к
ClusterIPпакет перехватывается и перенаправляется на реальный Pod-бэкенд.
Что важно помнить
kube-proxyработает на уровне L4, то есть на уровне TCP/UDP;kube-proxyне анализирует HTTP host/path;- маршрутизацию по доменам и путям делает Ingress Controller на уровне L7.
Подробно
Режимы работы kube-proxy
kube-proxy может работать в нескольких режимах, на практике используют два:
iptables
Правила создаются в таблицах фильтрации Linux. Режим простой и распространенный.ipvs
Используется подсистема IP Virtual Server в ядре Linux. Режим хорошо подходит для крупных кластеров и высокой нагрузки.
Выбор режима зависит от дистрибутива Kubernetes и настроек кластера.
Почему kube-proxy не виден приложению напрямую
Приложение в Pod обращается к Service по DNS имени или ClusterIP.
Дальше срабатывает сетевой стек ноды. В этой точке и работает kube-proxy.
Именно поэтому разработчик обычно не пишет в коде ничего про kube-proxy.
Как выглядит полный путь запроса
Пример: пользователь открывает https://app.example.com/api/orders.
- DNS указывает на внешний IP балансировщика.
- Балансировщик передает трафик в
ingress-nginx. - NGINX Ingress находит правило
host/pathи выбираетService. - Сервисная адресация приводит к одному из Pod-бэкендов.
- Ответ идет обратно тем же маршрутом к клиенту.
Внутри кластера сервисы продолжают вызывать друг друга через DNS сервисов (*.svc.cluster.local) без знания IP конкретных Pod.
Для новичка удобно держать в голове две независимые линии.
- внешняя линия входа через Ingress Controller;
- внутренняя линия связи сервисов через
Serviceи кластерный DNS.
Полный путь для внутреннего вызова между сервисами
Пример вызова frontend к backend:
frontendотправляет запрос наhttp://backend-service.default.svc.cluster.local.- Кластерный DNS возвращает
ClusterIPсервиса. - Пакет доходит до ноды и попадает в правила
kube-proxy. - Выбирается один живой Pod из
EndpointSlice. - Запрос обрабатывается приложением в Pod
backend.
Полезные команды:
kubectl get svc backend-service
kubectl get endpointslice -l kubernetes.io/service-name=backend-service
kubectl exec -it deploy/frontend -- nslookup backend-service.default.svc.cluster.local
С их помощью легко проверить DNS и связность внутри кластера.
Разница между Ingress Controller, NodePort и LoadBalancer
NodePort— простой способ открыть сервис наружу, обычно для dev/тестов;LoadBalancer— внешний L4-балансировщик для одного сервиса;Ingress Controller— единая L7-точка входа для множества HTTP/HTTPS-сервисов по доменам и путям.
Типичный production-шаблон: один LoadBalancer перед Ingress Controller и десятки сервисов за ним.
Короткий практический чек-лист
- Установите Ingress Controller (например,
ingress-nginx). - Проверьте
IngressClassи внешний адрес сервиса контроллера. - Создайте
ServiceтипаClusterIPдля приложения. - Создайте
IngressсingressClassName,host,path. - Проверьте маршрутизацию:
kubectl get ingress -A
kubectl describe ingress my-app-ingress
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=200
Так вы проходите весь путь между Pod и Service внутри кластера и внешний доступ через Ingress Controller.
Практический стенд для новичка
Ниже минимальный набор объектов, который можно развернуть и проверить руками.
Шаг 1 деплой приложения
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-web
spec:
replicas: 2
selector:
matchLabels:
app: demo-web
template:
metadata:
labels:
app: demo-web
spec:
containers:
- name: demo-web
image: hashicorp/http-echo:1.0.0
args:
- "-text=hello from demo-web"
ports:
- containerPort: 5678
Шаг 2 сервис для Pod
apiVersion: v1
kind: Service
metadata:
name: demo-web-service
spec:
selector:
app: demo-web
ports:
- port: 80
targetPort: 5678
Шаг 3 ingress для внешнего входа
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-web-ingress
spec:
ingressClassName: nginx
rules:
- host: demo.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-web-service
port:
number: 80
Команды проверки:
kubectl apply -f demo-deploy.yaml
kubectl apply -f demo-service.yaml
kubectl apply -f demo-ingress.yaml
kubectl get deploy,pods,svc,ingress
kubectl describe ingress demo-web-ingress
Для локального кластера можно добавить demo.local в hosts и проверить через браузер или curl.
TLS сертификаты и HTTPS
В production обычно нужен HTTPS. Базовый сценарий:
- сертификат хранится в
Secretтипаkubernetes.io/tls; Ingressссылается на этот secret в секцииtls;- Ingress Controller завершает TLS и передает HTTP во внутренние сервисы.
Пример секции tls:
spec:
tls:
- hosts:
- app.example.com
secretName: app-example-tls
Для автоматизации часто ставят cert-manager.
Полезные ссылки:
Отладка проблем с трафиком
Ingress создан, сайт не открывается
Проверяйте по порядку:
- есть ли внешний адрес у сервиса
ingress-nginx-controller; - совпадает ли
hostв Ingress и доменное имя запроса; - существует ли целевой
Service; - есть ли у сервиса живые endpoints.
Команды:
kubectl get svc -n ingress-nginx
kubectl get ingress -A
kubectl describe ingress demo-web-ingress
kubectl get endpointslice -l kubernetes.io/service-name=demo-web-service
Service есть, но трафик не идет в Pod
Обычно причина в одном из пунктов:
- в
selectorсервиса указана метка, которой нет у Pod; targetPortне совпадает с портом контейнера;- Pod в статусе
NotReady, поэтому не попадает в endpoints.
Команды:
kubectl get pods -l app=demo-web --show-labels
kubectl describe svc demo-web-service
kubectl describe pod POD_NAME
Ошибки 404 и 502 от NGINX Ingress
404часто означает, что не найдено правило по host/path;502часто означает, что backend сервис найден, но целевой Pod недоступен.
Команда для чтения причин:
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=300
Безопасность сетевого периметра
Базовые рекомендации:
- хранить TLS-секреты в отдельном namespace и ограничивать доступ через RBAC;
- закрывать доступ к сервисам без необходимости внешней публикации;
- использовать
NetworkPolicy, чтобы ограничить межсервисные соединения; - разделять публичные и внутренние сервисы по namespace;
- включать логи ingress-контроллера и собирать метрики.
Официальная ссылка:
Частые ошибки новичков
- Путают
portиtargetPortвService. - Создают
Ingress, но не устанавливают Ingress Controller. - Пишут
host, который не резолвится в DNS. - Забывают
ingressClassNameи ожидают автоподхват в любом кластере. - Проверяют только
kubectl get, безkubectl describeи логов. - Используют
NodePortдля production без дополнительных защитных слоев.
Полезные команды для ежедневной работы
kubectl get svc,ingress,endpointslice -A
kubectl describe svc SERVICE_NAME -n NAMESPACE
kubectl describe ingress INGRESS_NAME -n NAMESPACE
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=200
kubectl get pods -n ingress-nginx -o wide
kubectl get events -A --sort-by=.metadata.creationTimestamp
Если эти команды запускать в указанном порядке, обычно причина сетевой проблемы находится быстро.
Что изучать дальше в разделе
- Docker Swarm и Kubernetes
- Реализация Kubernetes
- Справочник по Kubernetes
- Первые шаги с Docker и Kubernetes