Remplacer ingress-nginx : Gateway API en pratique

ingress-nginx s'arrête en mars 2026. Comment migrer vers la Gateway API avec Kong, Traefik ou NGINX Gateway Fabric : config, commandes, coûts.

Photo en noir et blanc d'une femme tapant du code sur un ordinateur portable posé sur ses genoux

Réponse courte : le projet ingress-nginx est en fin de vie — l'équipe Kubernetes a annoncé l'arrêt de la maintenance et des correctifs de sécurité en mars 2026. Le successeur officiel n'est pas un autre contrôleur Ingress mais une API : la Gateway API, passée en GA (v1) en octobre 2023. La migration consiste à installer les CRD Gateway API, déployer un contrôleur conforme (Kong, Traefik ou NGINX Gateway Fabric), traduire chaque Ingress en Gateway + HTTPRoute, puis basculer le DNS. On peut faire tourner les deux en parallèle pendant la transition.

Beaucoup d'équipes qui gèrent un cluster pour une PME découvrent la nouvelle en lisant un bulletin de sécurité : « ingress-nginx retirement ». Le contrôleur installé il y a trois ans par un helm install et jamais retouché devient, du jour au lendemain, un composant non maintenu exposé sur Internet. Ce n'est pas une urgence à traiter en une nuit, mais c'est un chantier à planifier maintenant, parce qu'il touche le point d'entrée de tout le trafic HTTP de production.

Photo en noir et blanc d'une femme tapant du code sur un ordinateur portable posé sur ses genoux

Pourquoi ingress-nginx s'arrête et ce que cela change

ingress-nginx est le contrôleur Ingress historique du projet Kubernetes, maintenu par le SIG Network. L'annonce de retrait, publiée sur le blog Kubernetes en novembre 2025, pointe deux raisons : une équipe de mainteneurs réduite à une poignée de bénévoles pour un composant critique utilisé par une majorité de clusters, et une dette technique difficile à tenir — notamment la fameuse configuration par annotations et les configuration-snippet, source de plusieurs CVE à fort impact (dont CVE-2025-1974, « IngressNightmare », qui permettait une exécution de code arbitraire dans le contrôleur).

Concrètement :

  • après l'arrêt, plus aucune release, plus de correctifs de sécurité, plus d'images mises à jour ;
  • votre cluster continue de fonctionner — rien ne casse le jour J ;
  • mais toute nouvelle CVE dans NGINX, dans Lua ou dans le contrôleur lui-même restera sans patch officiel.

Un contrôleur Ingress est exposé publiquement et dispose, par conception, d'un ClusterRole capable de lire tous les Secrets du cluster (pour les certificats TLS). C'est précisément ce qui rendait IngressNightmare dévastateur. Rester sur un composant non maintenu à cet endroit du système n'est pas une option tenable au-delà de quelques mois.

À ne pas confondre : ingress-nginx (le contrôleur communautaire Kubernetes) et NGINX Ingress Controller, le produit maintenu par F5/NGINX. Ce dernier continue d'exister. La plupart des clusters installés via helm repo add ingress-nginx utilisent le premier.

L'Ingress aussi est en bout de course

Le problème dépasse un seul contrôleur. L'API networking.k8s.io/v1 Ingress est gelée : elle ne couvre que le routage HTTP par hôte et par chemin. Tout le reste — réécritures, timeouts, mTLS, répartition de trafic entre deux versions, en-têtes, gRPC, TCP — s'exprime en annotations propriétaires, différentes chez chaque éditeur. Un Ingress avec dix annotations nginx.ingress.kubernetes.io/* n'est portable nulle part.

La Gateway API répond à ça avec des ressources typées, validées par le serveur d'API, et un modèle de responsabilités partagées entre l'équipe plateforme et les équipes applicatives.

Le modèle Gateway API en trois ressources

RessourceQui la gèreRôle
GatewayClassFournisseur / plateformeDésigne l'implémentation (Kong, Traefik, NGINX…)
GatewayÉquipe plateformeLes listeners : ports, protocoles, hostnames, certificats TLS
HTTPRouteÉquipe applicativeLe routage : chemins, en-têtes, backends, poids, filtres

Le gain opérationnel est immédiat : l'équipe plateforme possède le point d'entrée et les certificats, les développeurs déclarent leurs routes dans leur propre namespace, sans pouvoir toucher au listener 443 ni voler un hostname. L'autorisation passe par allowedRoutes sur le Gateway et ReferenceGrant pour les références inter-namespaces.

Les versions utiles en novembre 2026 : GATEWAY_API_VERSION=v1.3.0 apporte HTTPRoute, GRPCRoute et GatewayClass en v1 (stable), tandis que TCPRoute, UDPRoute et TLSRoute restent en v1alpha2. Les CRD ne sont pas livrés avec Kubernetes : il faut les installer explicitement.

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
kubectl get crd | grep gateway.networking.k8s.io

Le canal standard suffit pour du HTTP/HTTPS classique. Le canal experimental est nécessaire pour TCPRoute, BackendTLSPolicy ou le routage par pourcentage avancé selon les implémentations.

Choisir son implémentation : Kong, Traefik ou NGINX Gateway Fabric

Trois candidats sérieux pour un cluster de PME, selon ce que vous faisiez déjà avec vos annotations.

Kong Ingress Controller — si vous avez besoin d'une vraie passerelle d'API

Kong est le choix pertinent dès que le point d'entrée fait plus que router : authentification par clé ou OIDC, rate limiting par consommateur, transformation de requêtes, journalisation structurée. Le contrôleur (KIC 3.x) est conforme Gateway API et expose ses fonctions via des KongPlugin attachés à une HTTPRoute.

helm repo add kong https://charts.konghq.com
helm repo update
helm install kong kong/ingress -n kong --create-namespace \
  --set controller.ingressController.image.tag=3.5 \
  --set gateway.env.database=off

Le mode DB-less (database=off) est celui à privilégier : la configuration vit dans les CRD Kubernetes, pas dans une base PostgreSQL à sauvegarder. Un plugin de limitation de débit s'attache ensuite à une route précise :

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rate-limit-api
  namespace: production
plugin: rate-limiting
config:
  minute: 120
  policy: local
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api
  namespace: production
  annotations:
    konghq.com/plugins: rate-limit-api
spec:
  parentRefs:
    - name: public-gateway
      namespace: infra
  hostnames:
    - api.exemple.fr
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /v1
      backendRefs:
        - name: api-svc
          port: 8080

Le coût : Kong Gateway OSS est gratuit (licence Apache 2.0), mais les plugins d'entreprise (OIDC complet, RBAC, Konnect) sont payants. Comptez deux pods de 256 Mi à 512 Mi de RAM pour un trafic modéré.

Traefik — le plus simple à mettre en œuvre

Traefik v3 supporte la Gateway API en plus de ses IngressRoute historiques. Si vous utilisiez déjà Traefik ou si vos besoins se limitent au routage + TLS + quelques middlewares, c'est la migration la moins coûteuse.

helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik -n traefik --create-namespace \
  --set providers.kubernetesGateway.enabled=true \
  --set gateway.enabled=false

Attention à un détail qui fait perdre une demi-journée : par défaut, le chart Traefik crée lui-même une Gateway. Si vous gérez la vôtre en GitOps, désactivez-la (gateway.enabled=false) sous peine d'avoir deux objets qui se disputent le même listener.

NGINX Gateway Fabric — pour rester sur NGINX

NGF est l'implémentation Gateway API maintenue par NGINX/F5, avec NGINX en data plane. C'est le chemin de moindre surprise si vos équipes lisent couramment des directives NGINX et que vous voulez conserver le même comportement de proxy (buffering, keepalive, timeouts). En contrepartie, l'écosystème de politiques est plus jeune que celui de Kong.

Mains d'un homme adulte tapant sur un ordinateur portable affichant du code dans un éditeur sombre

Traduire ses Ingress en HTTPRoute

Voici l'exercice concret. Un Ingress typique sorti d'un cluster de production :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: site
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts: [www.exemple.fr]
      secretName: site-tls
  rules:
    - host: www.exemple.fr
      http:
        paths:
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service: { name: api-svc, port: { number: 8080 } }
          - path: /
            pathType: Prefix
            backend:
              service: { name: web-svc, port: { number: 3000 } }

Le Gateway équivalent, détenu par l'équipe plateforme :

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: public-gateway
  namespace: infra
spec:
  gatewayClassName: kong
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: "*.exemple.fr"
      tls:
        mode: Terminate
        certificateRefs:
          - name: site-tls
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "true"

Et la route, côté application, avec la réécriture exprimée par un filtre typé au lieu d'une annotation :

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: site
  namespace: production
spec:
  parentRefs:
    - name: public-gateway
      namespace: infra
  hostnames:
    - www.exemple.fr
  rules:
    - matches:
        - path: { type: PathPrefix, value: /api }
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: api-svc
          port: 8080
    - matches:
        - path: { type: PathPrefix, value: / }
      backendRefs:
        - name: web-svc
          port: 3000

Trois points à retenir :

  1. La regex disparaît. rewrite-target: /$2 devient un filtre URLRewrite avec ReplacePrefixMatch. Plus lisible, mais les réécritures vraiment régulières (captures multiples) n'ont pas d'équivalent standard : elles passent par une politique propre à l'implémentation.
  2. ReferenceGrant est obligatoire si le Secret TLS ou un Service backend vit dans un autre namespace que l'objet qui le référence. Sans lui, le statut de la route reste ResolvedRefs: False et le trafic tombe en 500.
  3. cert-manager sait émettre pour une Gateway : activez --enable-gateway-api sur le contrôleur et annotez la Gateway avec cert-manager.io/cluster-issuer. C'est supporté depuis cert-manager 1.15.

L'outil qui fait 80 % du travail

Le projet Gateway API fournit ingress2gateway, qui lit vos Ingress (y compris certaines annotations nginx et kong) et génère les manifestes correspondants :

go install github.com/kubernetes-sigs/ingress2gateway@latest
ingress2gateway print --providers ingress-nginx --all-namespaces > gateway-api.yaml

Le résultat est un point de départ, pas une livraison : relisez-le, factorisez les Gateway (l'outil en crée souvent une par Ingress) et vérifiez chaque annotation non traduite.

Basculer sans coupure

La bonne nouvelle : les deux mondes cohabitent. Un contrôleur Ingress et une Gateway peuvent tourner côte à côte, chacun derrière son propre Service de type LoadBalancer, donc sa propre IP.

  1. Installer les CRD et le nouveau contrôleur dans un namespace dédié. Vérifier que l'IP est attribuée : kubectl get gateway -A -o wide.
  2. Tester hors DNS, avec l'en-tête Host forcé vers la nouvelle IP :
    curl -sk --resolve www.exemple.fr:443:203.0.113.42 https://www.exemple.fr/api/health -i
    
  3. Valider le statut des routes avant toute bascule : kubectl describe httproute site -n production doit afficher Accepted: True et ResolvedRefs: True.
  4. Abaisser le TTL DNS à 60 s la veille, puis basculer l'enregistrement A/AAAA. Sur OVHcloud ou Scaleway, prévoyez quelques minutes de propagation réelle au-delà du TTL annoncé.
  5. Observer pendant 24 à 48 h les codes 4xx/5xx et les latences p95 sur l'ancienne et la nouvelle IP. Le rollback est un simple retour DNS tant que l'ancien contrôleur tourne.
  6. Désinstaller ingress-nginx seulement après une semaine sans trafic résiduel sur son Service.

Le piège classique est le WebSocket et les connexions longues : elles ne se rejouent pas, elles se coupent au moment où le client rouvre. Prévoyez la bascule hors heures d'affluence, et vérifiez les timeouts sur la nouvelle Gateway (Kong : KongIngress/KongUpstreamPolicy ; Traefik : ServersTransport).

Écran d'ordinateur affichant des lignes de code Python colorées, vue en gros plan et en biais

Côté coût, le poste à surveiller n'est pas la licence mais le load balancer. Chaque Gateway avec un listener exposé crée un service LoadBalancer, donc une IP facturée par le fournisseur — autour de 10 à 15 €/mois chez OVHcloud ou Scaleway pour un LB managé d'entrée de gamme. Pendant la phase de cohabitation, vous payez les deux. Mutualisez ensuite : une seule Gateway partagée par plusieurs namespaces, grâce à allowedRoutes, au lieu d'une Gateway par application. C'est exactement le genre d'arbitrage que nous traitons dans nos missions d'infrastructure et d'exploitation cloud.

Pensez aussi aux secrets de registre si vos images sont privées : les pods du nouveau contrôleur, et surtout vos applications redéployées dans de nouveaux namespaces, ont besoin de leur imagePullSecret — le sujet est détaillé dans notre guide sur les images GitLab privées sur Kubernetes.

Questions fréquentes

Faut-il migrer avant mars 2026 absolument ?

Non : rien ne s'arrête techniquement à cette date. Ce qui s'arrête, c'est la publication de correctifs. Le vrai critère est votre exposition : un cluster public avec des données clients devrait être migré dans le trimestre ; un cluster interne derrière un VPN peut attendre une fenêtre plus confortable. Dans tous les cas, documentez la décision et surveillez les annonces de CVE sur NGINX.

Peut-on garder ingress-nginx et ajouter une Gateway ?

Oui, et c'est la stratégie recommandée pour la transition. Les deux API coexistent dans le même cluster. Faites simplement attention à ce qu'un même hostname ne soit pas servi par les deux en même temps : vous obtiendriez un comportement dépendant du DNS, donc des incidents impossibles à reproduire.

Kong, Traefik ou NGINX Gateway Fabric : lequel pour une PME ?

Traefik si vous voulez le minimum de friction et que le routage + TLS suffit. Kong si le point d'entrée doit faire office de passerelle d'API (clés, quotas, OIDC, journalisation). NGINX Gateway Fabric si votre équipe tient à conserver NGINX comme data plane. Les trois sont conformes HTTPRoute v1, donc vos routes restent portables : seules les politiques spécifiques (plugins, middlewares) vous lient à un éditeur.

Que deviennent les annotations qui n'ont pas d'équivalent ?

Elles passent par des CRD propres à l'implémentation : KongPlugin et KongUpstreamPolicy chez Kong, Middleware chez Traefik, ClientSettingsPolicy et ObservabilityPolicy chez NGF. Profitez de la migration pour faire l'inventaire : dans la pratique, un tiers des annotations accumulées au fil des ans ne sert plus à rien.

La Gateway API gère-t-elle le TCP et le gRPC ?

GRPCRoute est stable depuis la v1.1 du canal standard. TCPRoute, UDPRoute et TLSRoute restent en v1alpha2 et demandent le canal experimental, avec un support variable selon l'implémentation. Pour exposer PostgreSQL ou Redis hors du cluster, vérifiez d'abord la matrice de conformité du projet Gateway API.

En résumé

  • ingress-nginx n'est plus maintenu après mars 2026 : plus de correctifs de sécurité sur un composant exposé qui peut lire tous les Secrets du cluster.
  • Le successeur est la Gateway API (v1.3.0), à installer via ses CRD, avec un contrôleur conforme : Kong (passerelle d'API), Traefik (simplicité), NGINX Gateway Fabric (continuité NGINX).
  • La migration traduit chaque Ingress en Gateway + HTTPRoute : les annotations deviennent des filtres typés, et ingress2gateway génère un premier jet.
  • Les deux contrôleurs cohabitent : testez avec curl --resolve, basculez par le DNS à TTL réduit, gardez l'ancien une semaine pour le rollback.
  • Surveillez le coût des load balancers pendant la cohabitation et mutualisez ensuite une seule Gateway via allowedRoutes.
  • Besoin d'un regard extérieur sur votre point d'entrée ou votre cluster ? Découvrez l'équipe et parlons de votre projet.