🐳 Раздел 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» — антипаттерн, ведущий к огромным необоснованным затратам.

Связанные вопросы