Envoy Gateway


O Envoy Gateway é um controlador Kubernetes Gateway API que usa o Envoy Proxy para lidar com o tráfego de entrada. Com ele, você pode publicar serviços HTTP, HTTPS, gRPC, TCP e UDP, configurar roteamento por domínio e caminho, gerenciar TLS e aplicar políticas de tráfego usando recursos padrão do Kubernetes.

O Gateway API é a evolução do Ingress. Em vez de um único recurso Ingress, as responsabilidades são divididas entre vários objetos dedicados:

  • GatewayClass define qual controlador vai gerenciar os gateways.
  • Gateway descreve o ponto de entrada: portas, protocolos e configurações de TLS.
  • HTTPRoute define as regras de roteamento do tráfego HTTP para os serviços de backend.
  • GRPCRoute, TCPRoute, UDPRoute, TLSRoute tratam outros tipos de tráfego.

O Envoy Gateway monitora esses recursos e os utiliza para criar um Envoy Proxy que recebe o tráfego externo e o direciona para os serviços dentro do cluster.

Instalação
Copiar link

Para instalar o Envoy Gateway:

  1. Acesse a seção Kubernetes e clique no cluster.
  2. Navegue até a aba Complementos e selecione Envoy Gateway.
  3. (Opcional) Ative a Instalação avançada para editar o values.yaml. Na maioria dos casos, os valores padrão já são suficientes para começar.
  4. Clique em Instalar.
  5. Aguarde a conclusão e verifique se os pods do Envoy Gateway estão em execução:
kubectl get pods -n envoy-gateway-system

Todos os pods devem exibir o status Running.

Você também pode confirmar que os recursos do Gateway API estão disponíveis no cluster:

kubectl api-resources | grep gateway.networking.k8s.io

Exemplo prático
Copiar link

Neste exemplo, vamos configurar o Envoy Gateway para receber tráfego HTTP em um único IP externo e roteá-lo para dois serviços diferentes:

  • http://app.example.com/service1 direciona para service1
  • http://app.example.com/service2 direciona para service2

Comece criando um namespace dedicado:

kubectl create namespace envoy-example

Criar um ConfigMap
Copiar link

Crie um arquivo chamado configmap.yaml com as páginas HTML dos dois serviços:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-pages
  namespace: envoy-example
data:
  service1.html: |
    <html>
      <head><title>Service 1</title></head>
      <body><h1>Service 1</h1></body>
    </html>
  service2.html: |
    <html>
      <head><title>Service 2</title></head>
      <body><h1>Service 2</h1></body>
    </html>

Aplique o manifesto:

kubectl apply -f configmap.yaml

Criar Deployments e Services
Copiar link

Crie o arquivo service1.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service1
  namespace: envoy-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service1
  template:
    metadata:
      labels:
        app: service1
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          configMap:
            name: nginx-pages
            items:
              - key: service1.html
                path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service1
  namespace: envoy-example
spec:
  selector:
    app: service1
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP

Crie o arquivo service2.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service2
  namespace: envoy-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service2
  template:
    metadata:
      labels:
        app: service2
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          configMap:
            name: nginx-pages
            items:
              - key: service2.html
                path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service2
  namespace: envoy-example
spec:
  selector:
    app: service2
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP

Aplique os dois manifestos:

kubectl apply -f service1.yaml
kubectl apply -f service2.yaml

Verifique se os pods estão em execução:

kubectl get pods -n envoy-example

Criar um GatewayClass
Copiar link

O GatewayClass conecta o Gateway API ao controlador Envoy Gateway.

Crie o arquivo gatewayclass.yaml:

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy-gateway
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

Aplique:

kubectl apply -f gatewayclass.yaml

Verifique o status:

kubectl get gatewayclass envoy-gateway

A coluna ACCEPTED deve exibir True, indicando que o Envoy Gateway registrou o GatewayClass e vai gerenciar os recursos associados a ele.

Criar um Gateway
Copiar link

O recurso Gateway define o ponto de entrada externo para a sua aplicação.

Crie o arquivo gateway.yaml:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: app-gateway
  namespace: envoy-example
spec:
  gatewayClassName: envoy-gateway
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same

Aplique:

kubectl apply -f gateway.yaml

Após a criação do Gateway, o Envoy Gateway vai provisionar um Envoy Proxy e um load balancer. Você pode acompanhar a criação do load balancer no painel de controle ou verificar com o comando:

kubectl get gateway app-gateway -n envoy-example

Aguarde até que a coluna PROGRAMMED exiba True e a coluna ADDRESS mostre um IP externo.

Você também pode inspecionar o serviço criado:

kubectl get svc -n envoy-gateway-system \
  -l gateway.envoyproxy.io/owning-gateway-namespace=envoy-example,gateway.envoyproxy.io/owning-gateway-name=app-gateway

Criar um HTTPRoute
Copiar link

O HTTPRoute define as regras de roteamento. Crie o arquivo httproute.yaml:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: envoy-example
spec:
  parentRefs:
    - name: app-gateway
  hostnames:
    - app.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /service1
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: service1
          port: 80
    - matches:
        - path:
            type: PathPrefix
            value: /service2
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: service2
          port: 80

Aplique:

kubectl apply -f httproute.yaml

Confirme que a rota foi aceita:

kubectl get httproute app-route -n envoy-example -o yaml

O status do recurso deve conter:

status: "True" type: Accepted

Neste manifesto, o HTTPRoute aceita requisições para app.example.com e as direciona para diferentes serviços com base no prefixo do caminho. O filtro URLRewrite substitui os prefixos /service1 e /service2 por /, para que o Nginx dentro de cada serviço sirva corretamente sua página principal.

Verificar o funcionamento
Copiar link

Obtenha o IP externo do Gateway:

kubectl get gateway app-gateway -n envoy-example

Adicione esse IP como um registro A para app.example.com nas configurações de DNS. Após a propagação, teste os dois endpoints:

curl http://app.example.com/service1
curl http://app.example.com/service2

Se o DNS ainda não tiver propagado, você pode testar pelo IP usando o cabeçalho Host:

curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service1
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service2

Ambas as requisições devem retornar as páginas do Service 1 e do Service 2.

Limpar os recursos
Copiar link

Para remover todos os recursos criados neste exemplo, execute:

kubectl delete namespace envoy-example
kubectl delete gatewayclass envoy-gateway

Isso não desinstala o add-on Envoy Gateway. Para removê-lo, acesse a aba Complementos no painel de controle do cluster.

Migrar do Nginx Ingress para o Envoy Gateway
Copiar link

Você pode rodar o Envoy Gateway junto com o Nginx Ingress e migrar as rotas aos poucos. Essa abordagem permite testar os recursos do Gateway API em um IP externo separado antes de atualizar os registros DNS ou redirecionar o tráfego para o novo Gateway.

Para automatizar a conversão dos recursos Ingress existentes, use o utilitário ingress2gateway. Ele lê os recursos Ingress do seu cluster e gera os recursos equivalentes do Gateway API: Gateway, HTTPRoute e outros objetos relacionados.

Pré-requisitos
Copiar link

Antes de migrar, certifique-se de que o cluster está preparado:

  • O Envoy Gateway está instalado.
  • Um GatewayClass para o Envoy Gateway foi criado.
  • Os recursos Ingress existentes estão funcionando corretamente pelo Nginx Ingress.

Verifique se as duas classes estão presentes:

kubectl get ingressclass
kubectl get gatewayclass

O resultado deve incluir um IngressClass chamado nginx e um GatewayClass chamado envoy-gateway.

Instalar o ingress2gateway
Copiar link

Se você tiver o Go instalado localmente, execute:

go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0

O binário será colocado em $(go env GOPATH)/bin. Certifique-se de que esse diretório está no seu PATH.

Outra opção é instalar via Homebrew:

brew install ingress2gateway

Ou baixar um binário pré-compilado na página de releases do projeto.

Configuração de origem
Copiar link

Neste exemplo, a migração é feita para uma aplicação já publicada pelo Nginx Ingress.

O cluster tem um namespace chamado ingress-migration-demo com:

  • Um recurso Ingress chamado migration-source
  • Os serviços service1 e service2
  • Duas regras de roteamento para o domínio ingress-migration.example.com:
    • /service1 direciona para service1
    • /service2 direciona para service2

Verifique o Ingress de origem:

kubectl get ingress -n ingress-migration-demo

A coluna CLASS deve exibir nginx.

Converter os recursos Ingress
Copiar link

Para converter o Ingress em recursos do Gateway API, execute:

ingress2gateway print \
 --providers=ingress-nginx \
 --emitter=envoy-gateway \
 --ingress-nginx-ingress-class=nginx \
 --namespace=ingress-migration-demo > gateway-migration.yaml

O que cada flag faz:

  • print exibe os recursos gerados no stdout; o redirecionamento > salva o resultado em gateway-migration.yaml.
  • --providers=ingress-nginx especifica o tipo de Ingress controller de origem.
  • --emitter=envoy-gateway define o Envoy Gateway como controlador de destino.
  • --ingress-nginx-ingress-class=nginx filtra apenas os recursos Ingress que usam a classe nginx.
  • --namespace=ingress-migration-demo limita a conversão ao namespace de origem.

Revisar e corrigir o arquivo gerado
Copiar link

Abra o arquivo gateway-migration.yaml e revise os recursos antes de aplicá-los.

Preste atenção ao campo gatewayClassName no recurso Gateway. O utilitário pode gerar esse valor com base no nome do IngressClass de origem, resultando em algo como:

spec:
  gatewayClassName: nginx

O Envoy Gateway não vai processar um Gateway com esse nome de classe, a menos que exista um GatewayClass chamado nginx no cluster. Atualize o valor para corresponder ao GatewayClass que você criou:

spec:
  gatewayClassName: envoy-gateway

Aplicar os recursos do Gateway API
Copiar link

Quando estiver satisfeito com o arquivo, aplique:

kubectl apply -f gateway-migration.yaml

Verifique se o Gateway foi criado e recebeu um IP externo:

kubectl get gateway -A

Confirme que o HTTPRoute foi aceito pelo controlador:

kubectl get httproute -A
kubectl describe httproute <nome-da-rota> -n <namespace>

O status do HTTPRoute deve conter Accepted=True e ResolvedRefs=True.

Testar antes de mudar o tráfego
Copiar link

Enquanto os registros DNS ainda apontam para o Nginx Ingress antigo, você pode verificar o novo Gateway enviando requisições diretamente para o IP externo com o cabeçalho Host:

curl -H "Host: app.example.com" http://<EXTERNAL_IP>/<path>

Onde:

  • app.example.com é o domínio do seu HTTPRoute.
  • <EXTERNAL_IP> é o IP do novo Gateway.
  • <path> é o caminho tratado pela rota.

Compare as respostas do Ingress antigo e do novo Gateway. Se tudo estiver correto, atualize os registros DNS para apontar para o IP do novo load balancer.