🐳 Розділ 14 · Питання #20

Що таке Ingress в Kubernetes

Головне концептуальне розділення, яке потрібно розуміти:


🟢 Junior Level

30-секундна відповідь

Ingress — це спеціалізований API-об’єкт Kubernetes, який керує вхідним зовнішнім HTTP/HTTPS трафіком (L7 рівня моделі OSI), забезпечуючи єдину точку входу в кластер, маршрутизацію за доменними іменами та URL-шляхами, а також централізовану термінацію SSL/TLS сертифікатів.

Головне концептуальне розділення, яке потрібно розуміти:

  1. Ingress Resource (Маніфест): це декларативний YAML-файл, у якому описані правила маршрутизації: «Запити на api.company.com/orders надсилати на сервіс order-service». Сам по собі цей YAML пасивний і нічого не перенаправляє.
  2. Ingress Controller (Виконавець): це реальний застосунок (Nginx, Traefik, HAProxy, Envoy), що працює в кластері як зворотний проксі (Reverse Proxy). Контролер безперервно читає маніфести Ingress з API-сервера та динамічно налаштовує свої таблиці маршрутизації.

Наочна аналогія з життя

Ingress — це ресепшн у великому офісному бізнес-центрі:

  • У будівлі є одна спільна вхідна адреса та один телефонний номер.
  • Відвідувач заходить на ресепшн і каже: «Мені в бухгалтерію» (запит до /billing) або «Мені у відділ кадрів» (запит до /hr).
  • Адміністратор на ресепшн (Ingress Controller) скеровує людину на потрібний поверх і в конкретний кабінет (внутрішній ClusterIP сервіс).

Базовий маніфест Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: main-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx # Зв'язка з конкретним Ingress-контролером
  tls:
  - hosts:
    - api.company.com
    secretName: company-tls-cert # SSL-сертифікат із K8s Secret
  rules:
  - host: api.company.com
    http:
      paths:
      - path: /orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 8080
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 8080

🟡 Middle Level

Економіка та архітектура: Ingress vs Service LoadBalancer

[ Без Ingress: Дорого та не масштабовано ]
Client ──► Cloud LoadBalancer 1 ($25/міс) ──► Order Service
Client ──► Cloud LoadBalancer 2 ($25/міс) ──► User Service
Client ──► Cloud LoadBalancer 3 ($25/міс) ──► Payment Service

[ З Ingress: Дешево, безпечно та централізовано ]
Client ──► ЄДИНИЙ Cloud LoadBalancer ($25/міс) ──► [ Ingress Controller (Nginx) ]
                                                            │
                                  ┌─────────────────────────┼─────────────────────────┐
                                  ▼                         ▼                         ▼
                            Order Service             User Service             Payment Service
                            (ClusterIP:8080)          (ClusterIP:8080)         (ClusterIP:8080)
  • L4 vs L7: Звичайний Service type: LoadBalancer працює на 4 рівні моделі OSI (TCP/UDP) — він не розуміє HTTP-заголовків, cookies, URL-шляхів та доменних імен.
  • Ingress працює на 7 рівні OSI (HTTP/HTTPS): він уміє розбирати HTTP-пакет, термінувати TLS, виконувати rewrite URL, перевіряти JWT-токени, обмежувати rate-limit та балансувати запити за префіксами шляхів.

Типи зіставлення шляхів (pathType)

Специфікація networking.k8s.io/v1 вимагає явного зазначення алгоритму зіставлення шляхів:

  • Exact: строгий точний збіг з урахуванням регістру (наприклад, шлях /orders спрацює строго на /orders, але запит /orders/123 буде відхилений із помилкою 404).
  • Prefix: збіг за префіксом URL із розділенням за слешами. /orders перенаправить і /orders, і /orders/123/items, але проігнорує /orders-archive.
  • ImplementationSpecific: зіставлення віддається логіці конкретного контролера (наприклад, підтримка регулярних виразів regex у Nginx Ingress).

Автоматизація TLS-сертифікатів з Cert-Manager

У продакшені сертифікати оновлюються автоматично зв’язкою Cert-Manager + Let’s Encrypt:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod" # Замовлення безкоштовного TLS-сертифіката
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - shop.example.com
    secretName: shop-tls-secret # Cert-Manager сам створить цей Secret

🔴 Senior Level

Проблема «Nginx Reload Storm» та перевага Envoy (Contour / Istio)

Найпопулярніший контролер — Nginx Ingress Controller — має архітектурну ваду на великих кластерах:

[ Nginx Ingress Controller ]
Подія зміни Pod/Service ──► Генерація нового nginx.conf ──► nginx -s reload (50-250ms)
                                                                    │
                                    Падіння активних з'єднань ◄─────┴──► Сплеск затримки (Latency Spike)
  1. Як працює Nginx: при кожному масштабуванні подів (HPA scale up/down) або зміні Endpoints контролер запускає шаблонізатор на Go, наново збирає гігантський файл конфігурації nginx.conf і надсилає сигнал процесу nginx -s reload.
  2. Reload Storm: якщо в кластері сотні сервісів безперервно деплояться або масштабуються, релоад Nginx відбувається раз на 2–3 секунди. У цей момент робочі процеси скидають кеші, затримують вхідні HTTP/2 та WebSocket з’єднання, викликаючи стрибки затримки (Latency Spikes) та помилки 502/504.
  3. Рішення (Envoy xDS API): сучасні контролери на базі Envoy (Contour, Envoy Gateway, Istio IngressGateway) використовують потоковий gRPC протокол xDS (EDS/CDS/LDS). Envoy динамічно оновлює списки IP-адрес бекендів в оперативній пам’яті на льоту за 2–5 мілісекунд БЕЗ перезавантаження процесу та без розриву мережевих сокетів!

Kubernetes Gateway API (Заміна Ingress у K8s 1.28+ GA)

Специфікація Ingress створювалася у 2015 році та має критичні недоліки: хаос невалідованих анотацій (nginx.ingress..., traefik.ingress...), відсутність підтримки gRPC/TCP/UDP та змішування зон відповідальності.

Gateway API розділяє ролі та ресурси:

  • GatewayClass: визначає тип контролера (керує інфраструктурний інженер або хмарний провайдер).
  • Gateway: визначає точку входу, IP та відкриті порти 80/443 (керує DevOps / кластерний адміністратор).
  • HTTPRoute / GRPCRoute: описують правила маршрутизації конкретного мікросервісу (керує команда бекенд-розробників):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: order-route
spec:
  parentRefs:
  - name: internal-gateway # Посилання на кластерний шлюз
  hostnames:
  - "api.company.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /orders
    backendRefs:
    - name: order-service
      port: 8080
      weight: 90
    - name: order-service-canary
      port: 8080
      weight: 10 # Вбудована нативна підтримка Canary без vendor-анотацій!

4 Tricky Questions

1. Що станеться, якщо створити об’єкт Ingress у кластері, де не розгорнуто жодного Ingress Controller?

Відповідь: Маніфест Ingress буде успішно прийнятий kube-apiserver і збережений у базі даних etcd (команда kubectl apply відпрацює без помилок). Проте жодної мережевої маршрутизації відбуватися не буде:

  • Стовпчик ADDRESS у виводі kubectl get ingress залишиться порожнім назавжди.
  • Жодних хмарних балансувальників навантаження створено не буде.
  • Об’єкт залишиться пасивним записом у базі даних доти, доки в кластері не з’явиться контролер (наприклад, ingress-nginx), який прочитає цей ресурс і прив’яже до нього свою зовнішню IP-адресу.

2. Як Nginx Ingress Controller реалізує канаркове розгортання (Canary Deployment), і що станеться при поєднанні відсоткової ваги (canary-weight) та збігу заголовка (canary-by-header)?

Відповідь: Канарковий Ingress створюється як дублюючий маніфест з анотацією nginx.ingress.kubernetes.io/canary: "true".

  • Контролер не змінює Kubernetes Endpoints, а генерує в блоці server Nginx спеціальний upstream, у який відправляє частину запитів.
  • Пріоритет правил при їх спільному використанні:
    1. canary-by-header: найвищий пріоритет. Якщо запит містить заголовок (наприклад, X-Canary: always), він завжди спрямовується на canary, незалежно від відсоткової ваги.
    2. canary-by-cookie: середній пріоритет (за значенням cookie).
    3. canary-weight: найнижчий пріоритет. Застосовується методом рандомізації лише до запитів, які не потрапили під правила заголовків або cookie.

3. Чому для реалізації WebSocket через Nginx Ingress потрібні спеціальні налаштування таймаутів, і що відбувається за замовчуванням?

Відповідь: Протокол WebSocket починається з HTTP Upgrade, після чого з’єднання перетворюється на довгоживучий двонаправлений TCP-тунель:

  • За замовчуванням у Nginx Ingress параметри proxy-read-timeout та proxy-send-timeout дорівнюють 60s.
  • Якщо між клієнтом і сервером немає безперервного обміну повідомленнями протягом 60 секунд, Nginx примусово обриває TCP-з’єднання з клієнтом.
  • Для стабільної роботи WebSocket у маніфест Ingress обов’язково додають анотації:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    

    а також налаштовують відправку Ping/Pong фреймів на рівні Java-сервера (Netty / Spring WebSocket).


4. У чому полягає загроза безпеки при використанні анотації configuration-snippet у Nginx Ingress, і чому багато хмарних провайдерів відключають її за замовчуванням?

Відповідь: Анотація nginx.ingress.kubernetes.io/configuration-snippet дозволяє вставляти довільний синтаксис директив Nginx прямо в тіло конфігураційного файлу.

  • Вразливість (CVE-2021-25742 / CVE-2023-5043): розробник, який має права на створення Ingress у своєму обмеженому namespace, може впровадити довільний код на Lua або директиви Nginx, що дозволяють прочитати приватні SSL-сертифікати інших орендарів кластера, отримати токени сервісних акаунтів контролера з файлової системи /var/run/secrets/ або здійснити Server-Side Request Forgery (SSRF).
  • У сучасних версіях фреймворку опція allow-snippet-annotations за замовчуванням відключена в ConfigMap контролера з міркувань безпеки.

🎯 Шпаргалка для інтерв’ю

Головне про Ingress

  • Суть: L7 (HTTP/HTTPS) зворотний проксі для маршрутизації зовнішнього трафіку за доменами та шляхами.
  • Ingress Resource vs Controller: YAML-маніфест пасивний; трафік проксіює активний процес (Ingress Controller — Nginx, Traefik, Envoy).
  • Економія: 1 хмарний балансувальник перед контролером обслуговує десятки й сотні сервісів ClusterIP.
  • TLS Termination: сертифікати зберігаються в K8s Secret і автоматично перевипускаються через Cert-Manager.
  • Проблема Nginx Reload: часті деплої викликають шторм перезавантажень Nginx; альтернатива — Envoy з динамічним xDS API.
  • Майбутнє: Kubernetes Gateway API (GA в K8s 1.28+) замінює Ingress завдяки типізованому рольовому API.

Ingress vs Service LoadBalancer

| Параметр | Service (type: LoadBalancer) | Ingress | | :— | :— | :— | | Рівень OSI | L4 (TCP / UDP) | L7 (HTTP / HTTPS / gRPC) | | Маршрутизація | Тільки за портами | За доменами (host), шляхами (path), заголовками | | Керування SSL | На рівні хмари або подів | Централізована термінація на вході | | Вартість у хмарі | Плата за кожен сервіс | Плата за один зовнішній балансувальник |

Червоні прапорці на співбесіді (Чого говорити не можна)

  • ❌ «Ingress — це балансувальник четвертого рівня для TCP з’єднань» — Ingress працює виключно на прикладному рівні L7 (HTTP/HTTPS).
  • ❌ «Якщо застосувати маніфест Ingress, він сам почне скеровувати трафік без будь-яких контролерів» — без запущеного Ingress Controller маніфест абсолютно марний.
  • ❌ «Для кожного мікросервісу в кластері ми створюємо окремий хмарний LoadBalancer» — антипатерн, що веде до величезних необґрунтованих витрат.

Пов’язані питання