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: