Introduction
Les laboratoires précédents ont introduit l'utilisation des journaux (logs), des événements, de kubectl exec, du transfert de port (port-forwarding) et des sondes (probes). Une application en état de "CrashLoop" combine plusieurs de ces compétences. Le Pod démarre, le conteneur s'arrête, Kubernetes le redémarre, et vous devez recueillir les preuves avant de modifier quoi que ce soit.
Dans ce laboratoire, vous déploierez une application qui s'arrête car une variable d'environnement requise est manquante. Vous observerez le comportement de redémarrage, lirez les journaux actuels et précédents, inspecterez les événements, identifierez la configuration manquante dans le Deployment, puis corrigerez le Deployment et vérifierez que l'application est devenue accessible.
Préparer un espace de noms pour le débogage de CrashLoop
Dans cette étape, vous allez préparer un espace de noms (namespace) propre pour l'exercice de débogage de CrashLoop.
Commencez dans /home/labex/project. Vous créerez et mettrez à jour le manifeste de l'application dans ce répertoire.
mkdir -p /home/labex/project
cd /home/labex/project
Vérifiez que le serveur API Kubernetes est accessible. Si la machine virtuelle vient de démarrer et que le nœud n'est pas encore prêt, attendez quelques secondes et relancez la commande.
kubectl get nodes --request-timeout=5s
La sortie attendue inclut :
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Attendez que le Pod réseau du cluster soit prêt. L'application corrigée sera testée ultérieurement via un Service.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Sortie attendue :
pod/calico-node-... condition met
Créez un espace de noms nommé ckad-prep-crashloop et définissez-le comme espace de noms actuel :
kubectl create namespace ckad-prep-crashloop
kubectl config set-context --current --namespace=ckad-prep-crashloop
Confirmez l'espace de noms actuel :
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Sortie attendue :
ckad-prep-crashloop
Déployer et observer un CrashLoop
Dans cette étape, vous allez déployer une application qui s'arrête de manière répétée.
Le script du conteneur nécessite la variable d'environnement APP_MESSAGE. Si la variable est manquante, le script affiche une erreur claire et s'arrête avec le code de sortie 1. Kubernetes redémarrera le conteneur, ce qui crée le comportement de CrashLoop que vous devez déboguer.
Créez crash-demo.yaml :
cat > crash-demo.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: crash-demo
spec:
replicas: 1
selector:
matchLabels:
app: crash-demo
template:
metadata:
labels:
app: crash-demo
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
if [ -z "${APP_MESSAGE:-}" ]; then
echo "startup failed: APP_MESSAGE is required"
exit 1
fi
mkdir -p /www
echo "$APP_MESSAGE" > /www/index.html
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: crash-demo
spec:
selector:
app: crash-demo
ports:
- port: 80
targetPort: 8080
EOF
Appliquez le manifeste :
kubectl apply -f crash-demo.yaml
Sortie attendue :
deployment.apps/crash-demo created
service/crash-demo created
Laissez un court instant à Kubernetes pour redémarrer le conteneur défaillant, puis inspectez le Pod :
sleep 12
kubectl get pods -l app=crash-demo
La sortie attendue inclut un Pod qui n'est pas sain. Le statut exact peut être Error ou CrashLoopBackOff selon le moment de l'exécution :
NAME READY STATUS RESTARTS AGE
crash-demo-... 0/1 CrashLoopBackOff ... ...
Stockez le nom du Pod et inspectez l'état de son conteneur. Le JSONPath vous permet de lire les champs spécifiques importants sans parcourir l'objet complet. La première valeur est le nombre de redémarrages. La seconde valeur est la raison de l'attente, qui peut être vide si vous interceptez le Pod alors que le dernier conteneur ayant échoué est dans un état Error au lieu d'attendre en CrashLoopBackOff.
CRASH_POD="$(kubectl get pods -l app=crash-demo -o jsonpath='{.items[0].metadata.name}')"
echo "$CRASH_POD"
kubectl get pod "$CRASH_POD" -o jsonpath='{.status.containerStatuses[0].restartCount}{" "}{.status.containerStatuses[0].state.waiting.reason}{"\n"}'
La sortie attendue inclut un nombre de redémarrages supérieur à 0. Selon le moment, la raison peut être vide ou afficher une valeur telle que CrashLoopBackOff :
2
ou :
... CrashLoopBackOff
Lire les journaux et les événements pour trouver la cause
Dans cette étape, vous utiliserez les journaux, les journaux précédents et les événements pour identifier pourquoi le conteneur s'arrête.
Lorsqu'un conteneur redémarre rapidement, kubectl logs peut afficher la tentative actuelle du conteneur, tandis que kubectl logs --previous lit la tentative du conteneur précédent ayant échoué. Pour le débogage de CrashLoop, --previous est souvent la commande qui révèle l'erreur de démarrage utile.
Lisez les journaux actuels :
kubectl logs "$CRASH_POD" --container web
La sortie attendue inclut :
startup failed: APP_MESSAGE is required
Lisez les journaux du conteneur précédent. Si Kubernetes a conservé le journal du dernier conteneur terminé, cela affiche la même erreur de démarrage issue d'une tentative antérieure. Dans certains cas de CrashLoop rapide, le runtime peut signaler qu'il ne peut pas récupérer le journal précédent. Cela enseigne tout de même un point de débogage important : utilisez --previous lorsqu'il est disponible, mais comparez-le toujours avec les journaux actuels et les événements du Pod.
kubectl logs "$CRASH_POD" --container web --previous
La sortie attendue inclut souvent :
startup failed: APP_MESSAGE is required
Il est également acceptable de voir un message similaire à :
unable to retrieve container logs for ...
Inspectez les événements du Pod. Les événements montrent Kubernetes en train de redémarrer le conteneur défaillant.
kubectl describe pod "$CRASH_POD" | sed -n '/Events:/,$p'
La sortie attendue inclut des événements tels que BackOff ou Started :
Warning BackOff ... Back-off restarting failed container
Inspectez maintenant la configuration de l'environnement du Deployment. La liste env est manquante, ce qui explique le message dans les journaux.
kubectl get deployment crash-demo -o jsonpath='{.spec.template.spec.containers[0].env}'; echo
La sortie attendue est vide :
Corriger le Deployment et vérifier le rétablissement
Dans cette étape, vous allez corriger la variable d'environnement manquante et vérifier que l'application se rétablit.
Le message d'erreur a nommé la configuration manquante : APP_MESSAGE. Au lieu de modifier la commande du conteneur, définissez la variable d'environnement requise sur le Deployment. Kubernetes créera un nouveau ReplicaSet car le modèle de Pod (Pod template) a changé.
Définissez la variable d'environnement :
kubectl set env deployment/crash-demo APP_MESSAGE=crashloop-fixed
Sortie attendue :
deployment.apps/crash-demo env updated
Attendez le déploiement (rollout) :
kubectl rollout status deployment/crash-demo --timeout=120s
Sortie attendue :
deployment "crash-demo" successfully rolled out
Inspectez le nouveau Pod. Il devrait être en état Running et Ready :
kubectl get pods -l app=crash-demo
La sortie attendue inclut :
NAME READY STATUS RESTARTS AGE
crash-demo-... 1/1 Running 0 ...
Créez un Pod client et testez le Service :
kubectl run crash-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/crash-client --timeout=120s
kubectl exec crash-client -- wget -qO- http://crash-demo
Sortie attendue :
crashloop-fixed
Enfin, confirmez que le Deployment inclut désormais la variable d'environnement :
kubectl get deployment crash-demo -o jsonpath='{.spec.template.spec.containers[0].env[0].name}{"="}{.spec.template.spec.containers[0].env[0].value}{"\n"}'
Sortie attendue :
APP_MESSAGE=crashloop-fixed
Résumé
Vous avez débogué une application en état de CrashLoop en utilisant les mêmes sources de preuves introduites précédemment à l'étape 5. Vous avez observé le statut du Pod défaillant, lu les journaux des conteneurs actuels et précédents, inspecté les événements, identifié une variable d'environnement manquante dans le Deployment, corrigé le modèle de Pod avec kubectl set env, et vérifié le rétablissement de l'application via son Service.


