Kubernetes Gateway API на GKE: миграция с Ingress

Недавно мы перевели наш производственный кластер GKE с традиционного Ingress-контроллера на Kubernetes Gateway API — и, честно говоря, стоило сделать это раньше. Ниже — всё, что нужно знать: что такое Gateway API, почему мы решились на переход и как настроить его самостоятельно шаг за шагом.

Проблема Kubernetes Ingress (и почему его никогда не хватало по-настоящему)

Если вы достаточно долго эксплуатируете Kubernetes в production, вы наверняка хорошо знакомы с ресурсом Ingress. С 2015 года он считается де-факто стандартом маршрутизации внешнего HTTP/HTTPS-трафика в кластер. Простой, привычный, повсеместно поддерживаемый — он справлялся со своей задачей. Какое-то время.

Сравнение Kubernetes Ingress и Gateway API

Но по мере того как наши приложения усложнялись, начали проявляться трещины.

Каждый раз, когда требовалось что-то большее, чем базовая маршрутизация по хосту или пути — разделение трафика для канареечных релизов, маршрутизация по заголовкам, более гибкое управление TLS — мы утопали в кладбище вендорозависимых аннотаций. Хотите включить канареечные релизы в NGINX? Это nginx.ingress.kubernetes.io/canary: "true". Переходите на другой контроллер? Начинайте заново. Ничего из этого не было переносимым.

Ресурс Ingress задумывался намеренно минималистичным — тонкая абстракция над L7-маршрутизацией с ограниченными возможностями расширения. Он просто не был рассчитан на современный мир с несколькими командами, протоколами и окружениями.

Мы были не одиноки в этом. Запланированное устаревание поддерживаемого сообществом Ingress-NGINX Controller (ориентировочно в 2026 году) превращает дискуссию «Ingress против Gateway API» из теоретической в насущную операционную необходимость. Использование неподдерживаемого Ingress-контроллера создаёт непосредственные риски: незакрытые CVE, расхождение API с новыми версиями Kubernetes и ухудшение совместимости с развивающимися сетевыми примитивами.

Этого оказалось достаточно, чтобы действовать. Встречайте: Kubernetes Gateway API.

Что такое Kubernetes Gateway API?

В ноябре 2023 года вышел Kubernetes Gateway API v1.0 — значимая веха для проекта, который создавался четыре года. Результатом этой работы — признанной наиболее коллаборативным API в истории Kubernetes — стал стандартизированный способ управления сетевым трафиком, устраняющий ограничения традиционного Ingress в плане гибкости и расширяемости.

Gateway API достиг статуса v1.0 в конце 2023 года и с тех пор набирает популярность. Он спроектирован так, чтобы напрямую решать недостатки Ingress — предлагая более гибкий, расширяемый и мощный фреймворк.

Gateway API — это открытый стандарт для сетевого взаимодействия сервисов (service networking). Он развивает ресурс Ingress и улучшает его по нескольким направлениям: архитектура ориентирована на роли — API-ресурсы соответствуют организационным ролям оператора кластера, разработчика и поставщика инфраструктуры. Помимо этого, стандарт переносим: существует множество реализаций, что обеспечивает единообразие ключевых концепций и ресурсов в разных реализациях и средах.

Хронология говорит сама за себя:

2015 → Представлен Ingress (v1beta1)
2019 → Ingress становится GA (v1)
2020 → Начало проекта Gateway API
2023 → Gateway API v1.0 GA
2024 → Gateway API v1.1 с расширенными возможностями
2025 → Gateway API получает широкое распространение
2026 → Gateway API рекомендован для всех новых кластеров

Основные строительные блоки: GatewayClass, Gateway и HTTPRoute

Gateway API вводит модульную структуру с чёткими ролями — поставщик инфраструктуры, оператор кластера и разработчик приложения — и новые ресурсы: GatewayClass, Gateway и HTTPRoute.

Представьте это как чистое разделение ответственности между тремя персонами:

GatewayClass — в зоне ответственности поставщика инфраструктуры. Это ресурс уровня кластера, определяющий класс шлюзов и контроллер, который ими управляет. В GKE компания Google предоставляет готовые GatewayClass-ы, например gke-l7-global-external-managed и gke-l7-rilb. Вы выбираете класс, соответствующий вашим потребностям по трафику.

# GKE предоставляет их из коробки — создавать их не нужно
# Примеры доступных GatewayClass на GKE:
# gke-l7-global-external-managed   → Внешний глобальный Application LB
# gke-l7-regional-external-managed → Внешний региональный Application LB
# gke-l7-rilb                      → Внутренний Application LB

Gateway — в зоне ответственности оператора кластера. Этот ресурс определяет, где и как балансировщик нагрузки принимает трафик — какие порты, протоколы и пространства имён разрешены.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: default
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same

HTTPRoute — в зоне ответственности разработчика приложения. Здесь живут правила маршрутизации — сопоставление хостов и путей, разделение трафика, перезапись заголовков и многое другое.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app-route
  namespace: default
spec:
  parentRefs:
    - name: my-gateway
  hostnames:
    - "myapp.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: frontend-service
          port: 80

Эта трёхуровневая модель меняет правила игры для крупных команд. Инженеры платформы управляют Gateway (а значит, и балансировщиком нагрузки), тогда как разработчики приложений самостоятельно управляют своими HTTPRoute — больше не нужно ждать, пока инфраструктурная команда внесёт каждое изменение маршрутизации.

Почему Gateway API превосходит Ingress: разбор по функциям

1. Никакого ада из аннотаций

В Ingress продвинутые функции требовали контроллерозависимых аннотаций. Нужны канареечные деплои с NGINX? Аннотации. Нужна ограничение частоты запросов в Traefik? Другие аннотации. Переходите на другой контроллер? Переписывайте всё заново.

Gateway API избавляет от этой перегрузки аннотациями — все эти возможности встроены непосредственно в спецификацию, делая конфигурации чище и переносимее.

2. Нативное разделение трафика для канареечных и сине-зелёных деплоев

Это была одна из наших главных болей с Ingress. В HTTPRoute разделение трафика является полноценным гражданином первого класса:

rules:
  - backendRefs:
      - name: app-v1
        port: 80
        weight: 90
      - name: app-v2
        port: 80
        weight: 10

Это канареечное разделение 90/10. Без аннотаций. Без кастомных CRD. Просто чистый декларативный YAML.

3. Поддержка нескольких протоколов

В отличие от Ingress, Gateway API не привязан к протоколу и поддерживает HTTP, TCP, gRPC и другие. Ingress работал исключительно с HTTP/HTTPS. Если требовалась маршрутизация TCP или UDP, приходилось рассчитывать только на себя — используя нестандартные расширения контроллеров.

4. Разделение по ролям (дружественное к RBAC)

Ролевая архитектура позволяет операторам кластера определять, как общая инфраструктура может использоваться множеством независимых команд разработчиков. Это напрямую транслируется в более тонкий RBAC: дайте разработчикам права на создание HTTPRoute в их пространстве имён, но не Gateway. Команды безопасности это оценят.

5. Маршрутизация между пространствами имён

Gateway API нативно поддерживает маршрутизацию от одного Gateway через несколько пространств имён с помощью allowedRoutes. Никаких хаков, никаких обходных путей.

6. Встроенная поддержка east-west трафика

Он обрабатывает как north-south, так и east-west трафик — то есть управляет и внешним входящим трафиком, и межсервисным взаимодействием внутри кластера, снижая потребность в отдельной сервисной сетке для простых сценариев.

7. Переносимость между облачными провайдерами

Поскольку это стандарт CNCF с едиными базовыми ресурсами, конфигурации, написанные для GKE, в значительной мере работают и на EKS, AKS или в кластерах on-prem. Команда приобретает один универсальный набор навыков.

Настройка Gateway API на GKE: шаг за шагом

Перейдём к практике. Вот точная инструкция по включению и использованию Gateway API на кластере GKE.

Предварительные требования

  • Кластер GKE версии 1.24 или выше

  • Установленный и аутентифицированный gcloud CLI

  • kubectl, настроенный для работы с вашим кластером

  • Кластер с VPC-native (alias IP) — обязательное условие для GKE Gateway

Шаг 1: Включите Gateway API на кластере GKE

Поддержка Gateway API поставляется вместе с GKE, но требует явного включения.

Для нового кластера:

gcloud container clusters create my-cluster \
  --gateway-api=standard \
  --region=us-central1 \
  --enable-ip-alias \
  --project=YOUR_PROJECT_ID

Для существующего кластера:

gcloud container clusters update my-cluster \
  --gateway-api=standard \
  --region=us-central1 \
  --project=YOUR_PROJECT_ID

💡 Флаг --gateway-api=standard включает стандартный канал Gateway API, который включает CRD для HTTPRoute, Gateway и GatewayClass.

Шаг 2: Проверьте установку CRD и GatewayClass

# Убедитесь, что CRD Gateway API существуют
kubectl get crd | grep gateway
# Ожидаемый вывод включает:
# gateways.gateway.networking.k8s.io
# httproutes.gateway.networking.k8s.io
# gatewayclasses.gateway.networking.k8s.io
# Проверьте доступные GatewayClass, предоставленные GKE
kubectl get gatewayclass

Вы должны увидеть управляемые GKE GatewayClass-ы, например:

NAME                                  CONTROLLER
gke-l7-global-external-managed       networking.gke.io/gateway
gke-l7-regional-external-managed     networking.gke.io/gateway
gke-l7-rilb                          networking.gke.io/gateway
gke-l7-regional-internal-managed     networking.gke.io/gateway

Шаг 3: Разверните тестовое приложение

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whereami
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whereami
  template:
    metadata:
      labels:
        app: whereami
    spec:
      containers:
        - name: whereami
          image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.22
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: whereami-svc
  namespace: default
spec:
  selector:
    app: whereami
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP
EOF

Шаг 4: Создайте ресурс Gateway

# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: external-gateway
  namespace: default
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same
kubectl apply -f gateway.yaml
# Наблюдайте за получением IP-адреса Gateway (может занять 1-2 минуты)
kubectl get gateway external-gateway --watch

После подготовки в столбце ADDRESS появится IP-адрес. GKE автоматически создаёт Google Cloud Load Balancer за кулисами.

Шаг 5: Создайте HTTPRoute

# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whereami-route
  namespace: default
spec:
  parentRefs:
    - name: external-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: whereami-svc
          port: 80
kubectl apply -f httproute.yaml

Шаг 6: Проверьте работу

# Проверьте статус Gateway
kubectl describe gateway external-gateway
# Ищите: Status > Conditions > Programmed: True
# Получите внешний IP
GATEWAY_IP=$(kubectl get gateway external-gateway \
  -o jsonpath='{.status.addresses[0].value}')
# Протестируйте эндпоинт
curl http://$GATEWAY_IP/

Вы должны увидеть JSON-ответ от приложения whereami, подтверждающий прохождение трафика через Gateway.

Шаг 7 (бонус): Добавьте терминирование TLS

# Создайте TLS-секрет (замените на реальные сертификат и ключ)
kubectl create secret tls my-tls-secret \
  --cert=path/to/cert.pem \
  --key=path/to/key.pem
# Обновите Gateway, добавив HTTPS-листенер
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: external-gateway
  namespace: default
spec:
  gatewayClassName: gke-l7-global-external-managed
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: my-tls-secret
      allowedRoutes:
        namespaces:
          from: Same

В GKE можно также использовать управляемые Google сертификаты с аннотацией networking.gke.io/managed-certificates на Gateway для автоматической выдачи сертификатов.

Ingress и Gateway API: краткое сравнение

Функция Ingress Gateway API

Разделение трафика

Через аннотации (нестандартно)

Нативное (веса в HTTPRoute)

Поддержка протоколов

Только HTTP/HTTPS

HTTP, TCP, gRPC, TLS, UDP

Разделение ролей

Отсутствует — единый ресурс

GatewayClass / Gateway / Route

Канареечные деплои

Зависит от контроллера

Встроено

Маршрутизация между namespace

Ограничена / с костылями

Нативная

Переносимость

Низкая (зависит от аннотаций)

Высокая (стандарт CNCF)

Маршрутизация по заголовкам

Через аннотации

Нативная

East-west трафик

Не поддерживается

Поддерживается

Гранулярность RBAC

Грубая

Тонкая, на уровне ресурса

Наш опыт после миграции

Перевод наших производственных нагрузок GKE с Ingress на Gateway API не случился за одну ночь — около трёх недель мы работали параллельно с обоими решениями, постепенно перенося маршруты. Но результаты не заставили себя ждать:

  • Чистые манифесты. Наши YAML-файлы Ingress содержали десятки аннотаций nginx.ingress.kubernetes.io/*. Файлы HTTPRoute понятны и читаемы для любого члена команды.

  • Автономия разработчиков. Команды приложений теперь управляют своими HTTPRoute, не затрагивая Gateway. Количество тикетов к инфраструктурной команде заметно снизилось.

  • Надёжные канареечные деплои. Раньше мы с трудом собирали канареечные пайплайны из Argo Rollouts и аннотаций Ingress. Маршрутизация на основе весов в HTTPRoute существенно упростила этот процесс.

  • Интеграция с Google Cloud LB. GKE создаёт балансировщики нагрузки, реализующие конфигурацию из ресурса Gateway, — а значит, мы получаем полную мощь Cloud Load Balancing: Cloud Armor, CDN, IAP — всё это нативно связано с нашей конфигурацией маршрутизации.

Стоит ли мигрировать?

Если вы используете GKE и всё ещё работаете с Ingress-контроллером — ответ: да, и чем раньше, тем лучше. Успешная миграция предполагает аудит текущей конфигурации Ingress, конвертацию настроек и постепенное внедрение изменений.

Gateway API рекомендован для новых кластеров начиная с 2026 года. Сам Google позиционирует его как предпочтительный путь для HTTP(S)-трафика в GKE на перспективу.

Начните с малого. Возьмите один сервис, создайте HTTPRoute рядом с существующим Ingress, проверьте трафик — и расширяйте охват. Порог входа реален, но невысок, а выигрыш в гибкости, переносимости и опыте разработчиков того определённо стоит.

© 2026 meganuke