Exercice 05 : Resource requests, limits et debugging
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Configurer des
requestsetlimitsCPU/mémoire dans un Deployment - ✅ Comprendre la différence entre
requests(réservation) etlimits(plafond) - ✅ Analyser un pod en état
Pending,CrashLoopBackOffouOOMKilled - ✅ Utiliser les commandes de debugging :
describe,logs,events,exec
Durée estimée : 25 minutes
Difficulté : ⭐⭐☆☆☆ (Intermédiaire)
Prérequis : Exercice 01 complété, namespace intermediaire existant
📖 Contexte
Sans limits, un seul pod peut consommer toute la mémoire du nœud et faire crasher les autres. Sans requests, le scheduler ne sait pas où placer les pods. Définir les resources correctement est une bonne pratique indispensable en production.
Savoir déboguer un pod en échec est la compétence la plus utilisée au quotidien par un ingénieur DevOps sur Kubernetes.
📋 Énoncé
Configurez des resources sur un Deployment, observez les comportements limites, puis diagnostiquez des pods en erreur.
🧭 Déroulement de l'exercice
Tâche 1 : Configurer les resources
cat > resources-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-resources
namespace: intermediaire
spec:
replicas: 1
selector:
matchLabels:
app: app-resources
template:
metadata:
labels:
app: app-resources
spec:
containers:
- name: app
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: "100m" # 100 millicores = 0.1 CPU
memory: "128Mi" # Réservation mémoire
limits:
cpu: "500m" # Max 0.5 CPU (throttling si dépassé)
memory: "256Mi" # Max 256Mi (OOMKilled si dépassé)
EOF
kubectl apply -f resources-deployment.yaml
# Voir les resources configurées
kubectl describe pod -l app=app-resources -n intermediaire | grep -A 10 "Limits\|Requests"Indice : Les
requestssont utilisées par le scheduler pour décider sur quel nœud placer le pod. Leslimitssont le plafond au-delà duquel :- CPU : le processeur est throttlé (ralenti, pas de kill)
- Mémoire : le pod est tué (
OOMKilled)
Tâche 2 : Observer un pod en état Pending
# Demander des resources trop importantes
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: too-large
namespace: intermediaire
spec:
containers:
- name: app
image: nginx:1.27
resources:
requests:
cpu: "99" # 99 CPU cores (impossible sur minikube)
memory: "500Gi"
EOF
# Le pod reste en Pending
kubectl get pod too-large -n intermediaire -w
# Diagnostiquer pourquoi
kubectl describe pod too-large -n intermediaire | tail -20
# → Events: Warning FailedScheduling ... Insufficient cpu# Nettoyer
kubectl delete pod too-large -n intermediaireTâche 3 : Simuler un CrashLoopBackOff
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: crash-demo
namespace: intermediaire
spec:
containers:
- name: app
image: busybox:latest
command: ["sh", "-c", "echo 'Je démarre' && sleep 2 && exit 1"]
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 50m
memory: 64Mi
EOF
# Observer le cycle CrashLoopBackOff
kubectl get pod crash-demo -n intermediaire -w# Diagnostiquer
kubectl describe pod crash-demo -n intermediaire | grep -A 20 "Events"
kubectl logs crash-demo -n intermediaire # Logs du dernier redémarrage
kubectl logs crash-demo -n intermediaire --previous # Logs du redémarrage précédent
# Voir le nombre de redémarrages
kubectl get pod crash-demo -n intermediaire
# RESTARTS augmente exponentiellement avec les délais de CrashLoopBackOff
kubectl delete pod crash-demo -n intermediaireTâche 4 : Toolkit de debugging
Voici les commandes indispensables pour diagnostiquer n'importe quel problème :
# 1. Vue d'ensemble rapide
kubectl get pods -n intermediaire
# STATUS : Running, Pending, CrashLoopBackOff, OOMKilled, ImagePullBackOff
# 2. Détail complet (toujours commencer par là)
kubectl describe pod <nom-du-pod> -n intermediaire
# 3. Logs en temps réel
kubectl logs <nom-du-pod> -n intermediaire -f # Suivre les logs
kubectl logs <nom-du-pod> -n intermediaire --tail=50 # Dernières 50 lignes
kubectl logs <nom-du-pod> -n intermediaire --previous # Logs avant le crash
# 4. Entrer dans le conteneur
kubectl exec -it <nom-du-pod> -n intermediaire -- sh
kubectl exec -it <nom-du-pod> -n intermediaire -- bash
# 5. Pod de debug éphémère (Kubernetes 1.23+)
kubectl debug <nom-du-pod> -n intermediaire \
--image=busybox:latest --target=<nom-du-pod> -it
# 6. Événements du namespace (très utile)
kubectl get events -n intermediaire --sort-by='.lastTimestamp' | tail -20
# 7. Consommation réelle des ressources
kubectl top pods -n intermediaire # Nécessite metrics-server# Pratiquer : créer un pod ImagePullBackOff et le diagnostiquer
cat << 'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: bad-image
namespace: intermediaire
spec:
containers:
- name: app
image: nginx:cette-version-nexiste-pas
resources:
requests:
cpu: 10m
memory: 32Mi
EOF
# Identifier le problème
kubectl describe pod bad-image -n intermediaire | grep -A 10 "Events"
# → Failed to pull image... : image not found
kubectl delete pod bad-image -n intermediaire✅ Vérification du résultat
- Le pod
app-resourcesestRunningavec les resources configurées - Le pod
too-largereste enPendingavecInsufficient cpudans les events - Le pod
crash-demoentre enCrashLoopBackOffet les logs montrent "Je démarre" - Le pod
bad-imagemontreErrImagePull/ImagePullBackOffdanskubectl describe
💡 À retenir
Statuts à connaître :
| Statut | Cause probable | Commande de diagnostic |
|---|---|---|
| Pending | Resources insuffisantes, nœud plein | kubectl describe pod → Events |
| CrashLoopBackOff | Application qui crashe | kubectl logs --previous |
| OOMKilled | Dépassement de la limit mémoire | kubectl describe pod → Exit Code 137 |
| ImagePullBackOff | Image inexistante ou privée | kubectl describe pod → Events |
| Running | ✅ Tout va bien |
Règle empirique pour les resources :
requests = usage normal moyen
limits = 2x à 3x les requests (pic d'activité)✨ Solution Complète
# Workflow de debugging (dans cet ordre)
kubectl get pods -n mon-namespace
kubectl describe pod mon-pod -n mon-namespace # Lire la section Events
kubectl logs mon-pod -n mon-namespace
kubectl logs mon-pod -n mon-namespace --previous # Si CrashLoopBackOff
kubectl exec -it mon-pod -n mon-namespace -- sh # Si besoin d'inspecter