Migrar de Ingress para Gateway API
A Gateway API é a sucessora do Ingress: separa responsabilidades (quem opera a
infraestrutura configura o Gateway; quem opera o serviço configura a HTTPRoute),
padroniza o que hoje vive em anotações proprietárias e resolve divisão de tráfego e
roteamento por header sem depender de extensões.
A migração pode e deve ser feita em paralelo, um serviço por vez, sem janela.
1. Mapeie o que o Ingress atual faz
Seção intitulada “1. Mapeie o que o Ingress atual faz”O trabalho real da migração está nas anotações — é ali que mora o comportamento que não está no spec.
kubectl get ingress -A -o json | jq -r '.items[] | "\(.metadata.namespace)/\(.metadata.name)\t\(.metadata.annotations // {} | keys | join(","))"'Classifique cada anotação em três grupos:
- Vira campo nativo: reescrita de caminho, redirecionamento, timeouts, divisão de tráfego, roteamento por header.
- Vira recurso de política do controlador (
BackendTLSPolicy, filtros específicos). - Não tem equivalente ainda: anote e decida — adiar a migração daquele serviço costuma ser melhor que forçar.
2. Instale as CRDs e um controlador compatível
Seção intitulada “2. Instale as CRDs e um controlador compatível”kubectl apply -f \ https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yamlkubectl get crd | grep gateway.networking.k8s.ioDepois instale (ou habilite) um controlador que a implemente — Istio, Cilium, Envoy
Gateway, NGINX Gateway Fabric, ou o controlador da sua nuvem. Verifique a versão da API
suportada e se ele cobre o canal standard ou também o experimental, porque parte dos
recursos ainda está no segundo.
3. Crie o Gateway
Seção intitulada “3. Crie o Gateway”Este recurso é de quem cuida da infraestrutura, e é compartilhado por vários times.
apiVersion: gateway.networking.k8s.io/v1kind: GatewayClassmetadata: { name: producao }spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller---apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata: { name: borda, namespace: infra }spec: gatewayClassName: producao listeners: - name: https protocol: HTTPS port: 443 hostname: "*.exemplo.com.br" tls: mode: Terminate certificateRefs: [{ name: curinga-tls }] allowedRoutes: namespaces: { from: Selector, selector: { matchLabels: { rotas: permitidas } } }allowedRoutes é o controle que o Ingress não tinha: só namespaces marcados podem anexar
rotas a esta borda.
4. Traduza regra por regra
Seção intitulada “4. Traduza regra por regra”apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata: { name: loja, namespace: loja }spec: parentRefs: [{ name: borda, namespace: infra }] hostnames: ["loja.exemplo.com.br"] rules: - matches: [{ path: { type: PathPrefix, value: /api } }] filters: - type: URLRewrite urlRewrite: { path: { type: ReplacePrefixMatch, replacePrefixMatch: / } } backendRefs: [{ name: api, port: 80 }] - matches: [{ path: { type: PathPrefix, value: / } }] backendRefs: - { name: loja-estavel, port: 80, weight: 90 } - { name: loja-canario, port: 80, weight: 10 } # nativo, sem anotaçãoEquivalências que respondem a maior parte das dúvidas:
| Ingress (nginx) | Gateway API |
|---|---|
rewrite-target |
filtro URLRewrite |
canary-weight |
weight no backendRefs |
ssl-redirect |
listener HTTP com filtro RequestRedirect |
configuration-snippet |
geralmente sem equivalente — reavalie a necessidade |
ingressClassName |
parentRefs apontando para o Gateway |
5. Rode os dois em paralelo
Seção intitulada “5. Rode os dois em paralelo”A transição segura usa hostnames diferentes antes de trocar o tráfego real:
- Publique a
HTTPRoutecom um host de teste (loja-gw.exemplo.com.br) apontando para o mesmo backend. - Compare respostas, cabeçalhos e códigos entre as duas bordas.
Janela do terminal for p in / /api/health /produtos/1; doecho "$p"curl -s -o /dev/null -w ' ingress %{http_code} %{time_total}s\n' https://loja.exemplo.com.br$pcurl -s -o /dev/null -w ' gateway %{http_code} %{time_total}s\n' https://loja-gw.exemplo.com.br$pdone - Confira o que costuma divergir: barra final, sensibilidade a maiúsculas no caminho,
cabeçalhos de encaminhamento (
X-Forwarded-*), timeouts e tamanho máximo de corpo. - Mude o DNS do host real para a borda nova, com TTL já reduzido.
- Observe erro e latência por pelo menos um ciclo de pico.
6. Corte e remova
Seção intitulada “6. Corte e remova”Só depois da estabilidade confirmada, remova o Ingress antigo — e mantenha o controlador anterior instalado até o último serviço migrar.
kubectl get ingress -A # o alvo é esta lista ficar vaziakubectl delete ingress loja -n lojaSe der errado
Seção intitulada “Se der errado”| Sintoma | Causa provável |
|---|---|
HTTPRoute com Accepted=False |
Namespace não permitido pelo allowedRoutes, ou hostname fora do listener |
| 404 na rota nova | Ordem de match: caminhos mais específicos precisam vir antes |
| TLS não funciona | certificateRefs em outro namespace exige ReferenceGrant |
| Comportamento diferente do Ingress | Uma anotação sem equivalente ficou para trás |
| Rota some após upgrade | Recurso do canal experimental não suportado na versão instalada |
kubectl describe httproute loja -n loja | sed -n '/Status/,$p'kubectl get gateway borda -n infra -o jsonpath='{.status.conditions}' | jqChecklist de pronto
Seção intitulada “Checklist de pronto”- Inventário de anotações feito e classificado.
- Controlador compatível instalado, com versão da API conferida.
-
GatewaycomallowedRoutesrestrito. - Rotas comparadas lado a lado com host de teste.
- Corte feito por DNS com TTL baixo, e monitorado.
- Ingress antigo removido apenas após estabilidade.