Введение: роль Ingress в маршрутизации трафика
Ingress - это объект Kubernetes, который управляет внешним HTTP/HTTPS-доступом к сервисам кластера. Он решает задачу централизованной маршрутизации: вместо того чтобы поднимать отдельный балансировщик для каждого микросервиса, вы описываете правила в одном манифесте и отдаёте их ingress-контроллеру. Тот принимает весь входящий трафик и распределяет его по сервисам на основе URL-путей и доменных имён.
Сравним с альтернативами. Service типа NodePort открывает порт на каждом узле, но не умеет маршрутизировать по путям и требует ручного управления портами. Service типа LoadBalancer создаёт внешний балансировщик для каждого сервиса, что быстро увеличивает счёт за облако. Ingress закрывает обе проблемы: один вход для всех сервисов, правила на уровне HTTP, поддержка TLS-терминации и экономия ресурсов.
Для работы Ingress нужен ingress-контроллер. Сам объект Ingress - это лишь набор правил. Фактическую обработку трафика выполняет контроллер, например NGINX Ingress Controller или Traefik. В этой статье мы используем NGINX как наиболее распространённый вариант. Если вы ещё не развернули контроллер, начните с руководства по настройке Service и Ingress в Kubernetes, где разобран процесс установки и базовые ошибки.
Основы маршрутизации: path-based routing
Path-based routing направляет трафик на разные сервисы в зависимости от URL-пути. Запрос на /api уходит в api-service, запрос на /web - в web-service. Это базовый сценарий для микросервисной архитектуры, где фронтенд и бэкенд живут в разных подах.
Структура Ingress состоит из секций rules, http, paths и backend. В rules перечисляются хосты и пути, в backend указывается целевой сервис и порт. Если один и тот же путь подходит под несколько правил, контроллер выбирает самый длинный совпадающий путь. Поэтому /api/v1 победит /api.
Пример манифеста Ingress с path-based routing
Ниже - готовый YAML, который можно скопировать и адаптировать под свои сервисы.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Разберём ключевые строки. ingressClassName: nginx указывает, какой контроллер обрабатывает этот Ingress. В rules задан один хост app.example.com. Внутри paths два правила: /api ведёт на api-service порт 8080, /web - на web-service порт 80. Поле backend.service.name должно совпадать с именем существующего Service, иначе контроллер вернёт 503.
Типы pathType: Prefix и Exact
Поле pathType определяет, как контроллер сопоставляет URL с путём. Тип Prefix совпадает по префиксу: правило /api с Prefix перехватит и /api, и /api/v1/users, и /apiary. Тип Exact требует точного совпадения: правило /api с Exact сработает только на запрос ровно /api.
Для большинства микросервисных сценариев подходит Prefix. Он позволяет бэкенду обрабатывать все подпути. Exact используйте, когда нужно жёстко ограничить маршрут, например для healthcheck-эндпоинта. Учитывайте, что поведение Prefix может отличаться в разных контроллерах. NGINX Ingress Controller трактует Prefix как совпадение по сегментам пути, Traefik - посимвольно. Проверяйте документацию вашего контроллера перед применением.
Маршрутизация по доменным именам (host-based routing)
Host-based routing направляет трафик на разные сервисы в зависимости от домена. Это удобно для разделения окружений или изоляции сервисов: api.example.com обрабатывает API, web.example.com отдаёт фронтенд. В одном Ingress можно указать несколько rules, каждый со своим host.
Хост указывается без схемы и порта. Запись https://api.example.com:443 в манифесте превращается в api.example.com. Контроллер сопоставляет заголовок Host входящего запроса с перечисленными хостами и выбирает подходящее правило. Если хост не указан вовсе, правило срабатывает для любого домена, что полезно для тестовых стендов.
Пример YAML для нескольких хостов
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: host-based-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Здесь два правила. Первое ловит все запросы на api.example.com и отправляет их в api-service. Второе обрабатывает web.example.com и направляет трафик в web-service. Путь / с Prefix означает «все пути этого хоста». Такой подход часто применяется для разделения публичного API и пользовательского интерфейса.
Настройка TLS-терминации в Ingress
TLS-терминация в Ingress означает, что HTTPS-соединение расшифровывается на контроллере, а дальше трафик идёт в сервис по HTTP внутри кластера. Это стандартная практика: сертификаты хранятся в одном месте, а приложения не занимаются шифрованием. Настраивается через секцию tls в спецификации Ingress.
Для работы нужен Secret с сертификатом и ключом. Секция tls содержит список хостов и имя Secret. Можно указать несколько сертификатов для разных доменов - контроллер выберет нужный по SNI.
Создание Secret с сертификатом
Создайте Secret типа kubernetes.io/tls командой:
kubectl create secret tls tls-secret \
--cert=cert.pem \
--key=key.pem \
-n default
Сертификат должен быть валидным для всех хостов, перечисленных в секции tls. Если сертификат выпущен только на api.example.com, а в правилах есть web.example.com, браузер покажет ошибку для второго домена. Для автоматизации выпуска сертификатов используйте cert-manager - это избавит от ручного обновления.
Пример Ingress с TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
После применения этого манифеста контроллер принимает HTTPS-запросы на api.example.com, расшифровывает их и передаёт в api-service по HTTP. Внутренний трафик остаётся незашифрованным, что безопасно в пределах доверенной сети кластера. Для сквозного шифрования потребуется дополнительная настройка на уровне сервиса.
Использование аннотаций ingress-контроллеров
Аннотации позволяют тонко настраивать поведение контроллера без изменения основной спецификации Ingress. Они зависят от конкретного контроллера: аннотации NGINX не работают в Traefik и наоборот. Для NGINX Ingress Controller наиболее полезны rewrite-target, ssl-redirect, proxy-body-size и cors.
Переопределение пути с rewrite-target
Частая проблема: правило /api ведёт на бэкенд, который ожидает запросы на корень /. Без переопределения бэкенд получит /api/users и вернёт 404. Аннотация nginx.ingress.kubernetes.io/rewrite-target: / убирает префикс перед отправкой в сервис.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
С этой аннотацией запрос /api/users придёт в бэкенд как /users. Значение / означает, что весь совпавший префикс заменяется на корень. Если нужно сохранить часть пути, используйте регулярные выражения в path и группы захвата в rewrite-target, например rewrite-target: /$2.
Другие полезные аннотации NGINX
- ssl-redirect - принудительно перенаправляет HTTP на HTTPS. Значение
"true"включает редирект. Полезно, когда весь трафик должен быть зашифрован. - proxy-body-size - ограничивает размер тела запроса. Значение
10mразрешает загрузку до 10 мегабайт. По умолчанию NGINX ограничивает тело 1 мегабайтом, что ломает загрузку файлов. - cors - настраивает CORS-заголовки. Значение
"true"включает базовую поддержку Cross-Origin Resource Sharing для запросов из браузера.
Аннотации добавляются в metadata.annotations манифеста. Применяйте их точечно: каждая аннотация усложняет конфигурацию и может конфликтовать с другими настройками контроллера.
Отладка и устранение распространенных ошибок
Проблемы с маршрутизацией проявляются как коды 404, 502 или 503. 404 означает, что правило не совпало или путь не найден. 502 и 503 указывают на проблемы с бэкендом: сервис недоступен, порт неверный или поды не готовы. Диагностика начинается с проверки статуса Ingress и логов контроллера.
Проверка статуса Ingress
Получите список Ingress и их адреса:
kubectl get ingress -n default
Вывод покажет имя, класс, хосты и адрес. Если в колонке ADDRESS пусто, контроллер не назначил внешний адрес - проверьте, запущен ли ingress-контроллер. Детальную информацию даёт команда:
kubectl describe ingress microservices-ingress -n default
В выводе смотрите секцию Events. Там отображаются ошибки применения правил, например несуществующий сервис или неверный порт. События - первый источник информации при отладке.
Анализ логов ingress-контроллера
Логи контроллера содержат детали по каждому запросу и ошибкам конфигурации. Найдите под контроллера:
kubectl get pods -n ingress-nginx
Затем посмотрите логи:
kubectl logs -n ingress-nginx ingress-nginx-controller-xxx
Типичные сообщения: service "default/api-service" not found - имя сервиса в манифесте не совпадает с реальным. no endpoints available - у сервиса нет готовых подов, проверьте селекторы и статус Deployment. SSL certificate does not match host - сертификат не покрывает указанный домен. Исправьте причину и перезапустите контроллер, если изменения не применились автоматически.
Для более глубокой диагностики сетевой связности между подами используйте методики из статьи о маршрутизации между сервисами.
Заключение: лучшие практики и дальнейшие шаги
Ключевые точки этой статьи: path-based routing направляет трафик по URL-путям, host-based routing - по доменам. TLS-терминация настраивается через секцию tls и Secret с сертификатом. Аннотации контроллера решают специфические задачи: переопределение пути, редирект на HTTPS, ограничение размера запроса.
Для production-среды используйте один Ingress на домен, чтобы изолировать правила и упростить отладку. Тестируйте изменения в staging-окружении перед применением в проде. Следите за актуальностью сертификатов - автоматизируйте их выпуск через cert-manager. Если вам нужны более продвинутые сценарии, такие как canary-развертывания и мониторинг маршрутизируемых запросов, обратитесь к руководству по маршрутизации для SRE.
Gateway API - более современная альтернатива Ingress. Он разделяет роли на GatewayClass, Gateway и HTTPRoute, что даёт больше гибкости для сложных сценариев. Если вы проектируете новую систему, оцените Gateway API. Для существующих кластеров Ingress остаётся рабочим и проверенным решением. Практические сценарии с Gateway API разобраны в материале о маршрутизации между сервисами.