Питання 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 forward’ить на 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