Introduction
L'Ingress Kubernetes est une ressource puissante pour router le trafic HTTP et HTTPS externe vers les services à l'intérieur d'un cluster. Mais lorsqu'un Ingress se comporte mal, les symptômes peuvent être déroutants : erreurs 404, délais d'attente, erreurs TLS ou trafic dirigé vers le mauvais backend. Le dépannage d'un Ingress exige une approche systématique : comprendre les composants impliqués, vérifier la configuration, inspecter les journaux et vérifier la connectivité étape par étape.
Ce guide fournit des exemples pratiques pour diagnostiquer et corriger les pannes courantes d'Ingress. Nous aborderons l'inventaire de l'environnement, les modifications sécurisées de configuration, les commandes de vérification, les modes de défaillance et les étapes de récupération. Chaque exemple inclut des commandes kubectl concrètes et les sorties attendues. À la fin, vous disposerez d'un flux de travail de dépannage reproductible.
Inventaire de version et d'environnement
Avant de dépanner, collectez des informations sur votre cluster, le contrôleur d'Ingress et les ressources associées. Cela établit une base de référence et aide à identifier les incohérences. Un piège courant est de supposer que le contrôleur d'Ingress est sain alors qu'il ne l'est pas, ou d'utiliser un client kubectl obsolète qui rapporte incorrectement les versions des ressources. Commencez par un inventaire propre.
Prérequis :
- Accès à un cluster Kubernetes avec kubectl configuré.
- Autorisation de lire et décrire les ressources dans les espaces de noms concernés.
- Compréhension de base des services, déploiements et Ingress Kubernetes.
Commandes à exécuter :
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.28.3
Si les versions client et serveur diffèrent significativement (par exemple, client en 1.22 et serveur en 1.28), certains champs de sortie kubectl peuvent être manquants ou obsolètes. Mettez à niveau votre client pour correspondre à la version mineure du serveur autant que possible.
kubectl get nodes -o wide
Cela montre l'état des nœuds, la version de Kubernetes et les adresses IP internes/externes. Recherchez tout nœud en état NotReady, ce qui peut affecter la planification du contrôleur d'Ingress.
kubectl get pods -n ingress-nginx
Remplacez ingress-nginx par l'espace de noms de votre contrôleur d'Ingress. Les espaces de noms courants incluent ingress-nginx, kube-system, traefik, istio-system ou contour. La sortie attendue montre des pods en cours d'exécution, par exemple :
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-6d5c7b8f9b-abcde 1/1 Running 0 5d
Si le pod du contrôleur n'est pas en cours d'exécution, décrivez-le pour en voir la raison :
kubectl describe pod <nom-du-pod> -n ingress-nginx
Vérifiez l'IngressClass :
kubectl get ingressclass
Exemple de sortie :
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 10d
Identifiez la ressource Ingress et sa configuration :
kubectl get ingress -A
kubectl describe ingress <nom-ingress> -n <namespace>
La sortie de describe montre les règles, les services backend, les paramètres TLS et les annotations. Vérifiez que l'IngressClass correspond à la classe du contrôleur (ou que l'Ingress utilise la classe par défaut si ingressClassName est omis). Une incohérence ici est une cause fréquente d'Ingress ignoré.
Liste de contrôle de la topologie :
- Le contrôleur d'Ingress est en cours d'exécution et sain.
- La ressource Ingress existe dans l'espace de noms attendu.
- Le service backend existe et sélectionne les bons pods.
- Le service a des endpoints (pods prêts).
- Le secret TLS existe si HTTPS est utilisé.
- Les politiques réseau autorisent le trafic du contrôleur d'Ingress vers les pods backend.
Chemin de configuration sécurisé
Lorsque vous apportez des modifications, procédez progressivement. D'abord, testez avec un Ingress simple avant de modifier un routage complexe. Cela reflète la pratique de commencer par un changement étroit et mesurable et d'inspecter localement avant un déploiement plus large. Évitez de modifier directement les ressources Ingress de production via kubectl edit ; exportez plutôt le manifeste actuel, modifiez-le dans un fichier et appliquez-le avec une vérification des différences.
Exemple d'Ingress minimal :
Créez un déploiement et un service de test :
kubectl create deployment web --image=nginx:1.25 --port=80 -n test
kubectl expose deployment web --port=80 --target-port=80 -n test
Créez un Ingress pour cela (enregistrez sous ingress.yaml) :
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
namespace: test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: test.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Appliquez et testez :
kubectl apply -f ingress.yaml
curl -H "Host: test.example.com" http://<ip-du-contrôleur-ingress>/
Si le contrôleur d'Ingress est exposé via un LoadBalancer, obtenez son IP :
kubectl get svc -n ingress-nginx ingress-nginx-controller
La sortie attendue montre une IP externe. Utilisez cette IP dans curl. Si vous n'avez pas d'IP externe, vous pouvez tester en utilisant le transfert de port :
kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80
Puis faites un curl http://localhost:8080/ avec l'en-tête Host.
Si vous devez modifier un Ingress existant, sauvegardez d'abord le manifeste actuel :
kubectl get ingress <nom> -n <ns> -o yaml > ingress-backup.yaml
Ensuite, modifiez, appliquez et vérifiez. Utilisez kubectl diff pour prévisualiser les changements :
kubectl diff -f updated-ingress.yaml
Cela montre ce qui changerait sans appliquer. Examinez toujours la différence avant d'appliquer pour détecter les modifications non intentionnelles.
Vérification et diagnostics
Après la configuration, vérifiez que le trafic circule correctement. Utilisez plusieurs commandes pour vérifier chaque couche. Considérez le contrôleur d'Ingress comme une boîte noire au départ : confirmez que les requêtes l'atteignent et qu'il peut atteindre les backends, puis réduisez le champ.
1. Vérifier l'état de la ressource Ingress
kubectl describe ingress web-ingress -n test
Recherchez les événements : synchronisation réussie ou erreurs. Exemple d'Ingress sain :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 2m nginx-ingress-controller Scheduled for sync
S'il y a des erreurs, elles apparaissent ici. Les erreurs courantes incluent « endpoint not found » ou « service not found ».
2. Vérifier les journaux du contrôleur d'Ingress
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller --tail=50
Ajustez l'espace de noms et le nom du déploiement. Cherchez des lignes contenant votre nom d'Ingress, l'hôte ou une erreur. Exemple d'erreur :
E0301 12:00:00.123456 1 controller.go:123] Unexpected error ingressing: service "test/web" is type "ClusterIP", expected "NodePort" or "LoadBalancer"
Avec la plupart des contrôleurs d'Ingress modernes, les services ClusterIP sont valides ; cette erreur peut indiquer un contrôleur mal configuré ou une version obsolète. Consultez la documentation du contrôleur.
Pour filtrer les journaux pour un hôte spécifique :
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller --tail=200 | grep "test.example.com"
3. Vérifier le service backend et les endpoints
kubectl get svc web -n test
kubectl get endpoints web -n test
Attendu :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP 10.96.123.45 <none> 80/TCP 10m
NAME ENDPOINTS AGE
web 10.244.0.10:80 10m
Si les endpoints sont vides, le sélecteur du service ne correspond pas aux pods ou les pods ne sont pas prêts. Vérifiez les étiquettes des pods :
kubectl get pods -n test --show-labels
Comparez avec le sélecteur du service :
kubectl describe svc web -n test
4. Tester depuis l'intérieur du cluster
Exécutez un pod temporaire avec curl :
kubectl run curl-test --image=curlimages/curl -i --rm --restart=Never -- curl -v -H "Host: test.example.com" http://ingress-nginx-controller.ingress-nginx.svc.cluster.local/
Cela teste le routage interne vers le service ClusterIP du contrôleur. Vérifiez le code de statut de la réponse et les en-têtes. Si cela échoue, le problème est à l'intérieur du cluster (contrôleur, service ou backend). Si cela réussit mais que l'accès externe échoue, concentrez-vous sur le réseau externe (LoadBalancer, DNS, pare-feu).
5. Tester TLS (le cas échéant)
kubectl get secret tls-secret -n test -o yaml
Vérifiez que le secret contient tls.crt et tls.key. Ensuite, testez avec curl en utilisant --resolve pour mapper l'hôte à l'IP de l'Ingress :
curl -v --resolve test.example.com:443:<ip-ingress> https://test.example.com/
Vérifiez les erreurs de certificat. Utilisez openssl pour examiner le certificat :
kubectl get secret tls-secret -n test -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates -subject
Résultats attendus pour une configuration fonctionnelle
- La description de l'Ingress montre un événement de synchronisation.
- Les journaux du contrôleur d'Ingress ne montrent aucune erreur pour l'hôte.
- Les endpoints contiennent des IP de pods.
- Curl renvoie HTTP 200 et le contenu attendu.
- La poignée de main TLS réussit (aucun avertissement de certificat).
Si l'un de ces éléments échoue, passez à la section des modes de défaillance ci-dessous.
Modes de défaillance courants et récupération
Cette section couvre les pannes d'Ingress les plus fréquentes, avec symptômes, diagnostic et étapes de récupération. Chaque mode de défaillance inclut des commandes concrètes et des sorties attendues.
Mode de défaillance 1 : 404 Not Found
Symptômes : Curl renvoie 404 même si le chemin semble correct.
Causes possibles :
- Le chemin de l'Ingress ne correspond pas au chemin de la requête (par exemple, le chemin est
/apimais la requête est/api/en raison d'une incompatibilité depathType). - L'annotation
rewrite-targetest mal configurée, ce qui fait que le backend reçoit un chemin inattendu. - Le service backend lui-même renvoie 404 pour le chemin.
Diagnostic :
Vérifiez les règles de l'Ingress :
kubectl get ingress web-ingress -n test -o yaml
Regardez path et pathType. Le pathType par défaut d'Ingress-nginx est Prefix. Avec Prefix, /api correspond à /api, /api/, /api/v1, etc. Avec Exact, seul /api correspond. Si vous avez besoin d'une correspondance exacte mais que vous avez utilisé Prefix, modifiez-le.
Vérifiez directement le service backend depuis un pod :
kubectl exec -it <un-pod-dans-le-même-namespace> -n test -- curl http://web.test.svc.cluster.local/<chemin>
Si le curl direct fonctionne mais que l'Ingress renvoie 404, le routage de l'Ingress est incorrect.
Récupération :
- Ajustez le chemin de l'Ingress ou le
pathTypepour correspondre à l'URL demandée. - Si vous utilisez
rewrite-target, testez d'abord sans. Une réécriture mal configurée peut supprimer ou ajouter des segments de chemin de manière inattendue. - Appliquez les modifications et retestez :
kubectl apply -f updated-ingress.yaml
curl -H "Host: test.example.com" http://<ip-ingress>/<chemin>
Mode de défaillance 2 : 503 Service Unavailable
Symptômes : L'Ingress renvoie 503.
Causes possibles :
- Le service backend n'a pas d'endpoints (pods non prêts).
- Incompatibilité de nom de service ou de port dans l'Ingress.
- Politique réseau bloquant le trafic du contrôleur d'Ingress vers les pods.
- La sonde de préparation échoue, donc les pods ne sont pas marqués prêts.
Diagnostic :
Vérifiez les endpoints :
kubectl get endpoints <service> -n <namespace>
S'ils sont vides, vérifiez les pods et leurs étiquettes :
kubectl get pods -n test --show-labels
kubectl describe svc web -n test
Assurez-vous que le sélecteur du service correspond exactement aux étiquettes des pods. Notez qu'un sélecteur de service avec app: web ne correspondra pas aux pods avec app: web-backend.
Vérifiez la définition du backend de l'Ingress :
kubectl describe ingress web-ingress -n test
Vérifiez le nom du service et le port. Dans l'exemple, le backend doit être serviceName: web et servicePort: 80.
Vérifiez les journaux du contrôleur d'Ingress pour une erreur :
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller | grep -i "test/web"
Exemple :
W0301 12:00:00.123456 1 controller.go:456] Service "test/web" does not have any active Endpoint.
Récupération :
- Corrigez le sélecteur du service pour qu'il corresponde aux pods.
- Assurez-vous que les pods sont prêts : vérifiez
kubectl get pods -n testet regardez la colonne READY. Si elle est à 0/1, décrivez le pod et vérifiez les journaux de la sonde de préparation. - Corrigez le nom/port du service dans l'Ingress.
- Si une politique réseau est suspectée, autorisez temporairement tout le trafic dans l'espace de noms pour tester, puis resserrez.
Mode de défaillance 3 : Erreurs de certificat TLS
Symptômes : Le navigateur affiche un avertissement de certificat ou curl signale un problème de certificat SSL.
Causes possibles :
- Secret TLS manquant ou mal formé.
- Incompatibilité de nom d'hôte du certificat.
- Certificat expiré.
- Secret n'est pas dans le même espace de noms que l'Ingress.
Diagnostic :
Vérifiez le secret :
kubectl get secret tls-secret -n test
S'il n'est pas trouvé :
Error from server (NotFound): secrets "tls-secret" not found
Vérifiez les détails du certificat :
kubectl get secret tls-secret -n test -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates -subject
La sortie attendue montre les dates de validité et le sujet CN/SAN. Vérifiez que le SAN inclut le nom d'hôte utilisé dans l'Ingress.
Récupération :
- Créez un secret valide :
kubectl create secret tls tls-secret --cert=chemin/vers/tls.crt --key=chemin/vers/tls.key -n test
- Assurez-vous que le certificat inclut le nom d'hôte dans le SAN (pas seulement le CN).
- Renouvelez s'il est expiré.
- Assurez-vous que le secret est dans le même espace de noms que la ressource Ingress.
Mode de défaillance 4 : Connexion refusée ou délai d'attente
Symptômes : Curl ne peut pas se connecter ; connexion refusée ou délai d'attente.
Causes possibles :
- Le service du contrôleur d'Ingress n'est pas accessible de l'extérieur (par exemple, l'IP du LoadBalancer n'est pas attribuée, le pare-feu bloque).
- Le pod du contrôleur d'Ingress n'est pas en cours d'exécution.
- Politique réseau bloquant le trafic vers le contrôleur.
- Échec de résolution DNS pour l'hôte.
Diagnostic :
Vérifiez le service du contrôleur d'Ingress :
kubectl get svc -n ingress-nginx
Recherchez EXTERNAL-IP. Si <pending>, le LoadBalancer peut être encore en cours de provisionnement, ou votre cluster peut ne pas prendre en charge LoadBalancer (par exemple, bare metal). Vérifiez les événements du service :
kubectl describe svc ingress-nginx-controller -n ingress-nginx
Vérifiez les pods du contrôleur :
kubectl get pods -n ingress-nginx
Si les pods ne sont pas en cours d'exécution, décrivez-les :
kubectl describe pod <nom-du-pod> -n ingress-nginx
Recherchez CrashLoopBackOff, ImagePullBackOff ou des problèmes de ressources.
Récupération :
- Attendez l'IP du LoadBalancer ou utilisez NodePort / port-forward pour les tests.
- Corrigez les problèmes de pod (par exemple, limites de ressources, erreurs de configuration).
- Vérifiez le pare-feu du fournisseur cloud ou les groupes de sécurité. Autorisez le trafic entrant sur les ports 80/443 depuis votre IP.
- Vérifiez que l'enregistrement DNS pointe vers la bonne IP ou utilisez
--resolvepour contourner le DNS.
Mode de défaillance 5 : Routage vers le mauvais backend
Symptômes : La requête est servie par un service inattendu.
Causes possibles :
- Plusieurs ressources Ingress avec le même hôte mais des chemins différents, et l'ordre de correspondance des chemins conduit au mauvais backend.
- Configuration du backend par défaut.
- Mauvaise configuration des annotations (par exemple, poids canary).
Diagnostic :
Listez toutes les ressources Ingress avec l'hôte :
kubectl get ingress -A | grep <hôte>
Inspectez les règles de chaque Ingress. Les contrôleurs d'Ingress fusionnent les règles de toutes les ressources Ingress du cluster, des conflits peuvent donc survenir. Ingress-nginx utilise un système de priorité : la correspondance de chemin la plus longue gagne, et en cas d'égalité, l'horodatage de création décide. Cela peut conduire à un routage inattendu.
Vérifiez le backend par défaut :
kubectl get ingress -n test web-ingress -o yaml
Si spec.defaultBackend est défini, toute requête ne correspondant pas à une règle y va.
Récupération :
- Consolidez les règles dans un seul Ingress pour l'hôte afin d'éviter l'ambiguïté.
- Ou ajustez la spécificité des chemins pour que le chemin le plus long prévu gagne.
- Utilisez des hôtes différents si possible.
- Définissez explicitement
ingressClassNamepour garantir que le bon contrôleur traite l'Ingress.
Vérifications de rollback et de récupération
Gardez toujours des sauvegardes des manifestes d'Ingress. Si une modification cause des problèmes, faites un rollback :
kubectl apply -f ingress-backup.yaml
Puis vérifiez avec curl et describe. Envisagez également d'utiliser kubectl rollout undo pour les déploiements si les changements de pods ont causé le problème :
kubectl rollout undo deployment/web -n test
Pièges courants et comment les éviter
Au-delà des modes de défaillance spécifiques, plusieurs erreurs récurrentes peuvent rendre le dépannage d'Ingress plus difficile. Voici les pièges les plus courants et leurs solutions.
Piège 1 : Ignorer l'IngressClass
De nombreux utilisateurs omettent ingressClassName ou le définissent incorrectement, en supposant que le contrôleur par défaut gérera l'Ingress. Si plusieurs contrôleurs existent ou si la classe par défaut n'est pas définie, l'Ingress peut être entièrement ignoré.
Comment éviter : Définissez toujours ingressClassName explicitement dans votre manifeste Ingress. Vérifiez que la classe existe avec kubectl get ingressclass.
Piège 2 : Mal comprendre pathType
La différence entre les types de chemin Prefix et Exact cause de nombreuses erreurs 404. Par exemple, avec pathType: Exact et path: /foo, une requête vers /foo/ ne correspondra pas et renverra 404. Avec Prefix, /foo correspond à /foo, /foo/ et /foo/bar.
Comment éviter : Choisissez Prefix pour la plupart des applications sauf si vous avez besoin d'une correspondance de chemin exacte. Testez avec et sans barres obliques finales.
Piège 3 : Mauvaise utilisation de l'annotation rewrite-target
L'annotation rewrite-target est puissante mais souvent mal configurée. Définir rewrite-target: / pour un Ingress avec le chemin /api supprimera /api et enverra le chemin restant au backend. Si ce n'est pas intentionnel, le backend reçoit des chemins inattendus et peut renvoyer 404 ou 500.
Comment éviter : Testez le comportement de réécriture en examinant les journaux d'accès du backend ou en utilisant un simple serveur echo. N'utilisez la réécriture que lorsque vous comprenez la sémantique du chemin cible.
Piège 4 : Ne pas vérifier les endpoints
Lorsqu'un service n'a pas d'endpoints, le contrôleur d'Ingress renvoie 503. Les utilisateurs passent souvent du temps à vérifier les règles d'Ingress alors que le vrai problème est que les pods ne sont pas prêts ou que les étiquettes ne correspondent pas.
Comment éviter : Faites de la vérification des endpoints une étape standard de votre liste de contrôle de dépannage. Utilisez kubectl get endpoints immédiatement après avoir vérifié l'Ingress.
Piège 5 : Négliger les politiques réseau
Les politiques réseau peuvent bloquer silencieusement le trafic entre le contrôleur d'Ingress et les pods backend. Le symptôme est généralement un délai d'attente ou une 503, mais les journaux peuvent montrer une connexion refusée.
Comment éviter : Lors du diagnostic des problèmes de connectivité, créez temporairement une politique réseau permissive dans l'espace de noms pour isoler le problème. Une fois confirmé, ajustez la politique pour autoriser le trafic nécessaire.
Liste de contrôle des opérations
Utilisez cette liste de contrôle pour les opérations de routine et pendant les incidents. Examinez-la mensuellement pour vous assurer que tous les composants sont sains. Attribuez un responsable à chaque vérification pour maintenir la responsabilité.
| Étape | Commande / Vérification | Résultat attendu | Responsable | Fréquence de révision |
|---|---|---|---|---|
| 1. Vérifier la santé du cluster | kubectl get nodes | Tous les nœuds Ready | Priya Shah, responsable plateforme | Mensuelle |
| 2. Vérifier le contrôleur d'Ingress | kubectl get pods -n ingress-nginx | Tous les pods en cours d'exécution | DevOps de garde | Hebdomadaire |
| 3. Vérifier la ressource Ingress | kubectl get ingress -A | Ingress désiré présent, aucune erreur dans les événements | Équipe applicative | Mensuelle |
| 4. Vérifier les endpoints | kubectl get endpoints <svc> -n <ns> | Liste d'endpoints non vide | Équipe applicative | Mensuelle |
| 5. Tester la route HTTP | curl -H "Host: <hôte>" http://<ip-ingress>/ | HTTP 200 | Ingénieur QA | À chaque release |
| 6. Tester la route HTTPS | curl --resolve <hôte>:443:<ip> https://<hôte>/ | Poignée de main TLS OK, HTTP 200 | Équipe sécurité | Trimestrielle |
| 7. Vérifier les journaux | kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail=100 | Aucune erreur pour notre hôte | DevOps de garde | Hebdomadaire |
| 8. Sauvegarder avant les changements | kubectl get ingress <nom> -n <ns> -o yaml > backup.yaml | Fichier de sauvegarde créé | Responsable des changements | À chaque changement |
| 9. Valider l'expiration du certificat | kubectl get secret tls-secret -n test -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -enddate | Expiration à plus de 30 jours | Équipe sécurité | Mensuelle |
Conclusion
Le dépannage d'un Ingress Kubernetes exige une approche méthodique : collecter des informations sur l'environnement, apporter de petites modifications sécurisées, vérifier chaque couche et connaître les modes de défaillance courants. En utilisant les commandes et les exemples de ce guide, vous pouvez rapidement identifier et corriger des problèmes tels que les erreurs 404, 503, TLS et les problèmes de connectivité.
Prochaines étapes :
- Pratiquez les commandes de diagnostic sur un Ingress de test.
- Créez un manuel basé sur la liste de contrôle des opérations.
- Automatisez la sauvegarde des manifestes d'Ingress à l'aide d'un CronJob ou de GitOps.
- Mettez en place une surveillance des journaux et des métriques du contrôleur d'Ingress (par exemple, des alertes Prometheus pour les taux de 5xx).
Avec ces outils, vous pouvez maintenir la fiabilité de votre routage Ingress et réduire les temps d'arrêt.