Вопрос 20 · Раздел 14

Что такое Ingress в Kubernetes?

Ingress -- это L7 (HTTP) маршрутизатор. В отличие от Service (L4, IP:порт), Ingress маршрутизирует по доменам, URL-путям, headers. Один Ingress = множество сервисов.

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Простое определение

Ingress — это API-объект Kubernetes, который управляет внешним HTTP/HTTPS трафиком, направляя его к нужным сервисам внутри кластера. Это “единая точка входа” — один адрес для всего кластера, а Ingress решает, какому сервису достанется каждый запрос.

Ingress – это L7 (HTTP) маршрутизатор. В отличие от Service (L4, IP:порт), Ingress маршрутизирует по доменам, URL-путям, headers. Один Ingress = множество сервисов.

Аналогия

Ingress — это ресепшн в большом офисном здании. Все звонки идут через один номер. Ресепшн спрашивает: “Вам бухгалтерия?” — направляет на 3 этаж. “Вам IT?” — на 5 этаж. Один телефонный номер, много направлений.

Пример YAML

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-v1
                port:
                  number: 8080
          - path: /v2
            pathType: Prefix
            backend:
              service:
                name: api-v2
                port:
                  number: 8080
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls-secret

Пример kubectl

# Посмотреть все Ingress ресурсы
kubectl get ingress

# Детальная информация
kubectl describe ingress my-ingress

# Проверить, работает ли Ingress Controller
kubectl get pods -n ingress-nginx

Когда использовать

  • Несколько сервисов, доступных снаружи кластера по одному IP
  • Нужна маршрутизация по доменным именам (api.example.com, web.example.com)
  • Нужна маршрутизация по путям (/v1, /v2, /static)
  • Централизованное управление SSL/TLS сертификатами

🟡 Middle Level

Как это работает

Ingress состоит из двух отдельных компонентов:

  1. Ingress Resource — YAML-манифест с правилами роутинга (хосты, пути, TLS). Это просто запись в etcd, сама по себе она ничего не делает.

  2. Ingress Controller — реальное приложение (Nginx, HAProxy, Traefik, Envoy), которое читает Ingress Resources из API Server и настраивает себя как reverse proxy. Без контроллера Ingress Resource бесполезен.

Ingress ресурс – это только правила маршрутизации. Ingress Controller – это процесс (nginx, Traefik, HAProxy), который эти правила применяет. Без Controller Ingress бесполезен.

Цепочка запроса:

Client → Cloud LoadBalancer (внешний IP) → Ingress Controller Pod → Service → Backend Pod

Ingress Controller обычно работает через Service типа LoadBalancer или NodePort. Он получает внешний IP от облачного провайдера и принимает весь входящий трафик.

Практические сценарии

Сценарий 1: Path-based routing для микросервисов

rules:
  - host: api.example.com
    http:
      paths:
        - path: /users
          pathType: Prefix
          backend:
            service:
              name: user-service
              port:
                number: 8080
        - path: /orders
          pathType: Prefix
          backend:
            service:
              name: order-service
              port:
                number: 8080

Сценарий 2: TLS с Cert-Manager (автоматические Let’s Encrypt сертификаты)

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: api-tls
spec:
  secretName: api-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - api.example.com

Сценарий 3: Canary deployment через Ingress

annotations:
  nginx.ingress.kubernetes.io/canary: "true"
  nginx.ingress.kubernetes.io/canary-weight: "10"

10% трафика идёт на canary-версию, 90% — на стабильную.

Таблица распространённых ошибок

Ошибка Последствие Решение
Создание Ingress без Ingress Controller Ingress Resource существует, но трафик не идёт Установить nginx-ingress, traefik или другой контроллер
Забытый ingressClassName Используется контроллер по умолчанию или ошибка Всегда указывать ingressClassName: nginx
Неправильный pathType Exact не матчит /v1/extra, Prefix матчит слишком много Использовать Prefix с rewrite-target или ImplementationSpecific
TLS Secret не существует Ingress работает, но без HTTPS Создать Secret с tls.crt и tls.key до создания Ingress
Один контроллер на весь кластер — single point of failure При падении контроллера весь внешний трафик недоступен Запускать контроллер как DaemonSet или реплики с anti-affinity
Аннотации контроллера не задокументированы Сложно поддерживать, неизвестно что делает каждая аннотация Документировать аннотации, использовать IngressClass с parameters

Сравнительная таблица: Ingress vs LoadBalancer vs NodePort

Характеристика NodePort LoadBalancer Ingress
Уровень OSI L4 (TCP/UDP) L4 (TCP/UDP) L7 (HTTP/HTTPS)
Стоимость Бесплатно $15-50/мес за каждый LB $15-50/мес за ОДИН LB на все сервисы
Маршрутизация По порту По порту По хосту, пути, заголовкам
TLS Нет (на уровне Pod) Нет (на уровне Pod) Централизованное
Масштабируемость Один сервис на порт Один сервис на LB Сотни сервисов на одном LB
Rate Limiting Нет Зависит от облака Да (через аннотации)
WebSocket Да Да Да (с настройками)

Когда НЕ использовать

  • TCP/UDP трафик без HTTP — Ingress работает только на L7. Для TCP/UDP используйте Service типа LoadBalancer или TCP/UDP ConfigMap в nginx-ingress
  • Один сервис — если у вас только один API, проще использовать LoadBalancer Service
  • Нужен L4 балансировщик с TLS termination — используйте Gateway API (следующее поколение Ingress) или Service Mesh
  • Внутренняя коммуникация между микросервисами — для этого используйте обычные Services, не Ingress

🔴 Senior Level

Глубинная механика: Ingress Controller, Nginx, и Controller Reconciliation

Ingress Controller Architecture: Ingress Controller — это Kubernetes Controller, который работает по стандартному pattern reconciliation:

1. Watch: Подписывается на Ingress Resources через API Server (watcher)
2. List: Получает полный список Ingress, Services, Endpoints, Secrets
3. Reconcile: Сравниет желаемое состояние (Ingress YAML) с текущим (nginx.conf)
4. Update: Генерирует новую nginx.conf и выполняет `nginx -s reload`
5. Loop: Повторяет при каждом изменении (через Informer)

Nginx Ingress Controller (самый популярный):

  • Использует Go-библиотеку k8s.io/client-go для informer’ов
  • При изменении Ingress/Service/Endpoint перегенерирует nginx.conf через Go templates
  • Выполняет nginx -s reload (graceful reload, без downtime)
  • При большом количестве Ingress (1000+) reload nginx становится bottleneck — nginx должен перезагрузить конфигурацию, что занимает 50-200ms

Contour (Envoy-based):

  • Вместо nginx использует Envoy Proxy
  • Envoy использует xDS API для динамической конфигурации — без перезагрузки
  • При 1000+ Ingress Contour стабильнее, так как нет reload overhead

Gateway API (будущее Ingress):

  • Более выразительный API: поддержка TCP/UDP, gRPC, header-based routing
  • Role-based: отдельные ресурсы для Gateway (infra-команда) и HTTPRoute (dev-команда)
  • Постепенно заменяет Ingress, но пока не все контроллеры поддерживают

Gateway API – GA с K8s v1.28. Более гибкий, поддерживает TCP/UDP, не только HTTP. Постепенно заменяет Ingress.

Trade-offs

Аспект Trade-off
Nginx vs Envoy Nginx проще и привычнее, но reload при больших конфигурациях = latency spike. Envoy без reload, но сложнее в эксплуатации
Один vs много контроллеров Один контроллер дешевле и проще, но single point of failure. Много контроллеров = изоляция по командам, но дороже
Ingress vs Gateway API Ingress зрелый и поддерживается везде. Gateway API более выразительный, но менее зрелый
Annotations vs CRD Annotations проще, но не валидируются. CRD (Kong, Gloo) дают валидацию и документирование, но требуют установки CRD
TLS termination: Ingress vs Pod Termination на Ingress = централизованное управление, но Ingress видит весь трафик. Termination в Pod = end-to-end TLS, но сложнее управление сертификатами

Edge Cases (6+)

Edge Case 1: Ingress Controller reload storm При 1000+ Ingress Resources и частых деплоях (100+ в день), nginx controller постоянно перегенерирует конфигурацию. Каждый reload = 50-200ms latency spike для активных соединений. Решение: batching updates, или переход на Envoy-based контроллер (Contour, Istio Gateway).

Edge Case 2: Sticky Sessions с IPVS Nginx Ingress поддерживает sticky sessions через cookie. Но если kube-proxy работает в IPVS mode, а не iptables, балансировка на уровне Service может конфликтовать с nginx sticky sessions. Клиент с sticky cookie попадает на нужный Pod через nginx, но nginx forwards на Service IP, и IPVS может перенаправить на другой Pod.

Edge Case 3: TLS Secret в другом namespace Ingress Resource может ссылаться на TLS Secret только в своём namespace. Если команда A управляет Ingress в namespace prod, а сертификаты хранятся в namespace cert-manager, нужен механизм копирования Secret’ов (например, cert-manager + secretTemplate или external-secrets operator).

Edge Case 4: WebSocket через Ingress WebSocket требует upgrade соединения HTTP → WS. Nginx Ingress по умолчанию закрывает idle соединения через 60 секунд. Для долгоживущих WebSocket нужно:

annotations:
  nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
  nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"

Edge Case 5: Ingress и NetworkPolicy Ingress Controller должен иметь доступ ко всем Backend Pod’ам. Если вы настроили NetworkPolicy, запрещающую входящий трафик на Backend namespace, Ingress Controller не сможет forward’ить запросы. Решение: NetworkPolicy должна разрешать трафик от ingress-nginx namespace.

Edge Case 6: Multiple Ingress Controllers В кластере может быть несколько Ingress Controller’ов (nginx для внешних сервисов, istio для внутренних). Ingress Resource должен явно указывать ingressClassName. Если не указан — используется контроллер с аннотацией ingressclass.kubernetes.io/is-default-class. Конфликт контроллеров = непредсказуемый роутинг.

Edge Case 7: Ingress с headless Service Ingress требует Service с ClusterIP. Headless Service (clusterIP: None) не поддерживается как backend для Ingress — nginx не может резольвить headless Service в upstream’ы. Решение: создать отдельный ClusterIP Service для Ingress.

Performance Numbers

Метрика Значение
Nginx reload latency 50-200ms (зависит от размера конфигурации)
Envoy xDS update latency 1-10ms (без перезагрузки)
Ingress Controller→Backend latency 1-5ms (внутри кластера)
Max Ingress Resources per Controller ~1000-2000 (nginx), ~5000+ (Envoy)
TLS handshake overhead 5-15ms (TLS 1.3), 15-30ms (TLS 1.2)
Rate limiting overhead 0.1-1ms на запрос (nginx limit_req)
Cloud LoadBalancer cost $15-50/мес (один LB для всего кластера)

Security

  • TLS termination на Ingress — трафик между Ingress и Pod’ами идёт без шифрования. Для compliance (PCI-DSS, HIPAA) нужен end-to-end TLS: Ingress → Pod через HTTPS с internal cert
  • Rate Limiting — защитите backend от DDoS через аннотации:
    nginx.ingress.kubernetes.io/limit-rps: "100"
    nginx.ingress.kubernetes.io/limit-connections: "50"
    
  • WAF (Web Application Firewall) — nginx-ingress поддерживает ModSecurity для защиты от OWASP Top 10:
    nginx.ingress.kubernetes.io/enable-modsecurity: "true"
    nginx.ingress.kubernetes.io/modsecurity-snippet: |
      SecRuleEngine On
    
  • IP Whitelisting — ограничьте доступ к внутренним API:
    nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12"
    
  • HSTS headers — enforce HTTPS:
    nginx.ingress.kubernetes.io/use-hsts: "true"
    nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
    
  • Ingress Controller в отдельном namespace — запускать в ingress-nginx с ограниченным RBAC и NetworkPolicy

Production War Story

Ситуация: SaaS-платформа, 200 микросервисов, один Nginx Ingress Controller на весь кластер (реплика 2). Во время Black Friday количество деплоей выросло с 50 до 500 в день. Каждый деплой создавал/обновлял Ingress Resource, и nginx controller перегенерировал конфигурацию.

Проблема:

  1. Nginx reload происходил каждые 2-3 секунды
  2. Каждый reload вызывал 100-200ms latency spike для 30% активных соединений
  3. p99 latency вырос с 200ms до 2 секунд
  4. Клиенты начали получать timeout’ы
  5. HPA масштабировал Pod’ы, что создавало ещё больше Ingress updates → feedback loop

Post-mortem и fix:

  1. Разделили Ingress Controller’ы по критичности: ingress-external (публичные API), ingress-internal (B2B сервисы)
  2. Перешли на Contour (Envoy-based) — xDS updates без reload, latency spike исчезли
  3. Внедрили batching Ingress updates — контроллер ждёт 5 секунд перед reload, собирая пакетные изменения
  4. Ограничили количество деплоей в час через CI/CD pipeline throttling
  5. Добавили мониторинг nginx_ingress_controller_reload_duration_seconds

Мониторинг после fix:

# Alert: Nginx reload latency растёт
histogram_quantile(0.99, nginx_ingress_controller_config_last_reload_duration_seconds_bucket) > 0.1

# Alert: Ingress Controller pod restart
rate(kube_pod_container_status_restarts_total{namespace="ingress-nginx"}[5m]) > 0

# Alert: 5xx ошибки на Ingress
rate(nginx_ingress_controller_requests{status=~"5.."}[5m]) > 10

Monitoring (Prometheus/Grafana)

Ключевые метрики:

# Request rate по статусам
rate(nginx_ingress_controller_requests[5m])

# Latency p50/p95/p99
histogram_quantile(0.99, nginx_ingress_controller_request_duration_seconds_bucket)

# 5xx error rate
sum(rate(nginx_ingress_controller_requests{status=~"5.."}[5m])) by (ingress)

# Ingress Controller reload latency
histogram_quantile(0.99, nginx_ingress_controller_config_last_reload_duration_seconds_bucket)

# Open connections (для WebSocket/long-polling)
nginx_ingress_controller_nginx_metric_connections{state="active"}

# Rate limiting events
rate(nginx_ingress_controller_requests{status="429"}[5m])

Grafana Dashboard панели:

  1. Request rate (RPS) по Ingress/Service — зелёная/красная линия по статусам
  2. Latency p50/p95/p99 — корреляция с деплоями
  3. 5xx error rate — alert при > 1% от общего трафика
  4. Nginx reload count и duration — детекция reload storm
  5. Active connections — мониторинг WebSocket/long-polling
  6. Rate limiting events — детекция DDoS или misconfigured limits

Highload Best Practices

  1. Используйте Envoy-based контроллер (Contour, Istio Gateway) при 1000+ Ingress — nginx reload latency становится критичной
  2. Разделяйте Ingress Controller’ы по критичности — публичные API и внутренние сервисы на разных контроллерах
  3. Настраивайте rate limitinglimit-rps, limit-connections для защиты от DDoS и abuse
  4. Используйте Cert-Manager для автоматизации TLS — ручное управление сертификатами не масштабируется
  5. Batch Ingress updates в CI/CD — не создавайте 50 Ingress одновременно, группируйте деплои
  6. Мониторьте reload duration — alert при p99 > 100ms
  7. Anti-affinity для Ingress Controller Pod’ов — раскидайте реплики по разным нодам:
    affinity:
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: ingress-nginx
              topologyKey: kubernetes.io/hostname
    
  8. Используйте Gateway API для новых проектов — Ingress постепенно устаревает, Gateway API — будущее
  9. End-to-end TLS для compliance — internal mTLS между Ingress и Pod’ами через Service Mesh или cert-manager internal CA
  10. Canary через Ingress annotationscanary: "true" + canary-weight: "10" для безопасного деплоя

🎯 Шпаргалка для интервью

Обязательно знать:

  • Ingress — L7 (HTTP/HTTPS) маршрутизация: по домену, пути, headers; один IP для многих сервисов
  • Ingress Resource (YAML правила) ≠ Ingress Controller (nginx, Traefik, Envoy — реальный proxy)
  • Без Controller Ingress Resource бесполезен — это просто запись в etcd
  • Ingress экономит деньги: один LoadBalancer на все HTTP-сервисы вместо LB на каждый
  • TLS termination централизован на Ingress; Cert-Manager для авто-сертификатов (Let’s Encrypt)
  • Nginx reload (50-200ms) при 1000+ Ingress → latency spike; Envoy (xDS) без перезагрузки
  • Gateway API (GA с K8s v1.28) — будущее; поддерживает TCP/UDP, не только HTTP

Частые уточняющие вопросы:

  • «Ingress без Controller работает?» — Нет, Controller — реальный процесс (nginx/Envoy), читающий правила
  • «Ingress vs LoadBalancer?» — Ingress = L7 HTTP маршрутизация, LoadBalancer = L4 TCP/UDP
  • «Nginx vs Envoy Controller?» — Nginx проще, но reload overhead; Envoy без reload, но сложнее
  • «WebSocket через Ingress?» — Нужны специальные аннотации (proxy-read-timeout: 3600), иначе 60s timeout

Красные флаги (НЕ говорить):

  • «Ingress — это балансировщик» (это L7 маршрутизатор; балансировку делает Service)
  • «Ingress работает без Controller» (Controller обязателен)
  • «Ingress для TCP/UDP» (только HTTP/HTTPS; для TCP — LoadBalancer Service)
  • «Один Controller на весь кластер — ОК» (single point of failure; нужны реплики)

Связанные темы:

  • [[Какие типы Service существуют (ClusterIP, NodePort, LoadBalancer)]] — L4 vs L7
  • [[Что такое Service в Kubernetes]] — Service vs Ingress
  • [[Как организовать rolling update в Kubernetes]] — canary через Ingress