Introduction
ingress-nginx est en fin de vie : le projet est en mode maintenance et son remplacement officiel est la Gateway API. NGINX propose sa propre implémentation, NGINX Gateway Fabric (NGF), qui remplace ingress-nginx sur le même principe (reverse proxy L7 devant vos services) mais avec un modèle de ressources différent (Gateway, HTTPRoute, GRPCRoute…).
Ce guide couvre la migration d’un cluster qui tourne déjà en production avec ingress-nginx, pas une installation neuve. L’objectif : passer d’Ingress à HTTPRoute sans coupure de service, avec une porte de sortie à chaque étape.
À la fin, vous saurez :
- mapper vos ressources
Ingress(et leurs annotations) versGateway/HTTPRoute, - faire coexister les deux contrôleurs le temps de la bascule,
- migrer route par route avec un rollback immédiat en cas de souci,
- éviter les pièges les plus courants (namespaces, TLS, load balancer, cert-manager).
Prérequis
- Un cluster Kubernetes avec
ingress-nginxdéjà en place. - Accès
cluster-admin(installation de CRDs). kubectlet idéalementhelm.cert-managersi vous gérez du TLS automatique- Connaissance basique des ressources
Ingressde votre cluster (kubectl get ingress -A).
Étapes
1. Faire l’inventaire avant de toucher à quoi que ce soit
Listez tout ce qui dépend d’ingress-nginx avant de migrer, sinon vous découvrirez les cas particuliers en prod.
kubectl get ingress -A -o wide
kubectl get ingress -A -o json | jq -r '.items[] | .metadata.namespace + "/" + .metadata.name + ": " + (.metadata.annotations | keys | join(","))'
Notez en particulier :
- les annotations
nginx.ingress.kubernetes.io/*utilisées (rewrite, redirect, whitelist, rate-limit…), - les
IngressClassen jeu si vous en avez plusieurs, - les certificats TLS gérés par
cert-manager(kubectl get certificate -A), - l’IP du LoadBalancer actuel de
ingress-nginx(kubectl get svc -n ingress-nginx) : elle sera différente pour NGF, donc DNS à revoir.
2. Installer la Gateway API et NGINX Gateway Fabric en parallèle
Pas de big bang : NGF s’installe à côté d’ingress-nginx, sans y toucher. Les deux peuvent tourner en même temps sur le même cluster.
# CRDs de la Gateway API (standard channel)
kubectl apply -f kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml
Puis NGF via Helm :
helm install nginx-gateway-fabric oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--create-namespace -n nginx-gateway
Vérifiez qu’il tourne et que son Service reçoit bien une IP externe distincte de celle d’ingress-nginx :
kubectl get pods -n nginx-gateway
kubectl get svc -n nginx-gateway
3. Créer la ressource Gateway
ingress-nginx n’a pas d’équivalent explicite pour l’entrypoint: tout était implicite dans l’IngressClass. Avec la Gateway API, il devient une ressource à part entière : la Gateway. C’est elle qui porte les listeners (ports, TLS) ; les HTTPRoute viennent s’y attacher.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: nginx-gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
hostname: "*.mondomaine.com"
tls:
mode: Terminate
certificateRefs:
- name: wildcard-cert
allowedRoutes:
namespaces:
from: All
allowedRoutes.namespaces.from: All évite de recréer un ReferenceGrant pour chaque namespace applicatif pendant la migration. Vous pourrez restreindre après coup si besoin.
4. Convertir vos Ingress en HTTPRoute, un par un
C’est le cœur de la migration. Voici les correspondances les plus fréquentes.
Un Ingress simple :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: app.mondomaine.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
devient :
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
namespace: default
spec:
parentRefs:
- name: main-gateway
namespace: nginx-gateway
hostnames:
- "app.mondomaine.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: my-service
port: 80
Les cas génériques (path, host, rewrite, redirect HTTP→HTTPS) sont couverts nativement par la Gateway API. Les cas avancés (rate limiting, whitelist IP, body size) passent par les policies spécifiques à NGF (ClientSettingsPolicy), pas par un standard commun : c’est le principal piège de la migration, prévoyez du temps pour ces routes.
5. Basculer le DNS route par route, pas tout d’un coup
Comme les deux contrôleurs tournent en parallèle avec deux IP différentes, vous pouvez migrer service par service :
- Créez la
HTTPRouteéquivalente pour un service (sans supprimer l’Ingress). - Testez en direct sur l’IP de NGF, sans passer par le DNS :
curl -H "Host: app.mondomaine.com" https://<IP_NGF>/ -k - Une fois validé, changez l’enregistrement DNS pour pointer vers l’IP de NGF.
- Laissez tourner l’
Ingresséquivalent quelques jours avant de le supprimer : c’est votre rollback immédiat si un problème apparaît (retour DNS en arrière, zéro redéploiement).
6. Nettoyer une fois la migration validée
Quand toutes les routes sont basculées et stables :
kubectl delete ingress --all -A --selector=<vos anciens labels>
helm uninstall ingress-nginx -n ingress-nginx
kubectl delete ingressclass nginx
Ne faites cette étape qu’après avoir confirmé qu’aucune Ingress résiduelle n’est encore active (kubectl get ingress -A doit être vide).
Vérification
kubectl get gateway -A
kubectl get httproute -A
kubectl get pods -n nginx-gateway
Chaque HTTPRoute doit afficher une condition Accepted: True et ResolvedRefs: True :
kubectl describe httproute my-app -n default
Testez chaque hostname migré en HTTP et en HTTPS, avec certificat valide, avant de désactiver l’ancien Ingress correspondant.
Prochaines étapes
- Restreindre
allowedRoutessur laGatewayune fois la migration terminée (au lieu deFrom: All). - Explorer les
GRPCRoutesi vous exposez du gRPC. - Mettre en place des
ReferenceGrantciblés plutôt qu’un accès large entre namespaces. - Si vous gérez plusieurs équipes, envisager plusieurs
Gateway(une par domaine/équipe) plutôt qu’une seule partagée.
