← Kubernetes: сеть
8 мин · средне · Урок 8 из 8

Gateway API: HTTPRoute

Почему роутинг разнесли на GatewayClass, Gateway и HTTPRoute и чем это отличается от Ingress.

Что не так с Ingress

Ingress работает десять лет и никуда не уходит. Он по-прежнему GA, его всё ещё используют повсюду, и в кластере его никто не запрещает. Но у него есть три неудобства, которые накапливаются с ростом команды.

Первое: один объект описывает сразу всё. Хосты, пути, TLS, иногда даже backend-параметры через аннотации. Тот, кто пишет Ingress, должен знать и про инфру (порты listener-а, сертификаты), и про роутинг своего Service.

Второе: расширения через аннотации. nginx.ingress.kubernetes.io/..., traefik.ingress.kubernetes.io/.... Переехал с одного контроллера на другой и половина YAML стала мусором. Именно так и вышло: ingress-nginx, чьи аннотации разошлись по всем гайдам, сняли с поддержки в марте 2026, и теперь эти строки надо переписывать под другую реализацию.

Третье: только HTTP/HTTPS. TCP, UDP, gRPC, mTLS заворачивают через те же аннотации или CRD-расширения от конкретного вендора.

Gateway API чинит это иначе: вместо одного объекта вводит три, с разными владельцами.

Три роли, три объекта

HTTPRoute ссылается на обычный Service типа ClusterIP, ровно так же, как это делал Ingress. Новое здесь только разделение самого входа.

  GatewayClass: traefik          <- админ кластера выбрал имплементацию
       |
       v
  Gateway: traefik-gateway       <- ops владеет, в kube-system
       |  listens :80, *.example.com
       v
  HTTPRoute: helloroute          <- команда приложения владеет, в своём ns
       |  hostnames: [helloapp.example.com]
       |  backendRefs: [helloapp:8080]
       v
  Service helloapp -> Pods

GatewayClass определяет, какой контроллер будет обрабатывать трафик (Traefik, Cilium, Istio, NGINX Gateway Fabric). Создаёт админ кластера один раз. Разработчику он нужен, только чтобы убедиться, что нужный контроллер вообще установлен.

Gateway это реальный listener: на каком порту слушаем, на каких хостах, какой TLS. Создаёт инфра-команда. Лежит обычно в kube-system или отдельном gateway-system. Некоторые контроллеры создают его сами, когда включена поддержка Gateway API.

HTTPRoute правила приложения: какие хостнеймы и пути ловить, куда форвардить. Создаёт разработчик в своём namespace. Цепляется к Gateway через parentRefs.

Идея простая: ops держит входную дверь, разработчики раздают ключи к своим комнатам. Раньше всё было заперто в одной квартире.

Минимальный HTTPRoute

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: helloroute
spec:
  parentRefs:
    - name: traefik-gateway
      namespace: kube-system
  hostnames:
    - helloapp.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: helloapp
          port: 8080

Ключевые поля:

CRD Gateway API в кластере не установлены: kubectl get httproute отвечает error: no matches for kind "HTTPRoute". Ставят Gateway API CRDs.

Сравнение с Ingress

Что делаетIngressHTTPRoute
HTTP routingдада
TCP/UDP/TLS/gRPCчерез аннотации/CRD вендораотдельные типы Route
Hostrules[].hostspec.hostnames[]
Path matchpathType: Prefix/Exactpath.type: PathPrefix/Exact/RegularExpression
Несколько backend-ов с весамичерез аннотацииbackendRefs[].weight в спеке
Cross-namespace backendчерез аннотацииbackendRefs.namespace + ReferenceGrant
Модификация заголовков/redirectчерез аннотацииfilters в спеке
Стандарт между вендорамиминимальныйconformance suite
СтатусGA, не deprecatedGA с Gateway API v1.0, активно растёт

Ingress никуда не делся. Если на Service приходится один Ingress и всем владеет одна команда, переезжать не нужно. Gateway API даёт смысл там, где больше двух команд или появляются не-HTTP протоколы.

Что реально нужно

Gateway API уже стал тем направлением, куда двигается экосистема. Толчок дал конец ingress-nginx: контроллер, на котором сидела половина кластеров, сняли с поддержки в марте 2026, и командам пришлось выбирать замену. Почти все живые реализации сегодня делают ставку на Gateway API, а для переезда есть утилита ingress2gateway, которая генерирует HTTPRoute из готовых Ingress.

Ingress при этом читать всё равно надо: он GA, не deprecated, и его манифесты будут попадаться ещё годами. Но новое проектируют на HTTPRoute. Фундамент прежний, Service и NetworkPolicy, а Gateway API стоит слоем выше и занимается только входящим трафиком.

Что часто ломается

Команды для разведки

kubectl get gatewayclass
# traefik

kubectl get gateway -A
# kube-system/traefik-gateway   traefik   Programmed=True

kubectl get httproute -A
# HTTPRoute со списком hostname-ов

kubectl describe httproute helloroute
# смотреть в status.parents[0].conditions:
#   Accepted=True означает, что Gateway согласился обрабатывать route
#   ResolvedRefs=True означает, что Service найден и порт валидный
Filters: header rewrite, redirect, URL rewrite, mirror

В rules[].filters живут модификаторы запроса. Самые ходовые:

  • RequestHeaderModifier: добавить или удалить заголовки в запросе.
  • ResponseHeaderModifier: то же для ответа.
  • URLRewrite: поменять host или path до бэкенда. Удобно, когда внешний путь /api/users, а Service ждёт /users.
  • RequestRedirect: отдать 301/302 без обращения к backend.
  • RequestMirror: копию запроса в другой backend для shadow-тестов.

Пример URLRewrite:

rules:
  - matches:
      - path: { type: PathPrefix, value: /api }
    filters:
      - type: URLRewrite
        urlRewrite:
          path:
            type: ReplacePrefixMatch
            replacePrefixMatch: /
    backendRefs:
      - name: api-service
        port: 80
Canary через backendRefs

В Gateway API сплит трафика встроен прямо в спеку:

backendRefs:
  - name: helloapp-v1
    port: 8080
    weight: 90
  - name: helloapp-v2
    port: 8080
    weight: 10

С Ingress такое делали через аннотации или два отдельных Ingress, что часто приводило к гонкам.

Домашка

Теорию закрепляет задание на своём кластере: 2 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-gateway-basics     # развернуть стартовое состояние
./run.sh verify k8s-gateway-basics    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.