Aller au contenu
English
Conteneurs & Orchestration medium

Pod Kubernetes : créer, observer et comprendre son cycle de vie

45 min de lecture

logo kubernetes

Un Pod est l'objet de base utilisé par Kubernetes pour exécuter un ou plusieurs conteneurs. Dans la majorité des cas, un Pod contient un seul conteneur. Ce guide vous montre comment créer un Pod, l'observer, comprendre son cycle de vie et diagnostiquer les problèmes les plus fréquents.

Prérequis : un cluster kind et kubectl configuré.

  • Créer un Pod avec kubectl run et avec un fichier YAML
  • Observer un Pod : voir son état, lire ses logs, entrer dedans
  • Comprendre le cycle de vie : phases, restartPolicy, CrashLoopBackOff
  • Utiliser les init containers pour préparer l'environnement
  • Diagnostiquer les problèmes : ImagePullBackOff, Pending, crash

Un Pod est la plus petite unité déployable dans Kubernetes. C'est l'objet que Kubernetes crée, planifie sur un nœud et surveille.

Pour un débutant, retenez simplement :

  • Un Pod exécute vos conteneurs
  • Kubernetes gère le Pod (démarrage, surveillance, redémarrage)
  • Dans 80% des cas, un Pod = un conteneur

Pourquoi ne pas gérer directement les conteneurs ? Parce que certaines applications nécessitent plusieurs processus qui doivent :

  • Partager la même adresse IP (ils communiquent via localhost)
  • Partager les mêmes volumes (fichiers communs)
  • Être co-localisés sur le même nœud
  • Être démarrés et arrêtés ensemble

Le Pod est l'unité de scheduling : c'est lui que Kubernetes place sur un nœud, pas le conteneur individuel.

Même si un Pod peut contenir plusieurs conteneurs, vous utiliserez presque toujours des Pods mono-conteneur. Les Pods multi-conteneurs répondent à des cas précis, les sidecars et les init containers, tous deux traités plus bas dans ce guide.

Deux chemins mènent au même Pod. La méthode impérative tient en une commande et convient pour essayer, déboguer ou produire un squelette. La méthode déclarative passe par un fichier YAML que vous versionnez, et c'est celle que vous emploierez en équipe. Commencez par la première pour voir un Pod vivre, la seconde arrive juste après.

La façon la plus rapide de créer un Pod :

Fenêtre de terminal
kubectl run mon-nginx --image=nginx:1.27-alpine

Résultat : un Pod nommé mon-nginx exécutant Nginx.

Vérifiez sa création :

Fenêtre de terminal
kubectl get pods
Sortie
NAME READY STATUS RESTARTS AGE
mon-nginx 1/1 Running 0 10s

Pour un contrôle total, créez un fichier manifest :

mon-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: mon-nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10
ports:
- containerPort: 80
restartPolicy: Always

Appliquez-le :

Fenêtre de terminal
kubectl apply -f mon-nginx.yaml

Vous n'avez pas besoin d'écrire ce YAML de mémoire. kubectl sait le produire pour vous, sans rien créer sur le cluster, ce qui est le point de départ le plus rapide pour un manifeste :

Fenêtre de terminal
kubectl run mon-nginx --image=nginx:1.27-alpine --dry-run=client -o yaml

Une fois votre Pod créé, vous voulez immédiatement savoir : est-ce qu'il tourne ? Où regarder ?

Fenêtre de terminal
kubectl get pods -o wide
Sortie
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mon-nginx 1/1 Running 0 8s 10.244.1.24 doc-k8s-worker <none> <none>

Les deux dernières colonnes restent vides tant que vous ne faites ni préemption ni readiness gates : ne vous en préoccupez pas pour l'instant.

Les colonnes importantes :

ColonneSignification
READY1/1 = 1 conteneur prêt sur 1 total
STATUSPhase actuelle du Pod (Running, Pending...)
RESTARTSNombre de redémarrages du conteneur
IPAdresse IP interne du Pod
Fenêtre de terminal
kubectl describe pod mon-nginx

Cette commande affiche :

  • Conditions : états du Pod (PodScheduled, Initialized, Ready...)
  • Containers : état de chaque conteneur
  • Events : historique des actions (scheduling, pull d'image, démarrage...)

C'est la commande à lancer quand un Pod ne démarre pas. Les Events, en bas de la sortie, donnent presque toujours la raison : image introuvable, nœud sans ressource, volume en attente.

kubectl logs affiche ce que le conteneur écrit sur sa sortie standard. C'est là que se trouve le message d'erreur d'une application qui refuse de démarrer, et c'est donc la deuxième commande du diagnostic, juste après describe.

Fenêtre de terminal
kubectl logs mon-nginx

Options utiles :

Fenêtre de terminal
kubectl logs mon-nginx --tail=20 # Les 20 dernières lignes
kubectl logs mon-nginx --follow # Flux en temps réel
kubectl logs mon-nginx --previous # Logs du conteneur précédent (après crash)
Fenêtre de terminal
kubectl exec mon-nginx -- hostname
kubectl exec -it mon-nginx -- sh # Shell interactif

L'option -it est indispensable pour une commande interactive, shell ou éditeur. Sans elle, la commande s'exécute mais vous ne pouvez rien y taper.

Maintenant que vous avez vu un Pod vivre, regardons sa structure YAML :

ChampDescription
metadata.nameNom unique du Pod dans le namespace
metadata.labelsÉtiquettes pour organiser et sélectionner
spec.containers[]Liste des conteneurs (au moins un)
spec.containers[].imageImage à utiliser
spec.containers[].ports[]Ports exposés (informatif)
spec.restartPolicyComportement au redémarrage

La phase d'un Pod résume en un mot où il en est de son existence, du moment où l'API l'accepte jusqu'à son arrêt. C'est la colonne STATUS de kubectl get pods, et la première chose à lire quand quelque chose ne va pas. Il n'en existe que cinq, et trois suffisent au quotidien.

Un Pod passe par plusieurs phases :

Cycle de vie d'un Pod Kubernetes : Pending, Running, Succeeded ou Failed

PhaseSignification
PendingPod accepté mais pas encore sur un nœud. En attente de scheduling ou de téléchargement d'image.
RunningPod assigné à un nœud, au moins un conteneur tourne.
SucceededTous les conteneurs ont terminé avec succès (exit code 0).
FailedAu moins un conteneur a terminé en échec (exit code non-zéro).
UnknownÉtat indéterminé, souvent problème de communication avec le nœud.

Pour voir la phase :

Fenêtre de terminal
kubectl get pod mon-nginx -o jsonpath='{.status.phase}'

Chaque conteneur dans un Pod a son propre état :

ÉtatDescription
WaitingEn attente (pull d'image, init container en cours...)
RunningLe conteneur s'exécute
TerminatedLe conteneur s'est arrêté (succès ou échec)

Attention : CrashLoopBackOff n'est pas une phase du Pod. C'est un état d'attente du conteneur visible dans la sortie de kubectl get pods. Il signifie que le conteneur a crashé plusieurs fois et que Kubernetes attend avant de le redémarrer.

restartPolicy : que fait Kubernetes quand un conteneur s'arrête

Section intitulée « restartPolicy : que fait Kubernetes quand un conteneur s'arrête »

Le champ restartPolicy définit ce que Kubernetes fait quand un conteneur s'arrête :

ValeurComportementCas d'usage
Always (défaut)Redémarre le conteneur quoi qu'il arriveServices web, API
OnFailureRedémarre seulement si exit code ≠ 0Jobs de traitement batch
NeverNe redémarre jamaisTâches ponctuelles, debug

Avec les applications classiques, vous verrez surtout Always. Les valeurs OnFailure et Never apparaissent plutôt sur des Pods ponctuels ou créés par un Job.

job-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: job-pod
spec:
containers:
- name: worker
image: busybox:1.36@sha256:73aaf090f3d85aa34ee199857f03fa3a95c8ede2ffd4cc2cdb5b94e566b11662
command: ['sh', '-c', 'echo "Traitement..." && exit 0']
restartPolicy: OnFailure

Si le conteneur échoue (exit 1), Kubernetes le redémarre. S'il réussit (exit 0), le Pod passe en Succeeded.

Quand un conteneur échoue plusieurs fois, Kubernetes attend de plus en plus longtemps avant de le redémarrer :

  • 1ère tentative : 10s
  • 2ème : 20s
  • 3ème : 40s
  • Maximum : 5 minutes

C'est ce qui produit l'état CrashLoopBackOff.

Les init containers s'exécutent avant les conteneurs principaux. Ils sont plus simples à comprendre que les multi-conteneurs classiques car leur rôle est clair : préparer le terrain.

Un init container sert chaque fois qu'une condition doit être remplie avant que l'application démarre. Plutôt que d'inscrire cette attente dans le code applicatif, on la sort dans un conteneur dédié, qui a le droit d'échouer et d'être relancé sans conséquence.

  • Attendre qu'un service soit prêt (base de données, API)
  • Télécharger des fichiers de configuration
  • Initialiser une base de données
  • Vérifier des prérequis

Trois propriétés expliquent l'essentiel du comportement d'un init container, et notamment pourquoi un Pod peut rester bloqué en Init:0/1 sans jamais démarrer son application.

  • S'exécutent séquentiellement (un après l'autre)
  • Doivent tous réussir avant le démarrage des conteneurs principaux
  • Peuvent utiliser des images différentes (avec des outils spécifiques)
init-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: wait-for-db
image: busybox:1.36@sha256:73aaf090f3d85aa34ee199857f03fa3a95c8ede2ffd4cc2cdb5b94e566b11662
command: ['sh', '-c', 'until nc -z db-service 5432; do sleep 2; done']
containers:
- name: app
image: nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10

Le Pod restera en Init:0/1 jusqu'à ce que db-service:5432 réponde :

Fenêtre de terminal
kubectl get pod init-demo
Sortie pendant l'init
NAME READY STATUS RESTARTS AGE
init-demo 0/1 Init:0/1 0 5s

La question revient vite : faut-il mettre plusieurs conteneurs dans un Pod ? La réponse par défaut est non. Le partage du réseau et des volumes est le seul argument qui justifie de les réunir, et il ne se présente que dans des cas précis.

Dans 80% des cas, un Pod contient un seul conteneur. C'est le pattern recommandé car :

  • Plus simple à gérer
  • Scaling indépendant
  • Isolation des pannes

Les Pods multi-conteneurs servent à des cas spécifiques où les conteneurs doivent absolument partager réseau et volumes :

PatternDescriptionExemple
SidecarConteneur auxiliaire qui enrichit l'app principaleAgent de logs, proxy Envoy
Init containerPrépare l'environnement avant l'appAttente d'une dépendance

Les conteneurs d'un même Pod communiquent par localhost et partagent leurs volumes. Aucun Service n'est nécessaire entre eux, c'est précisément ce qui distingue un Pod multi-conteneur de deux Pods séparés.

app-avec-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-avec-sidecar
spec:
containers:
- name: app
image: nginx:1.27-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54ef4b76fb8e2f2a10
volumeMounts:
- name: logs
mountPath: /var/log/nginx
- name: log-collector
image: busybox:1.36@sha256:73aaf090f3d85aa34ee199857f03fa3a95c8ede2ffd4cc2cdb5b94e566b11662
command: ['sh', '-c', 'tail -f /var/log/nginx/access.log']
volumeMounts:
- name: logs
mountPath: /var/log/nginx
volumes:
- name: logs
emptyDir: {}

Les deux conteneurs partagent le volume logs.

Ne commencez pas par là. Maîtrisez d'abord les Pods mono-conteneur ; les sidecars viendront quand un besoin réel les appellera, typiquement la centralisation des logs ou un service mesh.

Ne créez jamais de Pods directement en production. Passez toujours par un contrôleur, qui saura les recréer, les répliquer et les mettre à jour. La raison tient en une phrase : un Pod n'est surveillé par personne, et Kubernetes ne répare que ce qu'un contrôleur lui demande de maintenir.

Un Pod "nu" (créé directement avec kubectl run ou un YAML Pod) a plusieurs problèmes :

ProblèmeConséquence
Pas de reschedulingSi le nœud tombe, le Pod disparaît définitivement
Pas de réplicasUn seul Pod = pas de haute disponibilité
Pas de rolling updateImpossible de mettre à jour sans interruption
Pas d'auto-scalingLe nombre de Pods est fixe
ContrôleurCas d'usage
DeploymentApplications stateless (API, web)
StatefulSetApplications stateful (bases de données)
DaemonSetUn Pod par nœud (agents de monitoring)
JobTâches batch ponctuelles
CronJobTâches planifiées

Ces contrôleurs créent et gèrent les Pods pour vous, avec la résilience nécessaire.

Le diagnostic d'un Pod suit toujours le même ordre, du moins coûteux au plus intrusif. Les premières commandes ne touchent à rien et répondent déjà à la plupart des situations ; les suivantes entrent dans le conteneur, et ne servent qu'ensuite.

Ces quatre commandes se lancent dans cet ordre, et chacune répond à une question différente : où en est le Pod, ce que Kubernetes a tenté, ce que l'application a dit, puis ce que le conteneur contient.

  1. Voir l'état :

    Fenêtre de terminal
    kubectl get pod mon-pod -o wide
  2. Lire les événements :

    Fenêtre de terminal
    kubectl describe pod mon-pod | tail -20
  3. Consulter les logs :

    Fenêtre de terminal
    kubectl logs mon-pod --tail=50
  4. Entrer dans le conteneur (si possible) :

    Fenêtre de terminal
    kubectl exec -it mon-pod -- sh

Ces quatre commandes résolvent 90% des problèmes.

Fenêtre de terminal
kubectl top pod mon-pod
Sortie
NAME CPU(cores) MEMORY(bytes)
mon-pod 3m 45Mi

kubectl top ne fonctionne pas sur un cluster nu. Il interroge le Metrics Server, qui n'est pas installé par défaut, ni sur kind ni sur un cluster kubeadm. Sans lui, la commande répond Metrics API not available.

Si le conteneur n'a pas de shell (image distroless, scratch), utilisez un conteneur éphémère :

Fenêtre de terminal
kubectl debug -it mon-pod --image=busybox:1.36@sha256:73aaf090f3d85aa34ee199857f03fa3a95c8ede2ffd4cc2cdb5b94e566b11662 --target=mon-conteneur

Le conteneur éphémère partage le namespace réseau et process du Pod ciblé.

Trois symptômes couvrent la très grande majorité des Pods qui ne démarrent pas. Chacun se reconnaît à la colonne STATUS, et pour chacun c'est la section Events de kubectl describe qui donne la cause exacte.

Symptôme : Le Pod redémarre en boucle.

NAME READY STATUS RESTARTS AGE
mon-pod 0/1 CrashLoopBackOff 5 3m

Rappel : ce n'est pas une phase du Pod, mais un état d'attente visible dans STATUS.

Causes possibles :

  1. L'application plante au démarrage (erreur de code)
  2. Configuration manquante (variables d'environnement, secrets)
  3. Dépendance non disponible (base de données, API)

Diagnostic :

Fenêtre de terminal
kubectl logs mon-pod --previous # Logs du crash précédent
kubectl describe pod mon-pod # Voir le exit code

Symptôme : le Pod ne démarre pas et Kubernetes n'arrive pas à télécharger l'image. La séquence relevée sur un cluster est ContainerCreating, puis ErrImagePull au premier échec, puis ImagePullBackOff quand les tentatives s'espacent. Les deux derniers alternent ensuite à chaque nouvelle tentative : voir l'état changer sous vos yeux dans un kubectl get pods -w est normal, ce n'est pas deux pannes différentes.

Causes possibles :

  1. Image inexistante ou mal orthographiée
  2. Registry privée sans credentials
  3. Problème réseau

Diagnostic :

Fenêtre de terminal
kubectl describe pod mon-pod | grep -A 5 "Events"

Symptôme : le Pod reste en Pending sans jamais être placé sur un nœud. Il a bien été accepté par l'API, mais le scheduler n'a trouvé aucun nœud qui lui convienne, ou le kubelet attend encore une ressource.

Causes possibles :

  1. Ressources insuffisantes sur les nœuds
  2. Pas de nœud avec les bons labels/taints
  3. Volume PVC en attente

Diagnostic :

Fenêtre de terminal
kubectl describe pod mon-pod | grep -A 10 "Events"
kubectl get nodes -o wide
kubectl describe node <nom-du-noeud>

Sept questions pour vérifier que les notions de ce guide sont acquises : cycle de vie, restartPolicy, init containers et diagnostic des trois pannes les plus fréquentes.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
80% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  1. Un Pod est l'unité minimale de Kubernetes : dans 80% des cas, 1 Pod = 1 conteneur
  2. Les conteneurs d'un Pod partagent réseau (localhost) et volumes
  3. Cycle de vie : Pending → Running → Succeeded/Failed
  4. CrashLoopBackOff n'est pas une phase du Pod, mais un état d'attente du conteneur
  5. restartPolicy : Always (défaut et le plus courant), OnFailure, Never
  6. Les init containers s'exécutent avant les conteneurs principaux pour préparer l'environnement
  7. Ne créez jamais de Pods nus en production : utilisez Deployments, StatefulSets ou Jobs
  8. Debug : commencez par get, describe, logs, exec avant kubectl debug

Ces questions reviennent souvent quand on découvre les Pods Kubernetes. Les réponses ci-dessous reprennent les points clés du guide, différence avec un conteneur, Pods multi-conteneurs, CrashLoopBackOff, init containers et cycle de vie.

  • Les Services : L'exposition stable de Pods dont l'adresse IP change à chaque recréation.
  • Les ConfigMaps : L'injection de configuration dans un Pod sans reconstruire son image.
  • Définir les Probes : Les sondes qui décident si un conteneur est vivant et prêt à recevoir du trafic.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn