Маршрутизация по URL в Kubernetes Ingress: настройка правил для микросервисов | AdminWiki

Маршрутизация по URL в Kubernetes Ingress: настройка правил для микросервисов

27 августа 2026 7 мин. чтения

Введение: роль 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 разобраны в материале о маршрутизации между сервисами.

Поделиться:
Сохранить гайд? В закладки браузера