Что такое Ingress в Kubernetes?
Ingress -- это L7 (HTTP) маршрутизатор. В отличие от Service (L4, IP:порт), Ingress маршрутизирует по доменам, URL-путям, headers. Один Ingress = множество сервисов.
🟢 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 состоит из двух отдельных компонентов:
-
Ingress Resource — YAML-манифест с правилами роутинга (хосты, пути, TLS). Это просто запись в etcd, сама по себе она ничего не делает.
-
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 перегенерировал конфигурацию.
Проблема:
- Nginx reload происходил каждые 2-3 секунды
- Каждый reload вызывал 100-200ms latency spike для 30% активных соединений
- p99 latency вырос с 200ms до 2 секунд
- Клиенты начали получать timeout’ы
- HPA масштабировал Pod’ы, что создавало ещё больше Ingress updates → feedback loop
Post-mortem и fix:
- Разделили Ingress Controller’ы по критичности:
ingress-external(публичные API),ingress-internal(B2B сервисы) - Перешли на Contour (Envoy-based) — xDS updates без reload, latency spike исчезли
- Внедрили
batchingIngress updates — контроллер ждёт 5 секунд перед reload, собирая пакетные изменения - Ограничили количество деплоей в час через CI/CD pipeline throttling
- Добавили мониторинг
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 панели:
- Request rate (RPS) по Ingress/Service — зелёная/красная линия по статусам
- Latency p50/p95/p99 — корреляция с деплоями
- 5xx error rate — alert при > 1% от общего трафика
- Nginx reload count и duration — детекция reload storm
- Active connections — мониторинг WebSocket/long-polling
- Rate limiting events — детекция DDoS или misconfigured limits
Highload Best Practices
- Используйте Envoy-based контроллер (Contour, Istio Gateway) при 1000+ Ingress — nginx reload latency становится критичной
- Разделяйте Ingress Controller’ы по критичности — публичные API и внутренние сервисы на разных контроллерах
- Настраивайте rate limiting —
limit-rps,limit-connectionsдля защиты от DDoS и abuse - Используйте Cert-Manager для автоматизации TLS — ручное управление сертификатами не масштабируется
- Batch Ingress updates в CI/CD — не создавайте 50 Ingress одновременно, группируйте деплои
- Мониторьте reload duration — alert при p99 > 100ms
- Anti-affinity для Ingress Controller Pod’ов — раскидайте реплики по разным нодам:
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: ingress-nginx topologyKey: kubernetes.io/hostname - Используйте Gateway API для новых проектов — Ingress постепенно устаревает, Gateway API — будущее
- End-to-end TLS для compliance — internal mTLS между Ingress и Pod’ами через Service Mesh или cert-manager internal CA
- Canary через Ingress annotations —
canary: "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