Основное про API-шлюз в Kubernetes

от автора

Существует множество альтернатив для доступа к модулю извне кластера. Шлюз API — это определенно новинка этой области, и потому выбран темой этой статьи.

Ранее мы описывали несколько способов доступа к модулям Kubernetes. Так, например, доступ к модулю pods можно получить через его IP-адрес, но важно учитывать, что поды по своей сути являются временными. Штатный способ — настроить Service: в этом случае IP-адрес стабилен, а задача Kubernetes — обеспечивать мапироание между Service и соответствующими ей подами. В настоящий момент доступны различные виды сервисов: только внутренние, NodePort, позволяющий открыть доступа извне кластера, и LoadBalancer, который полагается на сторонний компонент — обычно это на облачный провайдер. Не будем забывать и об Ingress, обеспечивающем маршрутизацию.

Ну а API-шлюз, как новинку в этой области, мы оставили на десерт, решив посвятить ему целый пост.

От Ingress к 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: Проприетарные объекты

Проприетарные объекты определенно являются проблемой при осуществлении миграции. Хотя миграция от одного поставщика к другому встречается довольно редко, тем не менее она должна быть максимально плавной. При использовании проприетарных объектов сначала необходимо сопоставить старые объекты с новыми. Существует большая вероятность того, что мапирование «one-to-one» в данном случае может не получиться. Затем важно перевести спецификацию в новую модель, что превращает весь процесс в полноценный сложный проект.

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

API-шлюз

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

Kubernetes Gateway API Introduction

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

Действительно, задачи оператора кластера и девелопера довольно сильно отличаются друг от друга. Это чем-то напоминает старые серверы приложений Java EE, которые предлагали спецификацию, организованную вокруг ролей: девелоперы, deploy-специалисты и операторы. ИМХО, наиболее существенное отличие заключается в том, что спецификация была ориентирована в основном на опыт девелоперов; остальное зависело от исполнителей. Шлюз API, в свою очередь, не оставляет без внимания ни одну сторону.

Настройка доступа к поду через API-шлюз

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

Установите новые CRD для шлюза

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

Установите Implementation

Я буду использовать 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 устанавливает последнюю версию, которая не работает с API-шлюза.

#2: Шлюз в любом случае должен быть доступен за пределами кластера.

#3: Здесь происходит волшебство!

#4: Мы вернемся к этому позже.

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

k get all -n ingress-apisix
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 API SIX.

#2: Apache API SIX хранит свою конфигурацию в etcd. На диаграмме по умолчанию запланировано три пода, что вполне практично для разрешения неполадок в распределенных системах.

#3: Контроллер Apache API SIX: Контроллер Kubernetes — это цикл управления, который преобразовывает существующее состояние в желаемое.

#4: Служба Apache APISIX: Это служба NodePortService, которую мы установили через Helm Chart. Это также имя, на которое мы ссылались во время установки ingressPublishService в Helm Chart. На данном этапе вся инфраструктура готова.

Реализация

Как уже упоминалось выше, 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 API SIX работает с этой версией. Но даже не сомневайтесь, что в самом ближайшем будущем все обновится.

#2: Объект GatewayClass.

#3: Назовите его так, как вы хотите; однако позже мы будем использовать его для ссылки на класс шлюза.

#4: Имя контроллера зависит от реализации. В данном случае мы используем Apache APISIX.

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

Создание шлюза

Благодаря Apache API SIX здесь все довольно просто:

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: Тот же namespace, что и выше.

#2: Объект Gateway.

#3: Ссылка на класс шлюза, обозначенная ранее.

# 4: Разрешите некоторые ограничения на этом уровне, чтобы оператор кластера имел возможность избежать нежелательного использования.

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

Маршрутизация, маршрутизация и еще раз маршрутизация

До этого момента речь велась об инфраструктуре, и наконец-то мы добрались до маршрутизации.

Я хочу поработать с тем же маршрутом, что и в предыдущем посте: бранчи  /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. Совпадение правил (rules). В нашем случае мы сопоставляем префикс пути, но возможны разные вариации правил. Вы можете сопоставлять их на базе параметра запроса, заголовка и т.д.

  5. «Вышестоящий» сервер для переадресации. В предыдущем посте мы как раз давали определение leftService.

Проверяем в работе

Отстроив процессы маршрутизации, самое время проверить как все работает.

curl localhost:30800/left

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

left

Подведем итоги

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

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

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

P.S.: Кстати, подписывайтесь на наш телеграм-канал DevOps FM, кроме переводов мы публикуем там много авторских статей и новостей по теме DevOps: добро пожаловать к нам в комьюнити)


ссылка на оригинал статьи https://habr.com/ru/articles/690934/