Uma Breve Visão sobre a Kubernetes Gateway API

Nicolas Fränkel

Nicolas Fränkel

September 7, 2022

Ecosystem

Em um dos meus posts recentes no blog, descrevi várias maneiras de acessar pods do Kubernetes. É possível acessar um pod por meio de seu IP, mas os pods são naturalmente transitórios. A maneira nominal é configurar um Service: seu IP é estável, e o trabalho do Kubernetes é manter o mapeamento entre um Service e seus pods subjacentes atualizado. Diferentes tipos de serviços estão disponíveis: apenas internos, NodePort para finalmente permitir o acesso de fora do cluster, e LoadBalancer que depende de um componente de terceiros - geralmente, um provedor de nuvem. Por fim, mencionei o objeto Ingress, que também permite roteamento.

Deliberadamente, deixei de fora o novo recurso, a API Gateway. Este é o tema deste post.

De Ingress para a API Gateway

O acesso externo aos pods do Kubernetes passou por várias etapas evolutivas, e.g., o Ingress é a resposta para o problema da falta de roteamento no LoadBalancer. O maior problema do Ingress é sua dependência de objetos "proprietários". Como lembrete, aqui está o trecho para criar roteamento usando o 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. Objetos proprietários

Objetos proprietários são um problema durante a migração. Embora a migração de um provedor para outro seja provavelmente incomum, ela deve ser o mais tranquila possível. Ao usar objetos proprietários, você primeiro precisa mapear do objeto antigo para os novos. As chances são de que não seja um mapeamento um-para-um. Em seguida, você precisa traduzir a especificação para o novo modelo: é provável que seja um projeto completo.

A ideia por trás da API Gateway é ter uma separação clara entre objetos padrão e a implementação proprietária.

A API Gateway

A API Gateway é um projeto de código aberto gerenciado pela comunidade SIG-NETWORK. É uma coleção de recursos que modelam a rede de serviços no Kubernetes. Esses recursos - GatewayClass, Gateway, HTTPRoute, TCPRoute, Service, etc - visam evoluir a rede de serviços do Kubernetes por meio de interfaces expressivas, extensíveis e orientadas a funções que são implementadas por muitos fornecedores e têm amplo suporte da indústria.

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

A definição acima também menciona uma preocupação organizacional: diferentes funções devem gerenciar um conjunto diferente de objetos.

Modelo da API Gateway

Imagem de gateway-api.sigs.k8s.io

De fato, as preocupações de um operador de cluster e de um desenvolvedor são bastante diferentes. É bastante semelhante aos antigos servidores de aplicativos Java EE, que ofereciam uma especificação organizada em torno de funções: desenvolvedores, implantadores e operadores. Na minha opinião, a maior diferença é que a especificação estava focada principalmente na experiência do desenvolvedor; o resto era responsabilidade dos implementadores. A API Gateway parece se preocupar com todas as personas.

Configurando o acesso ao pod via API Gateway

Vamos substituir o Ingress que configuramos anteriormente pela API Gateway. Várias etapas são necessárias.

Instalar as novas CRDs do Gateway

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

Instalar uma implementação

Vou usar o Apache APISIX. Alternativamente, o site do SIG mantém uma lista de implementações.

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. Sem a opção --devel, o Helm instala a versão mais recente, que não funciona com a API Gateway
  2. O Gateway precisa ser acessível fora do cluster de qualquer maneira
  3. A mágica acontece aqui!
  4. Voltarei a isso mais tarde

Vamos verificar se tudo está funcionando:

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. O próprio Apache APISIX
  2. O Apache APISIX armazena sua configuração no etcd. O chart agenda três pods por padrão, uma boa prática para lidar com falhas em sistemas distribuídos
  3. Controlador do Apache APISIX: um controlador do Kubernetes é um loop de controle que move o estado existente em direção ao estado desejado
  4. Serviço do Gateway do Apache APISIX: é o Service NodePort que instalamos via o Helm Chart. É também o nome que referenciamos durante a instalação do Helm Chart - ingressPublishService

Neste ponto, a infraestrutura está pronta.

Declarar a implementação do Gateway

Como mencionei acima, a API faz uma separação clara entre a especificação e a implementação. No entanto, precisamos vinculá-la de alguma forma. Essa é a responsabilidade do objeto 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. Não usamos a versão mais recente de propósito, pois o Apache APISIX usa esta versão. Esteja ciente de que ela evoluirá no (próximo) futuro
  2. Objeto GatewayClass
  3. Nomeie como quiser; no entanto, usaremos isso mais tarde para referenciar a classe do gateway
  4. O nome do controlador depende da implementação. Aqui, estamos usando o do Apache APISIX.

Observe que o GatewayClass tem um escopo em todo o cluster. Esse modelo nos permite declarar diferentes implementações da API Gateway e usá-las em paralelo dentro do mesmo cluster.

Criar o Gateway

Com o Apache APISIX, é bastante direto:

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. Mesmo namespace que acima
  2. Objeto Gateway
  3. Referencie a classe do gateway declarada anteriormente
  4. Permite algumas restrições neste nível para que o operador do cluster possa evitar usos indesejados

Aviso: A API Gateway especifica a opção de alterar dinamicamente a porta no lado do operador. No momento da escrita, a alocação de portas do Apache APISIX é estática. O plano é torná-la dinâmica no futuro. Por favor, inscreva-se neste problema do GitHub para acompanhar o progresso.

Rotas, rotas, rotas por toda parte

Até agora, tudo era infraestrutura; finalmente podemos configurar o roteamento.

Quero o mesmo roteamento do post anterior; um ramo /left e um right. Vou pular o último por questão de brevidade.

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. Mesmo namespace que acima
  2. Objeto HTTPRoute
  3. Referencie o Gateway criado acima
  4. Regras de correspondência. No nosso caso, correspondemos a um prefixo de caminho, mas muitas regras estão disponíveis. Você pode corresponder com base em um parâmetro de consulta, em um cabeçalho, etc.
  5. O "upstream" para encaminhar. Definimos o Service left no post anterior do blog.

Verificando se funciona

Agora que configuramos nossas rotas, podemos verificar se está funcionando.

curl localhost:30800/left

Quando instalamos o chart do Helm, dissemos ao Apache APISIX para criar um serviço NodePort na porta 30800. Portanto, podemos usar a porta para acessar o serviço fora do cluster.

left

Conclusão

Muitas alternativas estão disponíveis para acessar um pod de fora do cluster. A CNCF adicionou a maioria delas para melhorar a anterior.

A API Gateway é a proposta mais recente nesse sentido. A especificação está em andamento e os produtos estão em diferentes estágios de implementação. Por esse motivo, é muito cedo para basear sua produção na API. No entanto, você provavelmente deve acompanhar o progresso, pois ela está destinada a ser uma melhoria considerável em relação às abordagens anteriores.

O código-fonte completo para este post pode ser encontrado no GitHub.

Para ir mais longe:

Tags: