La fin de vie annoncée du contrôleur Ingress-nginx change la donne pour des milliers de clusters Kubernetes en France et en Europe. Ce tutoriel montre comment installer Ingress-nginx et cert-manager pour publier une application avec un certificat TLS automatique via Let’s Encrypt, tout en préparant la suite après l’arrêt du support. Vous repartirez avec un projet complet, fonctionnel, et une checklist de migration.
Pourquoi ce tutoriel arrive au bon moment
Le projet cert-manager a confirmé que le contrôleur Ingress-nginx maintenu par la communauté Kubernetes atteindra sa fin de vie en mars 2026. Des milliers d’équipes en Europe utilisent encore ce contrôleur pour exposer leurs applications en HTTPS, souvent sans plan de sortie clair. Ce guide couvre l’installation complète d’Ingress-nginx et de cert-manager, l’émission automatique de certificats Let’s Encrypt, et une feuille de route pour migrer vers un contrôleur encore maintenu quand le moment sera venu.
L’angle pratique compte plus que jamais. cert-manager a publié sa branche 1.21 le 8 juillet 2026, avec une matrice de compatibilité couvrant Kubernetes 1.33 à 1.36. La version 1.20.4 est sortie le 16 septembre 2026, et la 1.21.2 était la dernière disponible au 11 septembre 2026. Le chart Helm ingress-nginx 4.15.1 date du 19 mars 2026 et embarque le contrôleur v1.15.1. Ces chiffres donnent le tempo : le terrain bouge vite, et un tutoriel figé dans le temps devient dangereux en quelques mois.
Beaucoup d’équipes françaises et européennes découvrent la fin de vie d’Ingress-nginx un peu tard, souvent au moment d’un audit de sécurité ou d’une revue de conformité. Le contrôleur reste techniquement fonctionnel après mars 2026, mais plus aucun correctif de sécurité ne sera publié pour de nouvelles failles découvertes après cette date. Sur un composant exposé directement à Internet, c’est un risque que peu d’organisations peuvent se permettre d’ignorer durablement, surtout dans un contexte où le Cyber Resilience Act impose déjà une traçabilité renforcée des composants logiciels en production.
Ce que vous allez construire : un cluster Kubernetes local avec un contrôleur Ingress-nginx, cert-manager pour la gestion des certificats, un ClusterIssuer Let’s Encrypt configuré en HTTP-01, une application de démonstration exposée en HTTPS avec renouvellement automatique, et un ensemble de vérifications de sécurité (RBAC minimal, NetworkPolicy, audit de version). Comptez environ 90 minutes pour suivre l’ensemble des 13 étapes, en incluant les temps d’attente pour la propagation DNS et l’émission des certificats. Le projet final tient dans un seul dépôt Git, avec quatre manifestes YAML et un script de nettoyage, ce qui le rend facilement reproductible sur un autre cluster ou par un collègue qui découvre le sujet.
Prérequis et versions exactes
Avant de commencer, réunissez les outils suivants. Ne sautez pas la vérification des versions : cert-manager 1.21 exige au minimum Kubernetes 1.33, et un cluster trop ancien provoquera des erreurs d’admission webhook difficiles à diagnostiquer.
- Un cluster Kubernetes fonctionnel (version 1.33 ou supérieure) : Minikube, K3s, ou un cluster managé AKS, GKE ou EKS
- kubectl configuré et pointant vers le bon contexte (
kubectl config current-context) - Helm 3 installé (Helm 3.16 ou plus récent recommandé)
- Un nom de domaine que vous contrôlez, avec accès à la zone DNS pour créer un enregistrement A
- Une adresse IP publique ou un load balancer accessible depuis Internet (obligatoire pour le challenge HTTP-01 de Let’s Encrypt)
- 10 Go d’espace disque libre et 4 Go de RAM disponibles pour un cluster de test local
- Un terminal Linux, macOS ou WSL2 sous Windows
Si vous testez en local sans domaine public, vous pouvez utiliser un service comme nip.io ou sslip.io, qui résout automatiquement des sous-domaines vers l’IP que vous indiquez, sans configuration DNS manuelle. C’est la méthode la plus rapide pour valider le tutoriel avant de le reproduire en production.
Un dernier point avant de commencer : vérifiez que votre pare-feu ou groupe de sécurité cloud autorise le trafic entrant sur les ports 80 et 443 vers le load balancer du contrôleur. Beaucoup de premiers essais échouent simplement parce que le port 80 reste fermé, ce qui bloque le challenge HTTP-01 sans qu’aucun message d’erreur explicite ne l’indique côté Kubernetes. Prenez le temps de tester ces deux ports avec un outil comme nc -zv votre-ip 80 depuis une machine extérieure à votre réseau interne.
Étape 1 : vérifier la version de votre cluster Kubernetes
Commencez toujours par confirmer la version exacte de votre cluster. cert-manager 1.21 référence Kubernetes 1.32 comme version minimale prise en charge sur EKS, GKE et AKS, et la matrice complète va jusqu’à 1.36. Un cluster plus ancien peut fonctionner, mais sans garantie de compatibilité du webhook d’admission.
kubectl version --short
kubectl get nodes -o wide
Exemple de sortie attendue :
Client Version: v1.34.1
Server Version: v1.34.1
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 2m v1.34.1
Si votre version affiche moins de 1.33, mettez à niveau le cluster avant de continuer. Sur Minikube, la commande minikube start --kubernetes-version=v1.34.1 permet de forcer une version récente dès la création.
Étape 2 : installer le contrôleur Ingress-nginx via Helm
Ajoutez le dépôt Helm officiel du projet, puis installez le chart dans un namespace dédié. Séparer Ingress-nginx dans son propre namespace facilite l’application de quotas de ressources et de politiques réseau strictes.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
kubectl create namespace ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.replicaCount=2 \
--set controller.resources.requests.cpu=100m \
--set controller.resources.requests.memory=128Mi
Vérifiez que le service reçoit une adresse externe :
kubectl get svc -n ingress-nginx ingress-nginx-controller
Sur un cluster cloud, la colonne EXTERNAL-IP affichera une adresse ou un nom de domaine de load balancer après quelques minutes. Sur Minikube, exécutez minikube tunnel dans un terminal séparé pour exposer le service localement.
Le choix de deux réplicas n’est pas anodin : un seul pod pour le contrôleur Ingress crée un point de défaillance unique sur toute votre exposition HTTPS. Si ce pod redémarre pendant une mise à jour ou un incident sur le nœud, l’ensemble du trafic entrant est coupé le temps du redémarrage. Avec deux réplicas répartis sur des nœuds différents (via une règle d’anti-affinité si votre cluster le permet), une coupure de nœud n’affecte qu’une partie du trafic, le temps que Kubernetes reprogramme le pod manquant.
Étape 3 : pointer votre nom de domaine vers le contrôleur
Créez un enregistrement DNS de type A pointant vers l’adresse IP externe récupérée à l’étape précédente. C’est l’étape la plus souvent bâclée, et elle cause la majorité des échecs de challenge Let’s Encrypt : le challenge HTTP-01 exige que le domaine résolve déjà vers votre ingress avant que cert-manager ne tente la validation.
# Vérifier la propagation DNS avant de continuer
dig +short demo.exemple.fr
nslookup demo.exemple.fr
Patientez jusqu’à ce que la commande retourne bien l’IP de votre ingress. Selon le registrar, la propagation peut prendre de quelques secondes à plusieurs heures. Ne passez pas à l’émission du certificat tant que la résolution n’est pas confirmée.
Étape 4 : installer cert-manager avec Helm
cert-manager s’installe lui aussi via Helm, avec un flag obligatoire pour créer les Custom Resource Definitions (CRD). Utilisez la version 1.21 ou la 1.20.4, toutes deux publiées en 2026 et compatibles avec un cluster 1.33+.
helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl create namespace cert-manager
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.21.2 \
--set crds.enabled=true
Confirmez que les trois pods (controller, webhook, cainjector) sont bien en état Running avant de continuer :
kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS
cert-manager-7d9f8c6b5-x2k9p 1/1 Running 0
cert-manager-cainjector-6b8d7f9c4-p8m2q 1/1 Running 0
cert-manager-webhook-5f7c9d8b6-t3n7r 1/1 Running 0
Si un pod reste en Pending plus de deux minutes, inspectez les événements avec kubectl describe pod : c’est souvent un problème de ressources insuffisantes sur le nœud.
Le pod webhook mérite une attention particulière : il intercepte chaque création ou modification de ressource cert-manager pour valider son schéma avant que l’API Kubernetes ne l’enregistre. Tant que ce pod n’est pas prêt, toute tentative d’appliquer un ClusterIssuer ou un Certificate échoue avec une erreur de connexion au webhook, ce qui déroute beaucoup de débutants qui pensent avoir mal écrit leur manifeste alors que le problème vient simplement d’un démarrage encore en cours.
Étape 5 : créer un ClusterIssuer Let’s Encrypt
Le ClusterIssuer indique à cert-manager quelle autorité de certification utiliser et comment prouver la propriété du domaine. Commencez toujours par l’environnement de staging de Let’s Encrypt : les limites de débit en production sont strictes, et un échec répété en test peut vous bloquer plusieurs heures.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
ingress:
ingressClassName: nginx
Appliquez ce manifeste, puis vérifiez son état :
kubectl apply -f cluster-issuer-staging.yaml
kubectl get clusterissuer letsencrypt-staging -o wide
Le champ READY doit passer à True en quelques secondes. Si ce n’est pas le cas, la cause la plus fréquente est une adresse email mal formée ou un namespace incorrect dans le solver.
L’adresse email renseignée ici n’est pas décorative : Let’s Encrypt s’en sert pour vous prévenir par courrier si un certificat approche de l’expiration sans renouvellement, ou si une modification de politique impose une action de votre part. Utilisez une adresse suivie par une équipe, pas celle d’une seule personne qui pourrait quitter l’organisation sans que personne ne reprenne cette alerte.
Étape 6 : déployer une application de démonstration
Créez un déploiement minimal et son service associé pour avoir quelque chose à exposer. Un simple serveur nginx avec une page statique suffit pour valider toute la chaîne TLS.
kubectl create namespace demo-app
kubectl create deployment demo-web --image=nginx:1.27 -n demo-app --replicas=2
kubectl expose deployment demo-web -n demo-app \
--port=80 --target-port=80 --name=demo-web-svc
Vérifiez que les deux réplicas tournent avant de passer à la ressource Ingress :
kubectl get pods -n demo-app
kubectl get svc -n demo-app
Dans un projet réel, remplacez évidemment cette image nginx générique par votre propre application packagée en conteneur. La logique de bout en bout reste identique : tant que votre application écoute sur un port HTTP interne et expose un Service Kubernetes, cert-manager et Ingress-nginx s’occupent de tout le reste de la couche TLS sans modification de votre code applicatif.
Étape 7 : créer la ressource Ingress avec annotation TLS
C’est l’étape charnière : l’annotation cert-manager.io/cluster-issuer indique à cert-manager de surveiller cette ressource Ingress et de générer automatiquement le certificat correspondant, sans intervention manuelle.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-web-ingress
namespace: demo-app
annotations:
cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
ingressClassName: nginx
tls:
- hosts:
- demo.exemple.fr
secretName: demo-web-tls
rules:
- host: demo.exemple.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-web-svc
port:
number: 80
Appliquez ce fichier avec kubectl apply -f ingress-demo.yaml. Dès que la ressource est créée, cert-manager génère une ressource Certificate et démarre le challenge HTTP-01.
Étape 8 : suivre l’émission du certificat en temps réel
Surveillez la ressource Certificate pour voir chaque étape du processus : création de la demande, résolution du challenge, puis émission finale.
kubectl get certificate -n demo-app -w
Sortie attendue une fois le certificat émis :
NAME READY SECRET AGE
demo-web-tls True demo-web-tls 47s
Si le champ READY reste à False après deux minutes, inspectez les événements du CertificateRequest et du Challenge :
kubectl describe certificate demo-web-tls -n demo-app
kubectl describe challenge -n demo-app
Étape 9 : basculer vers l’environnement de production Let’s Encrypt
Une fois le certificat de staging validé, créez un second ClusterIssuer pointant vers l’API de production, puis changez l’annotation sur votre Ingress. Ne réutilisez jamais le même secret de clé privée entre staging et production.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
ingressClassName: nginx
Let’s Encrypt applique des limites de débit strictes en production : 50 certificats par domaine enregistré par semaine, et 5 échecs de validation par compte, par heure, par nom d’hôte. Testez toujours en staging avant de basculer pour éviter de consommer ce quota.
Étape 10 : vérifier la chaîne TLS depuis l’extérieur
Ne faites jamais confiance uniquement au statut Kubernetes : validez la chaîne de certificats telle qu’un navigateur ou un client HTTP la verrait réellement.
curl -vI https://demo.exemple.fr 2>&1 | grep -E "SSL|subject|issuer"
openssl s_client -connect demo.exemple.fr:443 -servername demo.exemple.fr </dev/null 2>/dev/null | openssl x509 -noout -dates
Exemple de sortie attendue :
notBefore=Sep 26 08:14:32 2026 GMT
notAfter=Dec 25 08:14:31 2026 GMT
Un certificat Let’s Encrypt standard est valide 90 jours. cert-manager déclenche le renouvellement aux deux tiers de la durée de vie du certificat par défaut, soit autour du 60e jour, environ 30 jours avant l’expiration.
Étape 11 : restreindre les privilèges avec RBAC et NetworkPolicy
Un contrôleur Ingress mal isolé peut devenir un point d’accès privilégié vers l’ensemble du cluster. Limitez ses permissions au strict nécessaire et isolez son trafic réseau.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ingress-nginx-restrict
namespace: ingress-nginx
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from: []
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 53
- protocol: UDP
port: 53
Vérifiez aussi que le ServiceAccount du contrôleur ne dispose pas de droits cluster-admin. Le chart Helm officiel applique déjà un ClusterRole restreint par défaut, mais un audit régulier avec kubectl auth can-i --list --as=system:serviceaccount:ingress-nginx:ingress-nginx reste recommandé.
Étape 12 : auditer votre exposition avant la fin de vie d’Ingress-nginx
Avec l’échéance de mars 2026 pour la fin de vie du contrôleur Ingress-nginx, dressez l’inventaire de toutes vos ressources Ingress qui en dépendent avant que le support ne s’arrête réellement.
kubectl get ingress --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.ingressClassName}{"\n"}{end}'
Cette commande liste chaque Ingress avec sa classe associée. Toute ligne indiquant nginx comme classe doit figurer dans votre plan de migration vers un contrôleur encore maintenu, comme le contrôleur NGINX officiel en version 5.6.3, ou une alternative telle que Traefik ou HAProxy Ingress.
Étape 13 : automatiser le nettoyage et la reproductibilité
Pour un environnement de test, gardez toujours un script de nettoyage à portée de main. Cela évite d’accumuler des ressources orphelines qui consomment du quota Let’s Encrypt inutilement.
#!/bin/bash
set -euo pipefail
kubectl delete ingress demo-web-ingress -n demo-app --ignore-not-found
kubectl delete certificate demo-web-tls -n demo-app --ignore-not-found
kubectl delete namespace demo-app --ignore-not-found
helm uninstall cert-manager -n cert-manager
helm uninstall ingress-nginx -n ingress-nginx
kubectl delete namespace cert-manager --ignore-not-found
kubectl delete namespace ingress-nginx --ignore-not-found
echo "Nettoyage terminé."
Enregistrez ce script dans votre dépôt Git aux côtés des manifestes YAML. Un projet complet reproductible tient en quatre fichiers : le ClusterIssuer de staging, celui de production, l’Ingress applicatif, et ce script de nettoyage.
Structurer le projet complet dans un dépôt Git
Pour que ce tutoriel serve réellement de base de départ, organisez les fichiers dans une arborescence claire plutôt que de coller les manifestes en vrac. Voici la structure recommandée, testée sur ce tutoriel de bout en bout :
mon-projet-ingress-tls/
├── manifests/
│ ├── 01-cluster-issuer-staging.yaml
│ ├── 02-cluster-issuer-prod.yaml
│ ├── 03-demo-deployment.yaml
│ ├── 04-demo-ingress.yaml
│ └── 05-network-policy.yaml
├── scripts/
│ └── cleanup.sh
├── MIGRATION.md
└── README.md
Le fichier MIGRATION.md mérite un traitement à part : c’est lui qui documente votre plan de sortie d’Ingress-nginx pour toute personne qui reprendrait le projet après vous. Il doit contenir a minima la liste des Ingress concernés, la date cible de migration, et le contrôleur de remplacement retenu. Une fois l’arborescence en place, appliquez l’ensemble des manifestes dans l’ordre numéroté pour reproduire exactement l’environnement décrit dans ce tutoriel :
kubectl apply -f manifests/01-cluster-issuer-staging.yaml
kubectl apply -f manifests/03-demo-deployment.yaml
kubectl apply -f manifests/04-demo-ingress.yaml
kubectl apply -f manifests/05-network-policy.yaml
kubectl get certificate -n demo-app
kubectl get ingress -n demo-app
Ce découpage en fichiers numérotés facilite aussi l’intégration dans un pipeline GitOps avec ArgoCD ou Flux : chaque fichier devient une ressource versionnée que l’outil de synchronisation applique automatiquement au cluster, sans intervention manuelle après la première mise en place.
Le fichier README.md, souvent négligé dans les projets internes, prend ici une valeur particulière : il doit indiquer clairement quel ClusterIssuer utiliser en staging, lequel utiliser en production, et surtout rappeler que les deux ne doivent jamais être appliqués simultanément sur la même ressource Ingress sans changer l’annotation. Cette précision simple évite qu’un collègue pressé n’épuise le quota de production en testant par erreur avec le mauvais issuer.
Observer le cycle de vie des certificats avec Prometheus
cert-manager expose nativement des métriques Prometheus sur le port 9402 du pod controller, avec notamment certmanager_certificate_expiration_timestamp_seconds qui donne la date d’expiration exacte de chaque certificat sous forme d’horodatage Unix. Sur un cluster où Prometheus tourne déjà (voir notre tutoriel dédié à Prometheus et Grafana sur Kubernetes), il suffit d’ajouter une ressource ServiceMonitor pour commencer à collecter ces données.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: cert-manager
namespace: cert-manager
spec:
selector:
matchLabels:
app: cert-manager
endpoints:
- port: tcp-prometheus-servicemonitor
interval: 60s
path: /metrics
Une fois les métriques collectées, une règle d’alerte simple suffit à couvrir le scénario le plus redouté : un certificat qui expire sans que personne ne s’en aperçoive. Configurez une alerte qui se déclenche si certmanager_certificate_expiration_timestamp_seconds tombe sous 7 jours restants, ce qui laisse encore une semaine de marge pour investiguer un renouvellement bloqué avant la coupure réelle du service. Cette alerte se révèle particulièrement utile après un incident réseau prolongé, un scénario où le renouvellement automatique peut silencieusement échouer plusieurs fois de suite sans qu’aucune page d’erreur ne s’affiche côté utilisateur avant l’expiration effective.
cert-manager expose aussi une métrique certmanager_certificate_ready_status qui reflète directement l’état READY vu par kubectl get certificate, mais interrogeable en continu plutôt qu’à la demande. Croisée avec un tableau de bord Grafana dédié, cette métrique donne une vision d’ensemble de tous les certificats du cluster en un coup d’œil, un gain de temps réel dès qu’un cluster héberge plus d’une dizaine d’applications exposées en HTTPS.
Comparatif des versions et compatibilité 2026
Le tableau suivant résume les versions actuelles des composants utilisés dans ce tutoriel, avec leurs dates de publication et leur compatibilité Kubernetes minimale.
| Composant | Version | Date de publication | Kubernetes minimal |
|---|---|---|---|
| cert-manager | 1.21.2 | 11 septembre 2026 | 1.33 |
| cert-manager (branche stable) | 1.20.4 | 16 septembre 2026 | 1.32 |
| Chart Helm ingress-nginx | 4.15.1 | 19 mars 2026 | 1.31 |
| Contrôleur ingress-nginx | v1.15.1 | 19 mars 2026 | 1.31 |
| Contrôleur NGINX officiel (alternative post-EOL) | 5.6.3 | 16 septembre 2026 | 1.31 |
Pièges fréquents à éviter
Ces erreurs reviennent le plus souvent lors de la mise en place de cert-manager avec Ingress-nginx, y compris chez des équipes expérimentées.
- Appliquer l’Ingress avant que le DNS ne résolve. Le challenge HTTP-01 échoue systématiquement si le domaine ne pointe pas encore vers le contrôleur au moment de la validation, et cert-manager ne relance pas toujours immédiatement une nouvelle tentative une fois le DNS propagé.
- Confondre Issuer et ClusterIssuer. Un Issuer est limité à un seul namespace, et si votre application vit ailleurs, cert-manager ne trouvera jamais la ressource. L’erreur retournée mentionne rarement cette cause de façon explicite.
- Passer directement en production sans tester en staging. Les limites de débit de Let’s Encrypt en production peuvent bloquer un domaine pendant une semaine entière, un délai qui peut coûter cher si le certificat concerne un service déjà annoncé aux utilisateurs.
- Oublier l’annotation
ingressClassName. Sans elle, plusieurs contrôleurs installés sur le même cluster entrent en conflit et aucun ne traite la ressource correctement, ce qui se traduit souvent par une page blanche sans message d’erreur clair. - Réutiliser le même secret de clé privée entre staging et production. Cela complique le débogage et peut provoquer des erreurs de validation croisées, en particulier quand plusieurs personnes de l’équipe testent en parallèle sur le même cluster.
- Ignorer les ressources orphelines après un test. Des CertificateRequest et Challenge non nettoyés s’accumulent et compliquent l’audit du cluster, au point de rendre difficile la distinction entre une ressource active et un reliquat de test oublié depuis des semaines.
- Ne pas surveiller la fin de vie du contrôleur. Continuer à déployer de nouvelles applications sur Ingress-nginx après mars 2026 sans plan de sortie augmente la dette technique à rattraper plus tard, et chaque nouvelle application déployée dans l’intervalle allonge d’autant la liste à migrer ensuite.
Guide de dépannage
Voici les situations de blocage les plus courantes, avec la commande à lancer et la cause probable.
| Symptôme | Commande de diagnostic | Cause probable |
|---|---|---|
| Certificate reste à READY=False | kubectl describe certificate | Challenge HTTP-01 non résolu, DNS non propagé |
| Challenge bloqué en état pending | kubectl describe challenge -n <namespace> | Le port 80 n’est pas accessible depuis Internet |
| ClusterIssuer reste READY=False | kubectl get clusterissuer -o yaml | Email invalide ou namespace du solver incorrect |
| Erreur “rate limited” de Let’s Encrypt | kubectl describe order -n <namespace> | Trop de tentatives en production, basculez en staging |
| Ingress ne reçoit aucun trafic | kubectl get svc -n ingress-nginx | EXTERNAL-IP encore en attente ou tunnel non actif sur Minikube |
| Webhook cert-manager injoignable | kubectl get pods -n cert-manager | Pod webhook non prêt, souvent après une mise à niveau incomplète |
| Certificat émis mais navigateur affiche une alerte | openssl s_client -connect host:443 | Cache DNS local ou secret TLS non recréé après renouvellement |
| Deux contrôleurs Ingress en conflit | kubectl get ingressclass | ingressClassName manquant ou dupliqué sur plusieurs ressources |
Face à un blocage, résistez à la tentation de supprimer et recréer immédiatement toutes les ressources : dans la majorité des cas listés ci-dessus, le problème vient d’une dépendance externe (DNS, pare-feu, quota Let’s Encrypt) et non d’une erreur dans les manifestes eux-mêmes. Commencez systématiquement par la commande kubectl describe sur la ressource bloquée : la section Events en bas de sortie contient presque toujours le message d’erreur exact qui explique le blocage, bien plus précis que le simple statut READY=False affiché par kubectl get.
Conseils avancés pour la production
Une fois le tutoriel de base maîtrisé, plusieurs ajustements renforcent la fiabilité en environnement de production. Activez d’abord la validation DNS-01 en complément du HTTP-01 : elle permet d’émettre des certificats wildcard, utiles si vous gérez de nombreux sous-domaines sous un même nom de domaine racine.
Ensuite, surveillez la date d’expiration de vos certificats avec une alerte proactive plutôt qu’en comptant uniquement sur le renouvellement automatique de cert-manager. Un exporteur Prometheus dédié aux métriques cert-manager permet de déclencher une alerte si un certificat approche de l’expiration sans que le renouvellement n’ait démarré, une situation qui peut survenir après un incident réseau prolongé.
Pour les clusters multi-régions, envisagez un ClusterIssuer par région avec des comptes ACME distincts, afin qu’une limite de débit atteinte dans une région n’affecte pas les autres. Enfin, documentez votre plan de sortie d’Ingress-nginx dans un fichier MIGRATION.md versionné : listez les Ingress concernés, la date cible, et le contrôleur de remplacement retenu. Cette traçabilité facilite grandement un audit de conformité, notamment dans le cadre du Cyber Resilience Act qui impose une gestion documentée des composants logiciels utilisés en production.
Protéger Ingress-nginx contre les abus avec des annotations de limitation de débit
Une fois le certificat en place, la surface d’attaque de votre application se déplace vers le volume de requêtes que le contrôleur laisse passer. Ingress-nginx embarque des annotations natives pour limiter le débit par adresse IP, ce qui atténue les tentatives de scraping agressif ou les débuts de déni de service applicatif avant même d’atteindre votre application.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-web-ingress
namespace: demo-app
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/limit-rps: "20"
nginx.ingress.kubernetes.io/limit-connections: "10"
spec:
ingressClassName: nginx
tls:
- hosts:
- demo.exemple.fr
secretName: demo-web-tls
rules:
- host: demo.exemple.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-web-svc
port:
number: 80
L’annotation limit-rps fixe un nombre maximal de requêtes par seconde et par adresse IP source, tandis que limit-connections plafonne le nombre de connexions simultanées ouvertes depuis une même IP. Ces valeurs dépendent entièrement du profil de trafic réel de votre application : commencez large, mesurez le trafic légitime sur une à deux semaines via vos métriques Prometheus, puis resserrez progressivement. Un seuil trop bas bloquera vos propres utilisateurs derrière un proxy d’entreprise partageant la même IP sortante, un piège fréquent dans les environnements professionnels européens.
Ces annotations restent une protection de premier niveau, pas un remplacement d’un pare-feu applicatif complet. Pour une application exposée publiquement à fort trafic, combinez-les avec une solution en amont capable d’absorber les pics de volume avant même d’atteindre votre cluster, qu’il s’agisse d’un CDN ou d’un service de protection réseau dédié. Ingress-nginx et cert-manager gèrent très bien la couche TLS et le routage applicatif, mais ne remplacent pas une défense en profondeur face à un trafic massif et distribué.
Comparer HTTP-01 et DNS-01 pour vos challenges ACME
Le choix du type de challenge influence directement la souplesse de votre configuration. Voici les critères clés pour trancher.
| Critère | HTTP-01 | DNS-01 |
|---|---|---|
| Configuration requise | Aucun accès API DNS nécessaire | Accès API du fournisseur DNS obligatoire |
| Certificats wildcard | Non supporté | Supporté |
| Accessibilité réseau | Le port 80 doit être ouvert publiquement | Aucune exposition réseau requise |
| Complexité de mise en place | Faible, idéal pour débuter | Plus élevée, nécessite un solver DNS spécifique |
| Cas d’usage typique | Une application, un sous-domaine | Nombreux sous-domaines sous un même domaine racine |
Dans la pratique, beaucoup d’équipes commencent avec HTTP-01 pour sa simplicité, puis migrent vers DNS-01 dès qu’elles ajoutent un deuxième ou un troisième sous-domaine. Le solver DNS-01 de cert-manager prend en charge la plupart des fournisseurs DNS majeurs, avec des intégrations natives et des identifiants stockés dans un Secret Kubernetes dédié, ce qui évite d’exposer des clés API en clair dans les manifestes versionnés.
Préparer la migration après la fin de vie d’Ingress-nginx
La feuille de route de migration recommandée suit quatre phases. D’abord, un inventaire complet de toutes les ressources Ingress dépendantes du contrôleur communautaire, via la commande d’audit vue à l’étape 12. Ensuite, un test en environnement de préproduction du contrôleur NGINX officiel (version 5.6.3 au 16 septembre 2026), qui reste maintenu commercialement au-delà de mars 2026.
Troisième phase : basculer les Ingress non critiques en premier, en changeant simplement la valeur de ingressClassName, puis en validant que le certificat cert-manager se réémet correctement sur le nouveau contrôleur. Quatrième et dernière phase : migrer les applications critiques, avec une fenêtre de rollback documentée au cas où le nouveau contrôleur introduirait une régression de comportement, notamment sur les annotations spécifiques à Ingress-nginx qui n’ont pas toutes d’équivalent direct ailleurs.
Cette approche progressive limite le risque tout en respectant l’échéance. Une migration précipitée, réalisée en urgence après l’arrêt effectif du support, expose à des failles non corrigées le temps que l’équipe redécouvre les subtilités d’un nouveau contrôleur sous pression.
Pour une équipe de taille moyenne gérant une dizaine d’applications derrière Ingress-nginx, comptez généralement entre deux et quatre semaines pour boucler les quatre phases, en tenant compte des fenêtres de changement et des cycles de validation propres à chaque organisation. Les secteurs soumis à une réglementation renforcée, comme la finance ou la santé, ajoutent souvent une phase de validation de conformité supplémentaire avant tout changement touchant à la couche d’exposition réseau. Prévoyez ce délai dans votre planning plutôt que de le découvrir au moment de demander une autorisation de déploiement en production.
Ressources officielles pour aller plus loin
Pour approfondir chaque brique de ce tutoriel, la documentation officielle de cert-manager détaille l’ensemble des types de solvers ACME disponibles. La documentation Kubernetes sur les ressources Ingress explique la spécification complète de l’API, et la page dédiée aux contrôleurs Ingress liste les alternatives maintenues.
Côté Let’s Encrypt, la page des limites de débit est incontournable avant tout test en production, et le RFC 8555 décrit le protocole ACME sous-jacent pour qui veut comprendre le mécanisme en profondeur. Le dépôt GitHub du projet ingress-nginx reste la source la plus fiable pour suivre l’avancement réel du calendrier de fin de vie, notamment via les annonces publiées directement dans les issues et les notes de version du projet.
Gardez ces liens en favoris plutôt que de vous fier à des résumés tiers, aussi bien rédigés soient-ils : un calendrier de fin de vie peut évoluer, et seule la source officielle fait foi le jour où vous devez justifier une décision de migration auprès de votre hiérarchie ou d’un auditeur externe.
Foire aux questions
Faut-il migrer immédiatement si mon cluster utilise encore Ingress-nginx ?
Non, mais commencez l’inventaire dès maintenant. La fin de vie communautaire annoncée pour mars 2026 ne signifie pas une coupure brutale du contrôleur en place, mais l’absence de correctifs de sécurité futurs. Planifiez la migration sur plusieurs mois plutôt que dans l’urgence, en commençant par les applications les moins critiques pour roder votre procédure avant de toucher aux services en première ligne.
Le challenge HTTP-01 fonctionne-t-il derrière un pare-feu strict ?
Non, il exige que le port 80 soit accessible publiquement au moment de la validation. Si votre environnement bloque ce port en permanence, utilisez plutôt un challenge DNS-01, qui ne nécessite aucune exposition réseau entrante et convient mieux aux environnements internes fortement cloisonnés.
Puis-je utiliser cert-manager sans Ingress-nginx ?
Oui. cert-manager fonctionne avec n’importe quel contrôleur Ingress compatible, ainsi qu’avec Gateway API. La configuration du ClusterIssuer reste identique, seule l’annotation ou la ressource cible change, ce qui rend la migration vers un autre contrôleur bien plus simple que si tout reposait sur une intégration propriétaire.
Que se passe-t-il si le renouvellement automatique échoue ?
Le certificat continue de fonctionner jusqu’à son expiration réelle, mais cert-manager retentera le renouvellement à intervalles réguliers. Surveillez les événements de la ressource Certificate pour détecter un échec persistant avant l’expiration, idéalement via l’alerte Prometheus décrite plus haut dans ce tutoriel plutôt qu’en découvrant le problème au moment où les utilisateurs signalent une erreur de certificat expiré.
Combien coûte un certificat Let’s Encrypt ?
Rien. Let’s Encrypt est une autorité de certification gratuite et automatisée, financée par un consortium à but non lucratif. Le seul coût réel est votre temps d’intégration initiale.
Un certificat wildcard fonctionne-t-il avec le challenge HTTP-01 ?
Non. Les certificats wildcard exigent obligatoirement un challenge DNS-01, car la validation doit prouver le contrôle de l’ensemble de la zone DNS, pas seulement d’un chemin HTTP accessible.
Comment savoir si mon contrôleur Ingress-nginx est vulnérable à une faille connue ?
Consultez régulièrement le dépôt GitHub officiel du projet ainsi que la base CVE de votre distribution Kubernetes. Une version antérieure à 1.15.1 doit être mise à niveau rapidement, surtout après l’annonce de fin de vie, et un outil de scan d’image comme celui présenté dans notre tutoriel sur Trivy permet d’automatiser cette vérification à chaque déploiement.
Le contrôleur NGINX officiel est-il un remplacement direct ?
Il couvre la majorité des cas d’usage, mais certaines annotations spécifiques à Ingress-nginx n’ont pas d’équivalent strict. Testez systématiquement en préproduction avant de basculer une application critique.




