Introduction
Les Pods Kubernetes sont les plus petites unités déployables d'un cluster, mais les traiter comme de simples enveloppes autour des conteneurs masque les comportements avancés qui déterminent si les charges de travail survivent aux pannes de nœuds, évoluent efficacement et respectent les budgets de ressources. Cet article dépasse le simple tutoriel kubectl run et explique le fonctionnement interne des Pods, leur architecture et leurs modèles de cycle de vie dont les opérateurs et les développeurs ont besoin pour des charges de travail de qualité production.
Vous apprendrez comment le kubelet gère les Pods tout au long de leur cycle de vie, comment contrôler le placement avec l'affinité, les tolérances et les contraintes de répartition topologique, et comment éviter les pannes en cascade grâce aux limites de ressources, aux sondes et aux budgets de perturbation. Chaque section comprend des manifestes concrets, des commandes et les sorties attendues pour que vous puissiez valider ces concepts dans votre propre cluster.
Nous supposons un cluster Kubernetes en cours d'exécution (v1.24 ou ultérieure) et kubectl configuré avec des autorisations de niveau cluster-admin ou d'espace de noms. Tous les exemples utilisent un espace de noms dédié appelé pod-lab. Créez-le avant de continuer :
kubectl create namespace pod-lab
Inventaire de la version et de l'environnement
Avant de modifier un Pod en production, capturez la version du cluster, le système d'exploitation des nœuds, le moteur d'exécution des conteneurs et la spécification exacte du Pod en cours d'exécution. Cet inventaire est la base d'un dépannage et d'une restauration en toute sécurité.
Informations sur le cluster et les nœuds
Exécutez les commandes en lecture seule suivantes pour établir votre environnement :
kubectl version --short
# Exemple de sortie :
# Client Version: v1.25.3
# Server Version: v1.25.3
kubectl get nodes -o wide
# NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
# node-1 Ready control-plane 10d v1.25.3 192.168.1.10 <none> Ubuntu 22.04.1 LTS 5.15.0-52-generic containerd://1.6.9
# node-2 Ready <none> 10d v1.25.3 192.168.1.11 <none> Ubuntu 22.04.1 LTS 5.15.0-52-generic containerd://1.6.9
Notez le moteur d'exécution des conteneurs (containerd, CRI-O ou Docker) et la version du noyau ; ils affectent les paramètres du contexte de sécurité du Pod et le comportement des montages de volumes.
Collecte de l'état actuel du Pod
Pour inspecter un Pod en cours d'exécution sans rien modifier :
kubectl get pod <nom-du-pod> -n <espace-de-noms> -o yaml > pod-actuel.yaml
Cette sauvegarde YAML est votre référence de restauration. Portez une attention particulière au bloc status, qui comprend des conditions telles que PodScheduled, Initialized, ContainersReady et Ready. Ces conditions indiquent où en est le Pod dans son cycle de vie.
Exemple d'extrait de statut :
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-05-01T12:00:00Z"
status: "True"
type: PodScheduled
- lastProbeTime: null
lastTransitionTime: "2023-05-01T12:00:10Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-05-01T12:00:20Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-05-01T12:00:25Z"
status: "True"
type: Ready
Chaque condition possède un champ lastTransitionTime et reason qui facilitent l'établissement d'une chronologie d'incident.
Chemin de configuration sécurisé
La configuration avancée des Pods doit suivre une progression allant de la validation locale au déploiement en production. Cela réduit le risque qu'un Pod mal configuré provoque une panne.
Commencer avec un manifeste de Pod minimal
Créez un manifeste de Pod de base qui ne comprend que l'image du conteneur et une étiquette :
# baseline-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: baseline-pod
namespace: pod-lab
labels:
app: baseline
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
Appliquez-le et vérifiez :
kubectl apply -f baseline-pod.yaml
kubectl get pod baseline-pod -n pod-lab
# NAME READY STATUS RESTARTS AGE
# baseline-pod 1/1 Running 0 10s
Ajouter des requêtes et des limites de ressources
Les requêtes de ressources garantissent une quantité minimale de CPU et de mémoire, tandis que les limites plafonnent le maximum. Sans elles, le kubelet ne peut pas prendre de décisions d'ordonnancement équitables, et un voisin bruyant peut affamer d'autres Pods.
Mettez à jour le manifeste avec les spécifications de ressources :
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
resources:
requests:
cpu: "100m" # 0,1 CPU
memory: "128Mi" # 128 MiB
limits:
cpu: "500m" # 0,5 CPU
memory: "256Mi" # 256 MiB
Appliquez et confirmez que la classe QoS est définie sur Burstable (car les requêtes sont inférieures aux limites) :
kubectl apply -f baseline-pod.yaml
kubectl get pod baseline-pod -n pod-lab -o jsonpath='{.status.qosClass}'
# Burstable
Pour les charges de travail critiques en latence, définissez les requêtes égales aux limites pour obtenir la classe QoS Guaranteed, qui donne au Pod la priorité d'éviction la plus élevée en cas de pression sur le nœud.
Configurer les sondes de santé et de disponibilité
Les sondes sont essentielles pour un fonctionnement avancé des Pods. Sans elles, Kubernetes ne peut pas détecter une application bloquée ni arrêter le trafic vers un Pod pas encore prêt.
Ajoutez des sondes de vivacité (liveness) et de disponibilité (readiness) au conteneur nginx :
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 3
Dans cet exemple, la sonde de vivacité redémarrera le conteneur si /healthz renvoie un statut différent de 200 trois fois de suite après le délai initial. La sonde de disponibilité marquera le Pod comme non prêt si le contrôle de santé échoue, ce qui amènera le Service à cesser de lui envoyer du trafic.
Appliquez et observez les sondes en action :
kubectl apply -f baseline-pod.yaml
kubectl describe pod baseline-pod -n pod-lab | grep -A5 'Liveness\|Readiness'
# Liveness: http-get http://:80/healthz delay=10s timeout=2s period=5s #success=1 #failure=3
# Readiness: http-get http://:80/healthz delay=5s timeout=2s period=3s #success=1 #failure=3
Vérification et diagnostics
Lorsqu'un Pod se comporte mal, une vérification et des diagnostics systématiques sont plus efficaces que les conjectures. Commencez par un état de haut niveau, puis passez aux événements, aux journaux et à l'intérieur des conteneurs.
Contrôle d'état de haut niveau
Obtenez l'état du Pod et les événements récents :
kubectl get pod <nom-du-pod> -n pod-lab -o wide
kubectl describe pod <nom-du-pod> -n pod-lab
La sortie de describe comprend une section comme :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m default-scheduler Successfully assigned pod-lab/baseline-pod to node-2
Normal Pulling 2m kubelet Pulling image "nginx:1.25-alpine"
Normal Pulled 119s kubelet Successfully pulled image "nginx:1.25-alpine" in 1.2s
Normal Created 119s kubelet Created container nginx
Normal Started 119s kubelet Started container nginx
Si le Pod est bloqué en Pending, recherchez les événements FailedScheduling indiquant des pénuries de ressources ou des tolérances. S'il est en CrashLoopBackOff, vérifiez le Last State et le code de sortie.
Vérifier les journaux du conteneur
Pour un conteneur qui plante, récupérez les journaux de l'instance précédente :
kubectl logs <nom-du-pod> -n pod-lab --previous
Si le conteneur écrit les journaux dans des fichiers au lieu de stdout/stderr, utilisez kubectl exec pour les inspecter :
kubectl exec -it <nom-du-pod> -n pod-lab -- cat /var/log/app.log
Déboguer avec un conteneur éphémère
Pour des diagnostics avancés sur un Pod en cours d'exécution qui manque d'outils de débogage, utilisez les conteneurs éphémères (Kubernetes v1.23+) :
kubectl debug -it <nom-du-pod> -n pod-lab --image=busybox --target=<nom-du-conteneur>
Cela attache un nouveau conteneur à l'espace de noms réseau et PID du Pod (si le partage est activé), ce qui vous permet d'exécuter nslookup, curl ou strace sans redémarrer le conteneur d'origine.
Exemple :
kubectl debug -it baseline-pod -n pod-lab --image=busybox --target=nginx
# À l'intérieur du conteneur éphémère :
/ # wget -qO- http://localhost/healthz
<!DOCTYPE html>...
Modes de défaillance et récupération
Les défaillances des Pods se répartissent en catégories prévisibles : échecs d'ordonnancement, erreurs d'extraction d'image, boucles de plantage, échecs de sondes et éviction. Comprendre chaque mode de défaillance permet une récupération rapide et une prévention.
Échecs d'ordonnancement
Si un Pod reste Pending, vérifiez les tolérances sur les nœuds et si le Pod les tolère. Listez les tolérances :
kubectl get nodes -o json | jq '.items[].spec.taints'
# [{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane"}]
Si un nœud est marqué avec NoSchedule, votre Pod doit avoir une tolérance correspondante. Ajoutez-en une à la spécification du Pod :
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
Vérifiez également que les requêtes de ressources tiennent sur un nœud. Utilisez kubectl describe nodes pour voir les ressources allouées.
Erreurs d'extraction d'image
Si le statut du Pod est ImagePullBackOff ou ErrImagePull, vérifiez le message d'événement :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10m default-scheduler Successfully assigned...
Warning Failed 10m kubelet Failed to pull image "nginx:1.25-alpine": rpc error: code = NotFound desc = failed to pull and unpack image
Causes courantes : balise d'image incorrecte, imagePullSecret manquant pour un registre privé, ou indisponibilité du registre. Corrigez la référence de l'image ou ajoutez un secret :
kubectl create secret docker-registry regcred \
--docker-server=myregistry.example.com \
--docker-username=myuser \
--docker-password=mypassword \
[email protected] \
-n pod-lab
Référencez-le ensuite dans la spécification du Pod :
imagePullSecrets:
- name: regcred
CrashLoopBackOff
Un CrashLoopBackOff signifie que le conteneur démarre puis se termine avec un code non nul. Inspectez le code de sortie et les journaux :
kubectl get pod <nom-du-pod> -n pod-lab -o jsonpath='{.status.containerStatuses[0].lastState.terminated.exitCode}'
# 1
kubectl logs <nom-du-pod> -n pod-lab --previous
Causes courantes : mauvaise configuration de l'application, dépendances manquantes ou script de démarrage en échec. Corrigez le problème sous-jacent et appliquez le manifeste mis à jour.
Récupération après échec de sonde
Si une sonde de disponibilité échoue, le statut du Pod affichera Running mais READY 0/1. Le trafic via un Service sera arrêté. Vérifiez la configuration de la sonde et la santé du point de terminaison :
kubectl get endpoints <nom-du-service> -n pod-lab
# NAME ENDPOINTS AGE
# my-service 192.168.1.12:80 5m
Si aucun point de terminaison n'est listé, la sonde de disponibilité échoue. Ajustez le chemin, le port ou les seuils de la sonde.
Éviction et perturbation des Pods
La pression sur les nœuds ou la préemption peut évincer les Pods. Utilisez un PodDisruptionBudget (PDB) pour limiter les perturbations volontaires pendant la maintenance. Exemple de PDB pour un Deployment :
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
namespace: pod-lab
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
Cela garantit qu'au moins deux répliques restent disponibles pendant les perturbations volontaires comme kubectl drain.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle avant et après toute opération avancée sur un Pod pour vous assurer d'avoir couvert les étapes d'observation, de sécurité et de vérification.
Avant d'effectuer des modifications
- [ ] Capturer le YAML actuel du Pod avec
kubectl get pod <nom> -o yaml > backup.yaml. - [ ] Enregistrer la version du cluster et le système d'exploitation/runtime des nœuds (
kubectl version,kubectl get nodes -o wide). - [ ] Vérifier l'état actuel du Pod, la classe QoS et les requêtes/limites de ressources.
- [ ] Vérifier tout PDB affectant le contrôleur du Pod.
- [ ] Confirmer l'espace de noms et le contexte cibles (
kubectl config current-context). - [ ] Si vous modifiez un Deployment, enregistrer la révision de déploiement actuelle (
kubectl rollout history deployment/<nom>).
Pendant la modification
- [ ] Appliquer une modification à la fois pour isoler les effets.
- [ ] Utiliser
--dry-run=serverpour valider la syntaxe du manifeste et le contrôle d'admission avant de l'appliquer :
kubectl apply -f pod-change.yaml --dry-run=server
- [ ] Déclencher la modification et surveiller immédiatement l'état du déploiement :
kubectl apply -f pod-change.yaml
kubectl get pods -n pod-lab -w
Après la modification
- [ ] Vérifier que le Pod atteint l'état
Readydans le délai prévu. - [ ] Vérifier les événements pour les avertissements (
kubectl describe pod <nom>). - [ ] Exécuter des tests de fumée au niveau de l'application (par exemple,
curlvia un Service). - [ ] Confirmer qu'aucune éviction ou redémarrage non intentionnel n'a eu lieu (
kubectl get pod <nom> -o jsonpath='{.status.containerStatuses[0].restartCount}'). - [ ] Mettre à jour la documentation avec la modification et le plan de restauration (par exemple,
kubectl apply -f backup.yaml).
Conclusion
La gestion avancée des Pods exige d'aller au-delà de la simple création pour comprendre le cycle de vie complet et les commandes de contrôle offertes par Kubernetes. En capturant l'inventaire de l'environnement, en suivant un chemin de configuration sûr, en vérifiant et en diagnostiquant systématiquement les problèmes et en vous préparant aux modes de défaillance, vous pouvez exploiter les Pods en toute confiance en production.
Commencez par un concept de cet article — par exemple, ajouter des limites de ressources à un Pod critique ou configurer des sondes de disponibilité — et validez-le dans un espace de noms de test. Observez les effets, documentez le comportement attendu, puis étendez à des charges de travail plus larges. Les commandes et les manifestes présentés ici sont votre point de départ pour construire des applications robustes et auto-réparatrices sur Kubernetes.
La prochaine fois qu'un Pod échouera, vous disposerez d'un processus structuré pour trouver rapidement la cause première et récupérer sans conjectures. Gardez cette liste de contrôle à portée de main et revisitez-la après chaque incident pour affiner votre manuel opérationnel.