Migrar a Entrada para a API Gateway

Nesta página, mostramos como migrar o gerenciamento de tráfego no Google Kubernetes Engine (GKE) da API Ingress para a API Gateway. A API Gateway oferece uma solução totalmente gerenciada Google Cloud para processar o tráfego do aplicativo.

Para minimizar o tempo de inatividade e mitigar riscos, a abordagem mais eficaz para migrar para a API Gateway é executar as configurações da API Ingress atual e da nova API Gateway simultaneamente. Esse método permite testar minuciosamente a nova configuração do gateway em um ambiente ativo sem afetar os serviços atuais. Depois de validar a nova configuração do gateway, é possível realizar uma transição rápida de DNS para redirecionar o tráfego para a API Gateway e ajudar a garantir uma transição tranquila e de baixo risco.

Em geral, a estratégia de migração envolve as seguintes fases:

  1. Configure o novo balanceador de carga.
  2. Defina regras para lidar com o tráfego de entrada.
  3. Implante a nova configuração e teste o fluxo de tráfego para o novo endereço IP do gateway.
  4. Mudar o tráfego de produção para a API Gateway.
  5. Limpar os recursos de Entrada restantes.

Configurar o novo balanceador de carga

Nesta fase, você implanta um recurso de gateway do Kubernetes para balancear a carga do tráfego no cluster do GKE. Quando você implanta um recurso de gateway, o GKE configura um balanceador de carga de aplicativo da camada 7 para expor o tráfego HTTP(S) aos aplicativos executados no cluster. Você implanta um recurso de gateway para cada cluster ou balanceador de carga necessário.

No exemplo a seguir, você configura um balanceador de carga de aplicativo externo global. Para criar um gateway, salve o seguinte manifesto como gateway.yaml:

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: external-http-gateway
spec:
  gatewayClassName: gke-l7-global-external-managed # GKE's managed external Application Load Balancer
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same # Only allow HTTPRoutes from the same namespace

O manifesto anterior descreve um gateway que inclui os seguintes campos:

  • gatewayClassName: gke-l7-global-external-managed: especifica o GatewayClass para esse gateway. Essa classe de gateway usa um balanceador de carga de aplicativo externo global.
  • protocol: HTTP e port: 80: especifica que o gateway expõe a porta 80 para o tráfego HTTP.

Definir regras para o tráfego de entrada

Os recursos de rota definem regras específicas do protocolo que mapeiam o tráfego de um gateway para os serviços de back-end.

Nesta fase, você traduz o manifesto de entrada em um recurso HTTPRoute. Para converter o manifesto de entrada, siga as etapas na ferramenta ingress2gateway.

Neste exemplo, pressupomos que você tenha o seguinte recurso de Entrada:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        pathType: Prefix
        backend:
          service:
            name: tea-svc
            port:
              number: 80
      - path: /coffee
        pathType: Prefix
        backend:
          service:
            name: coffee-svc
            port:
              number: 80

Depois de converter o manifesto usando a ferramenta ingress2gateway, a saída será o manifesto HTTPRoute traduzido.

Salve o seguinte manifesto de amostra como httproute.yaml:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: cafe-route
spec:
  # This route attaches to our new Gateway
  parentRefs:
  - name: external-http-gateway
  # The hostname is the same as before
  hostnames:
  - "cafe.example.com"
  # The routing rules are now more explicit
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: tea-svc
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee-svc
      port: 80

Observe que o campo rules no manifesto HTTPRoute corresponde diretamente às regras de rota definidas no manifesto Entrada original.

Implantar e testar a nova configuração

Nesta fase, você aplica os manifestos de Gateway e HTTPRoute criados nas duas fases anteriores e testa se o tráfego flui para o novo endereço IP do Gateway.

  1. Aplique os manifestos de Gateway e HTTPRoute:

    kubectl apply -f gateway.yaml
    kubectl apply -f httproute.yaml
    
  2. Consiga o endereço IP do gateway. Pode levar alguns minutos para alocar o endereço IP:

    kubectl get gateway external-http-gateway -o=jsonpath="{.status.addresses[0].value}" --watch
    

    A saída é o endereço IP externo do gateway, por exemplo, 203.0.113.90.

  3. Teste o novo endereço IP do gateway. Use o seguinte comando curl para enviar uma solicitação ao endereço IP e especificar o nome do host cafe.example.com. Exemplo:

    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/tea
    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/coffee
    

    Substitua 203.0.113.90 pelo endereço IP externo que você recebeu na etapa anterior. A saída confirma que o novo endereço IP do gateway encaminha corretamente o tráfego para cafe.example.com sem realizar uma busca DNS.

Direcionar o tráfego para o novo endereço IP do gateway

Nesta fase, você transfere o tráfego em tempo real do Entrada anterior para o novo Gateway atualizando os registros DNS para apontar para o novo endereço IP do Gateway. As etapas exatas para atualizar os registros DNS variam de acordo com o provedor de DNS.

Por exemplo, se você configurou cafe.example.com na entrada, localize o registro A para cafe.example.com com seu provedor de DNS e altere o valor do endereço IP de entrada antigo para 203.0.113.90, que é o novo endereço IP do gateway.

Depois que você atualiza o registro DNS, o tráfego começa a mudar do Entrada para o Gateway, mas a transição não ocorre imediatamente para todos os clientes. Os resolvedores de DNS que têm o registro anterior em cache aguardam o valor de tempo de vida (TTL) do registro expirar antes de consultar o registro novamente e receber o endereço IP atualizado. Por isso, continue executando o Entrada atual e o novo Gateway em conjunto até verificar que o tráfego para o Entrada foi interrompido, o que indica que a propagação de DNS foi concluída e os clientes não estão mais sendo direcionados para o endereço IP antigo. Para verificar isso, monitore o tráfego no balanceador de carga ou no controlador de entrada. Para mais informações, consulte Como verificar a propagação de DNS.

Se você usa o Cloud DNS, pode usar pesos de destino para transferir gradualmente o tráfego do endereço IP antigo para o novo. Para mais informações, consulte Configurar políticas de roteamento de DNS e verificações de integridade.

Limpar os recursos de Entrada restantes

Depois de confirmar que o novo gateway está funcionando, limpe os recursos antigos do Entrada.

  1. Exclua o recurso Entrada:

    kubectl delete ingress cafe-ingress
    
  2. Desinstale o controlador ingress-nginx. Por exemplo, se você usou o Helm para instalar o controlador, execute o seguinte comando:

    helm uninstall ingress-nginx -n ingress-nginx
    

Comparação de recursos entre o Ingress NGINX e o gateway do GKE

A API Gateway oferece uma maneira mais padronizada de configurar a entrada e tem paridade de recursos para os recursos mais comuns, como roteamento, cabeçalhos e divisão de tráfego.

A tabela a seguir compara a configuração usada para recursos comuns no controlador de Entrada e na API Gateway.

Recurso Anotação no Entrada Configuração no gateway do GKE Paridade
Roteamento com base em host O campo spec.rules.host no objeto Entrada. O campo hostnames no objeto HTTPRoute. Paridade total.
Roteamento baseado em caminho O campo spec.rules.http.paths no objeto Entrada e a anotação nginx.ingress.kubernetes.io/use-regex para correspondência de caminho de expressão regular. O campo rules.matches.path no objeto HTTPRoute. Paridade total. O gateway do GKE é compatível com correspondência exata, de prefixo e de expressão regular (RegularExpression) para caminhos. Além disso, é possível fazer a correspondência de cabeçalhos HTTP (rules.matches.headers) e parâmetros de consulta (rules.matches.queryParams) usando valores exatos ou expressões regulares.
Divisão de tráfego nginx.ingress.kubernetes.io/canary anotação. HTTPRoute com o campo backendRefs ponderado. Paridade total. Além disso, é possível dividir o tráfego com controle detalhado.
afinidade da sessão Anotações nginx.ingress.kubernetes.io/affinity e nginx.ingress.kubernetes.io/affinity-mode. GCPTrafficDistributionPolicy com o campo sessionAffinity. Paridade total. O gateway do GKE é compatível com vários tipos de afinidade da sessão, incluindo tipos de afinidade baseados em cookies (HTTP_COOKIE, GENERATED_COOKIE e STRONG_COOKIE_AFFINITY com estado), afinidade baseada em cabeçalho (HEADER_FIELD) e afinidade baseada em IP do cliente (CLIENT_IP).
CORS (Compartilhamento de recursos entre origens) nginx.ingress.kubernetes.io/enable-cors HTTPRoute com um filtro CORS. Paridade total. Observação: o gateway do GKE impõe limites ao número de padrões de caracteres curinga que podem ser definidos por listener ou nome do host.
Regravações de URL nginx.ingress.kubernetes.io/rewrite-target HTTPRoute com um filtro urlRewrite ou GCPHTTPFilter com o campo spec.urlRewrite.regexModifier. Paridade total. O gateway do GKE é compatível com substituições de caminho completo, substituições de prefixo e substituições de caminho de expressão regular.
Manipulação de cabeçalho nginx.ingress.kubernetes.io/proxy-set-headers ou add-headers HTTPRoute com um modificador requestHeaderModifier ou filtro responseHeaderModifier. Paridade total.
Autenticação nginx.ingress.kubernetes.io/auth-url para autenticação externa.
  • Identity-Aware Proxy (IAP): recurso personalizado GCPBackendPolicy.
  • Outros: requer uma abordagem mais personalizada, possivelmente com malha de serviço ou filtros personalizados.
Paridade parcial. O Identity-Aware Proxy é a maneira recomendada de proteger o gateway e é configurado no back-end.

A seguir