Introduction
Vous savez désormais décrire l'état souhaité à l'aide de manifestes et créer des Pods et des Deployments. La prochaine compétence essentielle consiste à comprendre quoi faire lorsque Kubernetes ne parvient pas à réaliser cet état souhaité.
Dans ce laboratoire, vous travaillerez avec deux petits Deployments : l'un sain et l'autre contenant volontairement une erreur de balise d'image. Vous suivrez une démarche reproductible, allant des symptômes généraux aux éléments de preuve précis. Vous corrigerez le manifeste plutôt que de modifier uniquement l'objet en cours d'exécution, puis vous inspecterez l'application rétablie à l'aide des journaux et de commandes exécutées dans son conteneur.
L'objectif n'est pas de mémoriser toutes les défaillances possibles, mais d'acquérir une méthode de diagnostic sereine : observer, circonscrire, examiner les preuves, corriger l'état souhaité et vérifier le rétablissement.
Créer une défaillance contrôlée
Démarrage de l’environnement : Ce lab démarre pour vous un cluster Kubernetes complet. La configuration du plan de contrôle, du nœud et des composants réseau prend généralement 2 à 3 minutes. Veuillez patienter jusqu’à la fin du chargement de l’environnement avant de commencer.
Tout diagnostic commence par un symptôme. Dans cette étape, vous allez déployer une charge de travail saine et une autre volontairement défaillante afin de pouvoir les comparer dans les mêmes conditions de cluster.
Accédez à l'espace de travail préparé et affichez ses fichiers. cd modifie le répertoire courant ; ls affiche les noms qu'il contient. Les commandes sont placées sur des lignes distinctes et s'exécutent dans l'ordre :
cd /home/labex/project/debug-lab
ls
Vous devriez voir healthy-web.yaml et broken-web.yaml. Tous deux définissent des Deployments à une réplique, mais l'un contient une erreur de configuration discrète que vous diagnostiquerez plus tard.
Appliquez les deux manifestes. kubectl apply envoie l'état souhaité au serveur d'API, et chaque option -f désigne un fichier d'entrée. Une même commande peut accepter plusieurs options -f :
kubectl apply -f healthy-web.yaml -f broken-web.yaml
Attendez d'abord que le Deployment connu comme sain soit déployé :
kubectl rollout status deployment/healthy-web --timeout=60s
Le message deployment "healthy-web" successfully rolled out établit une référence utile : le cluster sait planifier des Pods et exécuter l'image NGINX mise en cache.
Laissez maintenant à l'autre Deployment un court délai pour se déployer :
kubectl rollout status deployment/broken-web --timeout=15s || true
Le délai d'attente est prévu. || true indique au shell de poursuivre, car cet échec constitue un élément de l'exercice et non une raison d'arrêter le laboratoire.
Comparez le résumé des Deployments :
kubectl get deployments
healthy-web devrait afficher 1/1 réplique prête, tandis que broken-web devrait afficher 0/1. Vous avez ainsi établi que le problème est propre à cette charge de travail et ne provient pas d'une défaillance générale du cluster.
Circonscrire le problème avec les résumés des ressources
Dans cette étape, vous commencerez par une vue d'ensemble avant d'examiner les détails. Les contrôleurs Kubernetes créent une chaîne d'objets ; un problème de Deployment devient donc souvent visible d'abord dans son ReplicaSet et son Pod.
Répertoriez ensemble les types d'objets associés. Les virgules permettent à une seule requête kubectl get de demander plusieurs types de ressources, tandis que -o wide ajoute des colonnes utiles, comme les informations sur le nœud et l'adresse IP :
kubectl get deployments,replicasets,pods -o wide
Lisez la sortie de haut en bas :
- Un Deployment indique le nombre de répliques souhaitées et disponibles.
- Un ReplicaSet transmet ce nombre de répliques souhaitées aux Pods.
- Un Pod indique si le conteneur est prêt ainsi qu'une brève raison pour son état.
Limitez l'affichage à la seule application défaillante en utilisant son étiquette :
kubectl get pods -l app=broken-web -o wide
Le nom du Pod contient un suffixe généré automatiquement ; les étiquettes sont donc plus fiables que la copie d'un nom susceptible de changer dans des scripts.
Demandez uniquement les champs importants à ce stade. -o custom-columns='...' construit un tableau à partir de champs d'objet explicitement indiqués. Chaque entrée comporte un en-tête tel que NAME, suivi du chemin JSON qui fournit sa valeur. La barre oblique inverse finale réunit les deux lignes affichées du shell en une seule commande :
kubectl get pods -l app=broken-web \
-o custom-columns='NAME:.metadata.name,READY:.status.containerStatuses[0].ready,WAITING_REASON:.status.containerStatuses[0].state.waiting.reason,NODE:.spec.nodeName'
La raison de l'attente peut être initialement ErrImagePull, puis devenir ImagePullBackOff. Dans les deux cas, cela signifie que le conteneur n'a jamais démarré parce que Kubernetes n'a pas pu obtenir son image. C'est une information plus précise que de dire simplement « le Pod est arrêté ».
Examiner le Pod avec describe
Dans cette étape, vous utiliserez describe pour comprendre pourquoi le conteneur est en attente. Le résumé vous a indiqué ce qui ne va pas ; vous allez maintenant recueillir l'explication.
Enregistrez le nom généré du Pod dans une variable shell. $(...) correspond à une substitution de commande : le shell exécute la commande kubectl interne et affecte sa sortie à BROKEN_POD. JSONPath sélectionne le nom du premier Pod correspondant, puis echo affiche la valeur enregistrée :
BROKEN_POD=$(kubectl get pods -l app=broken-web -o jsonpath='{.items[0].metadata.name}')
echo "$BROKEN_POD"
Décrivez ce Pod :
kubectl describe pod "$BROKEN_POD"
describe rassemble des champs utiles ainsi que les événements récents. Concentrez-vous sur trois zones :
- Containers → Image affiche l'image demandée exacte.
- State → Waiting → Reason décrit l'état actuel du conteneur.
- Events consigne les tentatives du kubelet et les messages d'erreur.
Dans ce scénario, le message d'événement indique que la balise 1.27-alpine-missing est introuvable. Le cluster fait exactement ce que le manifeste lui demande ; c'est l'état souhaité lui-même qui est incorrect.
Confirmez directement l'image avec JSONPath :
kubectl get pod "$BROKEN_POD" -o jsonpath='Image: {.spec.containers[0].image}{"\n"}'
JSONPath est particulièrement utile lorsqu'un fichier YAML volumineux ou la sortie de describe contient davantage d'informations que nécessaire. Ici, il isole le champ qui devra être corrigé.
Lire les événements comme une chronologie
Dans cette étape, vous lirez les événements comme une chronologie de l'activité de Kubernetes. Les événements sont des enregistrements de diagnostic à durée de vie limitée qui permettent d'expliquer la planification, le téléchargement des images, le démarrage des conteneurs, les redémarrages et de nombreuses autres transitions d'état.
Répertoriez les événements récents du namespace dans l'ordre chronologique. --sort-by trie les objets selon le champ de métadonnées indiqué ; les guillemets permettent de conserver le chemin au format JSON comme un seul argument :
kubectl get events --sort-by='.metadata.creationTimestamp'
Les dernières lignes sont généralement les plus récentes. Recherchez les entrées dont la colonne OBJECT fait référence au Pod défaillant et dont la colonne REASON contient des valeurs telles que Pulling, Failed ou BackOff.
Vous pouvez réduire le bruit en filtrant les événements selon le nom généré du Pod. --field-selector filtre côté serveur les champs des objets, et non les étiquettes. La virgule signifie que les deux conditions doivent être satisfaites, tandis que les barres obliques inverses permettent de poursuivre une même commande sur plusieurs lignes lisibles :
BROKEN_POD=$(kubectl get pods -l app=broken-web -o jsonpath='{.items[0].metadata.name}')
kubectl get events \
--field-selector involvedObject.kind=Pod,involvedObject.name="$BROKEN_POD" \
--sort-by='.metadata.creationTimestamp'
Considérez get, describe et events comme trois vues complémentaires :
getlocalise rapidement l'objet défaillant.describerassemble la configuration, l'état et les événements associés à un objet donné.eventsfournit une vue chronologique qui peut révéler des tentatives répétées.
Les entrées BackOff répétées ne signifient pas que Kubernetes a abandonné le Pod. Elles indiquent simplement que Kubernetes espace les nouvelles tentatives de téléchargement après les échecs.
Corriger l'état souhaité et vérifier le rétablissement
Dans cette étape, vous allez corriger l'état souhaité et vérifier le rétablissement. Vous disposez de suffisamment d'éléments : le manifeste demande une balise d'image inexistante. Corrigez d'abord le manifeste enregistré, puis appliquez-le afin que le fichier et le cluster en cours d'exécution restent cohérents.
Affichez les lignes d'image des deux manifestes pour les comparer. grep recherche du texte, -n préfixe chaque correspondance par son numéro de ligne, et une seule commande recherche dans les deux fichiers :
grep -n 'image:' healthy-web.yaml broken-web.yaml
Le manifeste sain utilise nginx:1.27-alpine ; le manifeste défaillant ajoute le suffixe inexistant -missing.
Remplacez uniquement ce suffixe. sed effectue une substitution textuelle écrite sous la forme s/old/new/ ; -i modifie directement le fichier indiqué au lieu d'afficher uniquement le texte modifié :
sed -i 's/nginx:1.27-alpine-missing/nginx:1.27-alpine/' broken-web.yaml
Validez localement le fichier corrigé :
kubectl apply --dry-run=client -f broken-web.yaml
Prévisualisez la différence entre le fichier et l'objet en cours d'exécution :
kubectl diff -f broken-web.yaml || true
kubectl diff renvoie le code 1 lorsqu'il détecte une différence ; || true permet donc de poursuivre la séquence pédagogique. Dans la différence affichée, une ligne commençant par - contient l'ancienne image et une ligne commençant par + contient l'image corrigée.
Appliquez la correction et attendez le rétablissement :
kubectl apply -f broken-web.yaml
kubectl rollout status deployment/broken-web --timeout=60s
Vérifiez que les deux Deployments sont désormais sains :
kubectl get deployments
Tous deux devraient afficher 1/1 réplique prête. Kubernetes a créé un nouveau ReplicaSet et un nouveau Pod à partir du modèle de Pod corrigé ; il n'a pas été nécessaire de réparer manuellement le Pod défaillant.
Lire les journaux de l'application
Dans cette étape, vous utiliserez les journaux de l'application comme nouvelle source d'éléments maintenant que le conteneur démarre. kubectl logs récupère les flux de sortie standard et d'erreur standard du conteneur.
Sélectionnez le nouveau Pod sain géré par broken-web. Cette commande reprend la substitution de commande et JSONPath utilisés précédemment. --field-selector=status.phase=Running ajoute une condition côté serveur afin que le Pod sélectionné soit en cours d'exécution :
WEB_POD=$(kubectl get pods -l app=broken-web \
--field-selector=status.phase=Running \
-o jsonpath='{.items[0].metadata.name}')
echo "$WEB_POD"
NGINX n'a peut-être encore aucune entrée dans son journal d'accès, car personne n'a demandé de page. Générez-en une depuis l'intérieur du Pod. Dans kubectl exec POD -- COMMAND, -- sépare les options de kubectl de la commande exécutée dans le conteneur. wget -qO- récupère la page silencieusement et l'écrit sur la sortie standard ; le tube | transmet cette sortie à head, qui n'en affiche que le début :
kubectl exec "$WEB_POD" -- wget -qO- http://127.0.0.1 | head
Le code HTML commence par <!DOCTYPE html>, ce qui prouve que NGINX a répondu localement sur le port 80.
Lisez maintenant les journaux récents. --tail=10 limite la sortie aux dix lignes les plus récentes afin que les messages de démarrage ne masquent pas la requête intéressante :
kubectl logs "$WEB_POD" --tail=10
Recherchez une requête HTTP contenant GET / HTTP/1.1 ainsi qu'un code de réponse 200. Les journaux sont particulièrement utiles lorsqu'un conteneur fonctionne, mais que l'application se comporte de manière incorrecte. Ils sont généralement inutiles pour une erreur de téléchargement d'image, puisque le conteneur n'a jamais démarré.
Inspecter l'application depuis l'intérieur du conteneur
Dans cette étape, vous inspecterez l'application rétablie depuis l'intérieur de son conteneur. kubectl exec exécute une commande dans un conteneur déjà en fonctionnement et permet de vérifier son système de fichiers, ses processus, son environnement, sa configuration DNS ou son comportement réseau local.
Réutilisez le nom du Pod en cours d'exécution :
WEB_POD=$(kubectl get pods -l app=broken-web \
--field-selector=status.phase=Running \
-o jsonpath='{.items[0].metadata.name}')
Demandez au conteneur son nom d'hôte :
kubectl exec "$WEB_POD" -- hostname
La sortie correspond au nom du Pod, car Kubernetes définit par défaut le nom d'hôte du Pod.
Vérifiez la syntaxe de la configuration NGINX dans le conteneur :
kubectl exec "$WEB_POD" -- nginx -t
Les messages syntax is ok et test is successful indiquent que la configuration de l'application est valide en interne.
Enfin, effectuez une vérification de santé compacte depuis l'intérieur. >/dev/null ignore le code HTML téléchargé, tandis que && n'exécute echo que si wget réussit. Le message de réussite n'apparaît donc qu'après réception d'une réponse HTTP :
kubectl exec "$WEB_POD" -- wget -qO- http://127.0.0.1 >/dev/null && echo "NGINX responded inside the Pod"
Utilisez exec avec discernement. Cette commande nécessite un conteneur en cours d'exécution ; elle n'aurait donc pas permis de diagnostiquer l'échec de téléchargement d'image précédent. Pour cet incident, votre progression fondée sur les preuves a été la suivante :
get -> describe -> events -> repair manifest -> rollout status -> logs -> exec
Selon la nature de la défaillance, le diagnostic peut s'arrêter à un niveau différent. Commencer par des résumés peu coûteux, puis approfondir progressivement, permet toutefois de rester concentré.
Résumé
Vous avez mis en pratique une démarche complète de débogage pour débutants sur Kubernetes v1.35. Vous avez comparé des charges de travail saines et défaillantes, circonscrit le problème à l'aide d'étiquettes et de champs concis, utilisé describe et les événements pour identifier une balise d'image invalide, corrigé la source déclarative de référence, puis vérifié le rétablissement avec l'état du déploiement, les journaux et des commandes exécutées dans le conteneur.
La leçon essentielle est de choisir des éléments de preuve adaptés à l'étape actuelle du cycle de vie de la charge de travail. Lorsqu'un conteneur n'a pas démarré, examinez son état et les événements. Une fois qu'il fonctionne, les journaux et exec peuvent révéler le comportement de l'application. Le prochain défi vous demandera d'appliquer cette méthode de manière autonome.


