Краткий обзор Kubernetes Gateway API

Nicolas Fränkel

Nicolas Fränkel

September 7, 2022

Ecosystem

В одном из моих недавних постов в блоге я описал несколько способов доступа к подам Kubernetes. Можно получить доступ к поду через его IP, но поды по своей природе недолговечны. Основной способ — настроить Service: его IP стабилен, и задача Kubernetes — поддерживать актуальное соответствие между Service и его подлежащими подами. Доступны различные виды сервисов: только внутренние, NodePort, который позволяет доступ извне кластера, и LoadBalancer, который зависит от стороннего компонента — обычно от облачного провайдера. Наконец, я упомянул объект Ingress, который также позволяет маршрутизацию.

Я намеренно не упомянул новичка в этой области — Gateway API. Это тема данного поста.

От Ingress к Gateway API

Внешний доступ к подам Kubernetes прошел несколько этапов эволюции, например, Ingress — это ответ на проблему отсутствия маршрутизации в LoadBalancer. Самая большая проблема Ingress — это его зависимость от "проприетарных" объектов. В качестве напоминания, вот фрагмент для создания маршрутизации с использованием Apache APISIX:

apiVersion: apisix.apache.org/v2beta3 #1 kind: ApisixRoute #1 metadata: name: apisix-route spec: http: - name: left match: paths: - "/left" backends: - serviceName: left servicePort: 80 - name: right match: paths: - "/right" backends: - serviceName: right servicePort: 80
  1. Проприетарные объекты

Проприетарные объекты являются проблемой при миграции. Хотя миграция с одного провайдера на другой, вероятно, редка, она должна быть максимально безболезненной. При использовании проприетарных объектов сначала необходимо сопоставить старые объекты с новыми. Вероятно, это не будет однозначным соответствием. Затем нужно перевести спецификацию в новую модель: это, скорее всего, будет полноценный проект.

Идея Gateway API заключается в четком разделении стандартных объектов и проприетарной реализации.

Gateway API

Gateway API — это проект с открытым исходным кодом, управляемый сообществом SIG-NETWORK. Это набор ресурсов, которые моделируют сетевое взаимодействие сервисов в Kubernetes. Эти ресурсы — GatewayClass, Gateway, HTTPRoute, TCPRoute, Service и т.д. — направлены на развитие сетевого взаимодействия сервисов Kubernetes через выразительные, расширяемые и ориентированные на роли интерфейсы, которые реализованы многими поставщиками и имеют широкую поддержку в отрасли.

-- https://gateway-api.sigs.k8s.io

Вышеупомянутое определение также упоминает организационный аспект: разные роли должны управлять разными наборами объектов.

Модель Gateway API

Изображение с gateway-api.sigs.k8s.io

Действительно, задачи оператора кластера и разработчика довольно разные. Это очень похоже на старые Java EE серверы приложений, которые предлагали спецификацию, организованную вокруг ролей: разработчики, развертывающие и операторы. По моему мнению, самое большое отличие заключается в том, что спецификация была в основном сосредоточена на опыте разработчика; остальное было на усмотрение реализаторов. Gateway API, похоже, заботится обо всех персонах.

Настройка доступа к подам через Gateway API

Давайте заменим ранее настроенный Ingress на Gateway API. Для этого необходимо выполнить несколько шагов.

Установка новых CRD Gateway

k apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.0/standard-install.yaml

Установка реализации

Я буду использовать Apache APISIX. Альтернативно, на сайте SIG поддерживается список реализаций.

helm install apisix apisix/apisix \ --namespace ingress-apisix \ --create-namespace \ --devel \ #1 --set gateway.type=NodePort \ #2 --set gateway.http.nodePort=30800 \ #2 --set ingress-controller.enabled=true \ #2 --set ingress-controller.config.kubernetes.enableApiGateway=true \ #3 --set ingressPublishService="ingress-apisix/apisix-gateway" #4
  1. Без опции --devel Helm устанавливает последний релиз, который не работает с Gateway API
  2. Gateway должен быть доступен извне кластера в любом случае
  3. Здесь происходит магия!
  4. Я вернусь к этому позже

Проверим, что все работает:

k get all -n ingress-apisix
NAME READY STATUS RESTARTS AGE pod/apisix-5fc9b45c69-cf42m 1/1 Running 0 14m #1 pod/apisix-etcd-0 1/1 Running 0 14m #2 pod/apisix-etcd-1 1/1 Running 0 14m #2 pod/apisix-etcd-2 1/1 Running 0 14m #2 pod/apisix-ingress-controller-6f8bd94d9d-wkzfn 1/1 Running 0 14m #3 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) service/apisix-admin ClusterIP 10.96.69.19 <none> 9180/TCP service/apisix-etcd ClusterIP 10.96.226.79 <none> 2379/TCP,2380/TCP service/apisix-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP service/apisix-gateway NodePort 10.96.101.224 <none> 80:30800/TCP #4 service/apisix-ingress-controller ClusterIP 10.96.141.230 <none> 80/TCP
  1. Сам Apache APISIX
  2. Apache APISIX хранит свою конфигурацию в etcd. По умолчанию чарт планирует три пода, что является хорошей практикой для обработки сбоев в распределенных системах
  3. Контроллер Apache APISIX: контроллер Kubernetes — это цикл управления, который приводит существующее состояние к желаемому
  4. Сервис Gateway Apache APISIX: это NodePort Service, который мы установили через Helm Chart. Это также имя, на которое мы ссылались во время установки Helm Chart — ingressPublishService

На этом этапе инфраструктура готова.

Объявление реализации Gateway

Как я упоминал выше, API делает четкое разделение между спецификацией и реализацией. Однако нам нужно каким-то образом связать их. Это задача объекта GatewayClass:

apiVersion: gateway.networking.k8s.io/v1alpha2 #1 kind: GatewayClass #2 metadata: name: apisix-gateway-class #3 spec: controllerName: apisix.apache.org/gateway-controller #4
  1. Мы намеренно не используем последнюю версию, так как Apache APISIX использует эту версию. Учтите, что она будет развиваться в (ближайшем) будущем
  2. Объект GatewayClass
  3. Назовите его как угодно; однако мы будем использовать его позже для ссылки на класс шлюза
  4. Имя контроллера зависит от реализации. Здесь мы используем Apache APISIX.

Обратите внимание, что GatewayClass имеет область действия на уровне кластера. Эта модель позволяет нам объявлять различные реализации Gateway API и использовать их параллельно внутри одного кластера.

Создание Gateway

С Apache APISIX это довольно просто:

apiVersion: gateway.networking.k8s.io/v1alpha2 #1 kind: Gateway #2 metadata: name: apisix-gateway spec: gatewayClassName: apisix-gateway-class #3 listeners: #4 - name: http protocol: HTTP port: 80
  1. Тот же неймспейс, что и выше
  2. Объект Gateway
  3. Ссылка на ранее объявленный класс шлюза
  4. Позволяет накладывать некоторые ограничения на этом уровне, чтобы оператор кластера мог избежать нежелательного использования

Предупреждение: Gateway API предусматривает возможность динамического изменения порта на стороне оператора. На момент написания этого поста выделение портов в Apache APISIX является статическим. Планируется сделать его динамическим в будущем. Подпишитесь на этот GitHub issue, чтобы следить за прогрессом.

Маршруты, маршруты, маршруты повсюду

До сих пор все было инфраструктурой; наконец, мы можем настроить маршрутизацию.

Я хочу ту же маршрутизацию, что и в предыдущем посте; ветка /left и ветка /right. Я пропущу последнюю для краткости.

apiVersion: gateway.networking.k8s.io/v1alpha2 #1 kind: HTTPRoute #2 metadata: name: left spec: parentRefs: - name: apisix-gateway #3 rules: - matches: #4 - path: #4 type: PathPrefix #4 value: /left backendRefs: #5 - name: left #5 port: 80 #5
  1. Тот же неймспейс, что и выше
  2. Объект HTTPRoute
  3. Ссылка на созданный выше Gateway
  4. Правила соответствия. В нашем случае мы сопоставляем по префиксу пути, но доступно множество правил. Можно сопоставлять по параметру запроса, по заголовку и т.д.
  5. "Восходящий" сервис для перенаправления. Мы определили left Service в предыдущем посте в блоге.

Проверка работы

Теперь, когда мы настроили наши маршруты, мы можем проверить, что все работает.

curl localhost:30800/left

Когда мы устанавливали Helm chart, мы указали Apache APISIX создать NodePort сервис на порту 30800. Следовательно, мы можем использовать этот порт для доступа к сервису извне кластера.

left

Заключение

Доступно множество альтернатив для доступа к поду извне кластера. CNCF добавил большинство из них, чтобы улучшить предыдущие подходы.

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

Полный исходный код для этого поста можно найти на GitHub.

Для дальнейшего изучения:

Tags: