Introduction
Les mises à niveau de Kubernetes Ingress touchent l’une des zones les plus sensibles de votre plate-forme : la manière dont les utilisateurs accèdent à vos applications. Un bon plan permet de passer à des API supportées, des contrôleurs modernes et des politiques de trafic plus fines sans casser les routes ni le TLS. Ce guide propose une approche pratique et à faible risque pour la mise à niveau et la migration de Kubernetes Ingress, de l’inventaire et la planification jusqu’à la vérification, les modes de panne et le rollback.
Ce que vous obtiendrez :
- Prérequis clairs et étapes d’inventaire d’environnement.
- Trois voies sûres : mise à niveau d’API seule, upgrade du contrôleur sur place, et migration en parallèle.
- YAML concrets, commandes et résultats attendus.
- Modes de panne, rollback et une checklist reproductible.
Le premier pilote doit être étroit, mesurable et facilement inspectable en local et en préproduction avant tout changement en production. Gardez un périmètre réduit, vérifiez à fond, puis étendez.
Inventaire des versions et de l’environnement
Avant tout changement, capturez précisément l’état de ce que vous avez. Cela oriente le choix de la voie de mise à niveau et évite les surprises.
- Identifier les capacités du cluster et des API
- Vérifier la version du cluster :
kubectl version --short
- Confirmer les groupes d’API Ingress et la version préférée :
kubectl api-resources | grep -i ingress
kubectl explain ingress | head -n 5
Attendu : networking.k8s.io/v1 est disponible sur les clusters modernes (1.19+). Si vous dépendez encore de extensions/v1beta1, planifiez d’abord une migration d’API.
- Repérer vos contrôleurs et classes Ingress
- Lister les ressources IngressClass :
kubectl get ingressclass
- Retrouver les déploiements de contrôleurs (souvent dans
ingress-nginx,nginx-ingress,traefikou spécifiques fournisseur) :
kubectl get deploy, ds, svc -A | grep -i ingress
- Inspecter l’IngressClass pour la chaîne du contrôleur (exemple ingress-nginx) :
kubectl get ingressclass -o yaml
Attendu : une valeur du type spec.controller: k8s.io/ingress-nginx pour le contrôleur communautaire ingress-nginx.
- Cartographier le trafic et le TLS
- Lister les Ingress et leurs adresses :
kubectl get ing -A -o wide
- Inventorier les hôtes, chemins et secrets TLS (note : les secrets TLS sont dans le même namespace que l’Ingress) :
kubectl get ing -A -o jsonpath='{range .items[*]}{.metadata.namespace} {.metadata.name} {.spec.rules[*].host} {.spec.tls[*].secretName}{"\n"}{end}'
- Pour chaque Ingress public, identifiez les enregistrements DNS et les TTL actuels. Abaissez les TTL en amont de tout basculement planifié.
- Triage des risques pour les fonctionnalités incompatibles
- Relever les annotations utilisées (rewrites, timeouts, authentification, canary). Certaines peuvent se comporter différemment selon la version du contrôleur.
- Identifier les backends utilisant des ports nommés vs numériques, et les Services avec des probes non standard.
Changements de l’API Ingress en bref
| Zone | v1beta1 | networking.k8s.io/v1 | Notes |
|---|---|---|---|
| Groupe d’API | extensions/v1beta1 | networking.k8s.io/v1 | v1beta1 est supprimé sur les versions récentes |
| Référence backend | serviceName/servicePort | backend.service.name/port.number ou port.name | Structure modifiée en v1 |
| Type de chemin | implicite | pathType: Prefix, Exact, ou ImplementationSpecific | pathType requis en v1 |
| Sélection de classe | annotation: kubernetes.io/ingress.class | spec.ingressClassName | Préférez ingressClassName en v1 |
| Secret TLS | même namespace que l’Ingress | idem | Pas de changement ; vérifiez l’alignement de namespace |
Chemin de configuration sûr
Choisissez le plus petit changement qui atteint votre objectif. Trois options éprouvées :
A) Mise à niveau d’API seule (conservez votre contrôleur)
- Quand : votre contrôleur supporte déjà networking.k8s.io/v1 et vous ne changez que les manifests.
- Bénéfice : peu d’éléments mouvants. Idéal pour un premier pilote.
B) Mise à niveau du contrôleur sur place (même classe et même Service)
- Quand : vous voulez de nouvelles fonctions ou corrections de CVE tout en conservant le même Service LoadBalancer ou NodePort.
- Bénéfice : pas de changement DNS. Déploiements serrés avec surge et zéro indisponibilité.
C) Migration en parallèle (nouvelle classe et nouveau Service)
- Quand : vous remplacez la famille de contrôleur ou changez une configuration majeure. Ancien et nouveau contrôleurs tournent en parallèle avec des IngressClass distinctes.
- Bénéfice : canary ou bascule hôte par hôte en sécurité. Rollback simple via ingressClassName ou poids DNS.
A) Exemple de mise à niveau d’API seule
Supposons cet Ingress hérité (exemple construit) :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-legacy
namespace: prod
annotations:
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts: ['app.example.com']
secretName: tls-app
rules:
- host: app.example.com
http:
paths:
- path: /
backend:
serviceName: web
servicePort: 80
Migrez vers v1 avec pathType explicite et backend structuré :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: tls-app
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Appliquer en sécurité :
kubectl apply -f web-ingress-v1.yaml
kubectl describe ing -n prod web
Attendu : l’adresse reste identique, le secret TLS est trouvé et les règles correspondent à l’ancien Ingress.
B) Exemple de mise à niveau du contrôleur sur place (ingress-nginx)
- Confirmer la classe et le Service existants
kubectl get ingressclass
kubectl get svc -n ingress-nginx
- Préparer un déploiement contrôlé (commandes construites ; adaptez à votre outillage)
- Assurez-vous qu’un PodDisruptionBudget protège le contrôleur et que les readinessProbes sont au vert.
- Définir une stratégie de rollout sûre (exemple) :
kubectl patch deploy -n ingress-nginx ingress-nginx-controller -p '{"spec":{"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxUnavailable":0,"maxSurge":1}}}}'
- Mettre à jour l’image du contrôleur vers la version cible, puis surveiller :
kubectl set image deploy/ingress-nginx-controller -n ingress-nginx controller=registry.k8s.io/ingress-nginx/controller: vX.Y.Z
kubectl rollout status deploy/ingress-nginx-controller -n ingress-nginx --timeout=3m
kubectl logs deploy/ingress-nginx-controller -n ingress-nginx --tail=100
Attendu : pas de chute d’endpoints, l’IP externe du Service reste inchangée et les Ingress existants se resynchronisent proprement.
Rollback (si nécessaire) :
kubectl rollout undo deploy/ingress-nginx-controller -n ingress-nginx
C) Exemple de migration en parallèle (bascule par classe)
Objectif : exécuter un nouveau contrôleur en parallèle, ne lier que certains Ingress à celui-ci, valider, puis déplacer plus de trafic.
- Créer une nouvelle IngressClass pour le nouveau contrôleur (exemple construit) :
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx-new
spec:
controller: k8s.io/ingress-nginx
- Déployer le nouveau contrôleur qui référence cette classe (suivez la documentation de votre chart ou fournisseur). Vérifiez qu’il crée un Service distinct tel que
ingress-nginx-new-controlleravec sa propre IP externe.
- Dupliquer un Ingress à faible risque pour cibler la nouvelle classe :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-new
namespace: prod
spec:
ingressClassName: nginx-new
tls:
- hosts:
- app-canary.example.com
secretName: tls-app
rules:
- host: app-canary.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
- Créer un DNS pour
app-canary.example.compointant vers l’IP du Service du nouveau contrôleur avec un TTL court (exemple : 60 secondes). Vérifiez de bout en bout avant de déplacer les hôtes de production.
- Bascule hôte par hôte : modifiez l’Ingress de production en
ingressClassName: nginx-newet réappliquez. Alternativement, utilisez un DNS pondéré pour répartir le trafic entre les Services des anciens et nouveaux contrôleurs durant la transition.
Canary au sein d’un seul contrôleur (feature flag)
Si vous ne devez canaryer qu’une nouvelle version de backend (pas un nouveau contrôleur), vous pouvez utiliser un Ingress canary avec ingress-nginx.
Ingress principal (stable) :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-stable
namespace: prod
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Ingress canary (10% du trafic vers le Service web-canary) :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-canary
namespace: prod
annotations:
nginx.ingress.kubernetes.io/canary: 'true'
nginx.ingress.kubernetes.io/canary-weight: '10'
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-canary
port:
number: 80
Augmentez le poids au fur et à mesure que la confiance grandit.
Vérification et diagnostics
Validez chaque étape avec des contrôles explicites et des signaux attendus. Gardez des TTL bas et observez sur une fenêtre suffisante avant d’avancer.
Contrôles de base et signaux attendus
| Contrôle | Commande | Résultat attendu |
|---|---|---|
| Support API | kubectl api-resources | Ingress en networking.k8s.io/v1 |
| Statut Ingress | kubectl get ing -A -o wide | Colonne ADDRESS remplie pour chaque Ingress |
| Mappage de classe | kubectl get ingressclass -o wide | Noms de classes et chaînes contrôleur corrects |
| Événements | kubectl describe ing NAME -n NAMESPACE | Pas d’erreurs : secret TLS trouvé, backends résolus |
| Logs contrôleur | kubectl logs deploy/ingress-nginx-controller -n ingress-nginx | Cycles de sync sans erreur ni crashloop |
| Santé backend | curl -I https://host/healthz | HTTP 200/204 ; latence normale |
Diagnostics additionnels
- Confirmer la config générée (ingress-nginx) :
# Identifier un pod du contrôleur
POD=$(kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}')
# Inspecter un extrait de la config NGINX générée
kubectl exec -n ingress-nginx $POD -- cat /etc/nginx/nginx.conf | head -n 50
- Valider le contenu du secret TLS et l’alignement de namespace :
kubectl get secret tls-app -n prod -o yaml | grep -E 'tls\.crt|tls\.key'
- Confirmer les endpoints du Service :
kubectl get endpoints web -n prod -o yaml | grep addresses -A2
- Faire un petit test de charge (exemple construit) :
for i in $(seq 1 50); do curl -s -o /dev/null -w "%{http_code} %{time_total}\n" https://app.example.com/healthz; done | sort | uniq -c
Attendu : 200 stables avec des temps cohérents.
Modes de panne et reprise
Planifiez l’échec pour pouvoir récupérer vite et sereinement.
- 404 Not Found après bascule
- Cause : mauvais host, mismatch de chemin, ou default backend manquant. En v1,
pathTypeest requis et modifie le comportement de correspondance. - Correctif : utilisez
pathType: PrefixouExactselon l’intention, vérifiez l’orthographe de l’host et l’existence du Service backend. - Rollback : réappliquez le manifest Ingress connu bon (gardez-le à portée) ou revenez à l’ancienne classe via
ingressClassNamesi vous avez migré en parallèle.
- 502/504 depuis l’amont
- Cause : endpoints du Service non prêts, port en mismatch, ou readiness checks en échec.
- Correctif : vérifiez les selectors du Service, les endpoints et la readiness des pods. Confirmez le numéro vs le nom de port backend.
- Rollback : réduisez le poids canary à 0 ou revenez à l’Ingress stable.
- Erreurs de handshake ou de certificat TLS
- Cause : secret TLS introuvable, mauvais namespace, ou SAN manquant pour l’hôte.
- Correctif : assurez-vous que le secret existe dans le namespace de l’Ingress et contient
tls.crtettls.keyvalides pour l’hôte. - Rollback : rétablissez l’ancien secret TLS et réappliquez.
- Le contrôleur n’attribue jamais d’adresse
- Cause : latence de provisioning LoadBalancer, permissions cloud, ou mauvaise configuration.
- Correctif : inspectez les événements du Service, les logs du fournisseur cloud et du contrôleur. Vérifiez le type de
Serviceet ses annotations. - Rollback : gardez l’ancien contrôleur comme primaire ; évitez tout changement DNS tant que le nouveau Service n’a pas d’adresse.
- Changement de comportement d’annotation
- Cause : certaines annotations diffèrent entre versions de contrôleur.
- Correctif : comparez les annotations supportées, testez sur un hôte canary et ajustez/supprimez les clés dépréciées.
- Rollback : restaurez l’ancien jeu d’annotations et la version précédente du contrôleur.
- Routage inattendu après migration d’API
- Cause : hypothèses héritées de v1beta1 sur la correspondance de chemins.
- Correctif : définissez explicitement
pathType; pour les regex ou réécritures, vérifiez les annotations spécifiques au contrôleur. - Rollback : si supporté par votre cluster, revenez au manifest précédent le temps de corriger les chemins.
Playbooks de rollback
A) Rollback d’une mise à niveau API seule
# Réappliquer le manifest fonctionnel précédent
kubectl apply -f web-ingress-previous.yaml
# Confirmer le statut
kubectl describe ing -n prod web
B) Rollback d’un upgrade du contrôleur sur place
# Revenir au ReplicaSet antérieur
kubectl rollout undo deploy/ingress-nginx-controller -n ingress-nginx
# Observer le retour à Ready
kubectl rollout status deploy/ingress-nginx-controller -n ingress-nginx --timeout=3m
C) Rollback d’une migration en parallèle
- Rebasculer l’Ingress de production de
ingressClassName: nginx-newversingressClassName: nginxet appliquer. - Si DNS pondéré, remettre 100% sur l’ancien contrôleur et 0% sur le nouveau.
- Supprimer les Ingress canary/dupliqués visant la nouvelle classe une fois la stabilité revenue.
Vérification après rollback :
kubectl get ing -A -o wide
kubectl logs deploy/ingress-nginx-controller -n ingress-nginx --tail=100
curl -I https://app.example.com/healthz
Attendu : comportement précédent rétabli avec réponses saines.
Liste de contrôle d’exploitation
Utilisez cette checklist pour chaque mise à niveau ou migration. Cochez chaque point ; ne sautez pas les jalons de vérification.
Planification et inventaire
- [ ] Consigner la version du cluster et confirmer la dispo de networking.k8s.io/v1.
- [ ] Lister tous les Ingress, hôtes, chemins et secrets TLS.
- [ ] Identifier les contrôleurs, classes et Services Ingress actuels.
- [ ] Abaisser les TTL DNS des hôtes concernés.
Sélection du pilote
- [ ] Choisir un hôte ou chemin à faible risque pour le premier pilote.
- [ ] Décider de l’approche : API seule, upgrade sur place, ou migration parallèle.
- [ ] Préparer les manifests du pilote, incluant
pathTypeetingressClassName.
Exécution du changement
- [ ] Appliquer d’abord en environnement non prod ; valider de bout en bout.
- [ ] Pour l’upgrade sur place, garantir un rollout surge/zero-unavailable.
- [ ] Pour la migration parallèle, créer une nouvelle IngressClass et un nouveau Service de contrôleur.
- [ ] En canary, commencer à 5-10% et observer.
Vérification
- [ ] Vérifier le statut Ingress et les champs ADDRESS.
- [ ] Examiner les logs du contrôleur pour erreurs et rechargements de config.
- [ ] Valider les certificats TLS et SAN pour tous les hôtes.
- [ ] Sonder les endpoints de santé ; confirmer latence et taux d’erreur.
Décision et montée en charge
- [ ] Maintenir l’état stable sur une fenêtre d’observation convenue.
- [ ] Augmenter le poids canary ou déplacer d’autres hôtes.
- [ ] Documenter les changements d’annotations ou de comportement découverts.
Préparation au rollback
- [ ] Conserver les manifests et versions de contrôleur antérieurs.
- [ ] Préparer les poids DNS ou bascules d’ingressClassName.
- [ ] Vérifier les commandes de rollback en préproduction.
Conclusion
Réussir une mise à niveau ou une migration de Kubernetes Ingress consiste à cadrer l’ampleur du changement, valider chaque étape et garder un chemin de retour clair. Commencez par une mise à niveau d’API seule quand c’est possible, puis passez aux upgrades du contrôleur sur place ou aux migrations parallèles lorsque vous avez besoin de nouvelles fonctionnalités ou d’une autre famille de contrôleur. Gardez les pilotes petits, utilisez pathType et ingressClassName de façon explicite, validez avec les logs et des probes, et stockez des manifests connus bons pour une reprise instantanée. Avec une checklist courte et reproductible et un premier pilote étroit, vous pouvez moderniser Ingress en confiance et avec un minimum de perturbations.