Introduction
L'Ingress NGINX est le point d'entrée le plus courant dans les clusters Kubernetes. Lorsque le trafic n'atteint pas votre application ou échoue avec les codes HTTP 404 ou 502, vous avez besoin d'une méthode fiable pour isoler la cause : est-ce le DNS et le routage d'hôte, la règle d'Ingress, le TLS, le Service ou les Pods derrière celui-ci ?
Ce guide vous propose un flux de travail pratique, étape par étape, avec des commandes sûres et des manifestes minimaux. Vous apprendrez à vérifier les règles d'hôte et la correspondance de chemin, valider le TLS, interpréter les erreurs 404 vs 502, et confirmer les backends et les endpoints. Chaque étape est conçue pour être à faible risque et observable, afin que vous puissiez l'appliquer dans des environnements de type production en toute confiance.
Aperçu du flux de travail
Utilisez cette séquence pour dépanner les problèmes d'Ingress NGINX en toute sécurité. Chaque étape réduit le périmètre d'impact et évite les modifications perturbatrices.
- Identifier la requête exacte qui échoue
- Notez l'URL complète : schéma, hôte et chemin, par exemple :
https://api.example.com/v1/ping - Capturez le code de statut et les en-têtes de réponse si disponibles
- Confirmer le DNS et le routage d'hôte
- Depuis un client, résolvez l'hôte :
nslookup api.example.com
- Depuis un nœud ou un pod de diagnostic à l'intérieur du cluster, testez le routage HTTP avec l'en-tête Host :
kubectl -n default run curl --rm -it --image=curlimages/curl:8.7.1 --restart=Never --command -- sh -lc \
"curl -sS -o /dev/null -w '%{http_code} %{remote_ip}\n' -H 'Host: api.example.com' http://<ip-externe-ingress>/v1/ping"
- Si l'Ingress se trouve derrière un LoadBalancer, remplacez
<ip-externe-ingress>par l'IP publique ou le DNS du load balancer.
- Vérifier l'objet Ingress et sa classe
- Listez et inspectez l'Ingress dans l'espace de noms cible :
kubectl get ingress
kubectl describe ingress api-ing
- Vérifiez que
spec.ingressClassNamecorrespond à votre contrôleur (souventnginxouingress-nginx). Si vous utilisez l'annotation héritée, elle doit êtrekubernetes.io/ingress.class: nginx. - Confirmez que les règles d'hôte et les chemins correspondent exactement à votre requête, y compris la casse et les barres obliques finales.
- Valider la correspondance de chemin et les réécritures
- Comprenez
pathType: - Prefix : correspond par préfixe de chemin. Exemple :
/apicorrespond à/api,/api/v1. - Exact : correspond uniquement au chemin exact.
- Si votre backend attend des chemins sans le préfixe, utilisez une réécriture. Par exemple, pour retirer
/apidu chemin de la requête :
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: api.example.com
http:
paths:
- path: /api/(.*)
pathType: Prefix
backend:
service:
name: api-svc
port:
number: 80
- Après les modifications, relancez les tests curl avec et sans barre oblique finale pour confirmer le comportement.
- Différencier 404 vs 502 au niveau de l'Ingress
- 404 Not Found depuis NGINX indique généralement qu'aucune règle d'hôte ou de chemin ne correspond à la requête. Vérifiez :
- L'hôte dans la requête correspond à
spec.rules[].host - Le chemin et le
pathTypecorrespondent à l'URI entrant - La classe d'Ingress est correcte
- 502 Bad Gateway indique généralement que la règle a correspondu mais que l'upstream a échoué. Causes courantes :
- Le Service n'a pas d'endpoints (zéro Pod Ready)
- Le port du Service ne correspond pas au
containerPort - Une NetworkPolicy ou un pare-feu bloque le trafic vers les pods
- L'application backend a fermé la connexion ou a expiré
- Vérifier Service, Endpoints et Pods
- Confirmez le sélecteur et les ports :
kubectl get svc api-svc -o wide
kubectl describe svc api-svc
kubectl get endpoints api-svc -o wide
- Si les endpoints sont vides, vérifiez que les étiquettes sur les Pods correspondent au sélecteur du Service :
kubectl get pods -l app=api -o wide
kubectl get pod <pod> -o jsonpath='{.metadata.labels}'
- Vérifiez les ports des conteneurs et la disponibilité :
kubectl describe pod <pod>
- Si les sondes de disponibilité (readiness probes) échouent, le Pod n'apparaîtra pas comme endpoint prêt et NGINX renverra 502.
- Inspecter le contrôleur NGINX Ingress
- Assurez-vous que le contrôleur est en cours d'exécution et en bonne santé :
kubectl -n ingress-nginx get pods -o wide
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller | tail -n 100
- Recherchez les rechargements de configuration, les erreurs upstream ou les erreurs TLS.
- Valider la configuration TLS
- Vérifiez le bloc TLS et la référence au secret :
kubectl get ingress api-ing -o yaml | sed -n '/tls:/,/rules:/p'
kubectl get secret api-tls -o yaml
- Le type de secret doit être
kubernetes.io/tlsavectls.crtettls.key. - Depuis un client, inspectez la chaîne de certificats :
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts < /dev/null | openssl x509 -noout -issuer -subject -dates
- Si vous voyez un certificat pour le mauvais hôte, soit le SNI ne correspond pas, soit l'hôte de l'Ingress ne correspond pas à l'hôte de la requête.
- Timeouts et gros en-têtes ou corps
- Les réponses backend longues peuvent nécessiter des ajustements. Appliquez des annotations sur des chemins ou des Ingress spécifiques plutôt que globalement pour minimiser les risques :
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
- Validation sûre avant le déploiement
- Utilisez
kubectl diffpour prévisualiser les changements :
kubectl apply -f ingress.yaml --server-side --dry-run=server
kubectl diff -f ingress.yaml
- Validez en interrogeant le load balancer avec des en-têtes Host et en interrogeant les Services ClusterIP depuis un pod de diagnostic pour isoler les problèmes de Service vs Ingress :
# Tester le Service directement à l'intérieur du cluster
kubectl -n default run diag --rm -it --image=curlimages/curl:8.7.1 --restart=Never --command -- sh -lc \
"curl -sS -i http://api-svc.default.svc.cluster.local:80/healthz"
Plan pilote local
Créez un pilote étroit et mesurable dans un espace de noms isolé pour confirmer le routage, le TLS et les backends de bout en bout.
- Espace de noms et application exemple
apiVersion: v1
kind: Namespace
metadata:
name: ingress-pilot
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
namespace: ingress-pilot
spec:
replicas: 2
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: hashicorp/http-echo:0.2.3
args: ["-text=hello", "-listen=:8080" ]
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: echo-svc
namespace: ingress-pilot
spec:
selector:
app: echo
ports:
- port: 80
targetPort: 8080
- Ingress HTTP de base
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-ing
namespace: ingress-pilot
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: echo.local
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: echo-svc
port:
number: 80
- Tester en toute sécurité
- Appliquez et vérifiez :
kubectl apply -f pilot.yaml
kubectl -n ingress-pilot get ingress echo-ing -o wide
kubectl -n ingress-pilot describe ingress echo-ing
kubectl -n ingress-pilot get endpoints echo-svc
- Depuis un pod de diagnostic, interrogez l'Ingress en utilisant l'en-tête Host :
kubectl -n ingress-pilot run tester --rm -it --image=curlimages/curl:8.7.1 --restart=Never --command -- sh -lc \
"curl -i -H 'Host: echo.local' http://<ip-externe-ingress>/"
- Résultat attendu :
HTTP/1.1 200et corpshello.
- Pilote TLS (optionnel)
- Créez un secret TLS dans le même espace de noms :
kubectl -n ingress-pilot create secret tls echo-tls \
--cert=server.crt --key=server.key
- Ajoutez TLS à l'Ingress :
spec:
tls:
- hosts:
- echo.local
secretName: echo-tls
- Validez le certificat et le SNI :
openssl s_client -connect <ip-externe-ingress>:443 -servername echo.local < /dev/null | openssl x509 -noout -subject -dates
- Critères de succès
- Le chemin HTTP
/renvoie 200 avec le corpshello. - Le changement de l'en-tête Host vers un hôte non correspondant produit 404.
- La suppression de tous les endpoints du Service produit 502, puis revient à 200 lorsque les endpoints sont restaurés.
- Avec TLS configuré, le sujet du certificat correspond à
echo.localet la requête renvoie 200.
Conclusion
Lorsque l'Ingress NGINX échoue, traitez-le comme un puzzle de routage que vous pouvez résoudre étape par étape : confirmez le DNS et l'en-tête Host, vérifiez la classe et les règles de l'Ingress, contrôlez la correspondance de chemin et les réécritures, différenciez 404 de 502, et validez les Services, Endpoints et Pods. Utilisez des annotations ciblées uniquement lorsque nécessaire et testez toujours dans un pilote étroit avant d'apporter des modifications plus larges.
Prochaines étapes :
- Gardez un modèle de pod de diagnostic prêt pour interroger les Services et l'Ingress avec des en-têtes Host.
- Standardisez les patterns d'Ingress pour les hôtes, les chemins et le TLS afin que les équipes puissent réutiliser des blocs de construction connus et fiables.
- Capturez une courte liste de contrôle pour le triage 404 vs 502 et stockez-la avec vos runbooks d'application.