Aller au contenu
English
English
Conteneurs & Orchestration medium

Deployments Kubernetes : déployer et mettre à jour vos applications

65 min de lecture

logo kubernetes

Un Deployment Kubernetes gère le déploiement et les mises à jour de vos applications. Il crée automatiquement les Pods, assure leur disponibilité et permet de mettre à jour ou revenir en arrière sans interruption de service. Ce guide vous montre comment créer des Deployments, maîtriser les rolling updates et configurer les paramètres essentiels en production.

Prérequis : un cluster Kubernetes fonctionnel avec kubectl configuré.

  • Créer un Deployment avec kubectl et YAML
  • Mettre à jour une application sans interruption (rolling update)
  • Revenir en arrière en cas de problème (rollback)
  • Configurer les paramètres de production (maxSurge, progressDeadlineSeconds...)
  • Choisir entre RollingUpdate et Recreate

Un Deployment est une ressource Kubernetes qui gère un ensemble de Pods identiques. Il garantit que le nombre de Pods voulus est toujours en cours d'exécution et orchestre les mises à jour de version.

Pour un débutant, retenez :

  • Le Deployment crée et surveille vos Pods automatiquement
  • Si un Pod tombe, le Deployment en recrée un
  • Pour une mise à jour, le Deployment remplace progressivement les anciens Pods

Créer des Pods manuellement pose plusieurs problèmes :

  • Pas de redémarrage automatique si un Pod crash
  • Mises à jour manuelles, risquées et longues
  • Pas de rollback facile en cas de problème

Les Deployments résolvent ces problèmes :

FonctionnalitéDescription
Auto-healingMaintient l'état souhaité via un ReplicaSet, qui recrée les Pods manquants
Rolling UpdateMise à jour sans interruption
RollbackRetour à une version précédente en une commande
ScalingAjustement du nombre de Pods à la demande

Une limite à connaître dès maintenant : le Deployment est conçu pour des applications sans état. Ses Pods sont interchangeables, il les nomme au hasard et les remplace dans n'importe quel ordre. Une base de données ou une file de messages a besoin de l'inverse, une identité et un disque stables : c'est le rôle du StatefulSet.

Comme pour les autres objets, deux chemins mènent au même résultat. La méthode impérative tient en une commande et sert à démarrer vite ou à produire un squelette. La méthode déclarative passe par un fichier YAML versionné, seule forme tenable dès qu'une équipe travaille sur le même cluster.

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

Fenêtre de terminal
kubectl create deployment nginx-demo \
--image=nginx:1.29-alpine@sha256:5616878291a2eed594aee8db4dade5878cf7edcb475e59193904b198d9b830de \
--replicas=3

Vérifiez sa création :

Fenêtre de terminal
kubectl get deployment nginx-demo
Sortie
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-demo 3/3 3 3 10s

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

nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.26@sha256:41b194461e4bae16f9b25d68b0976ed4735b89ca625c89aad88e1c1c3b7e8860
ports:
- containerPort: 80

Appliquez-le :

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

Deux blocs de ce manifeste doivent impérativement s'accorder : selector.matchLabels et template.metadata.labels. Le premier dit quels Pods le Deployment pilote, le second étiquette ceux qu'il crée. S'ils divergent, Kubernetes rejette le manifeste au lieu de créer un Deployment qui ne piloterait rien.

Trois commandes suffisent à savoir où en est un déploiement, et elles vont du général au précis : l'état d'ensemble, le détail de la stratégie, puis les Pods réellement créés.

C'est la première commande à lancer pour savoir si un déploiement va bien. La colonne à surveiller est READY : tant que le premier chiffre est inférieur au second (par exemple 0/3), aucun Pod n'est prêt à recevoir du trafic, souvent parce que l'image ne se télécharge pas. Le drapeau -o wide ajoute les colonnes IMAGES et SELECTOR, indispensables pour vérifier d'un coup d'oeil quelle version tourne réellement et quels Pods le Deployment pilote.

Fenêtre de terminal
kubectl get deployment -o wide
Sortie
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-demo 3/3 3 3 2m nginx nginx:1.26 app=nginx-demo
ColonneSignification
READYPods prêts / Pods souhaités
UP-TO-DATEPods avec la dernière version du template
AVAILABLEPods accessibles aux utilisateurs

C'est ici que se lisent les valeurs que vous n'avez pas écrites : Kubernetes remplit les champs manquants avec ses défauts, et describe les affiche tels qu'ils s'appliquent réellement.

Fenêtre de terminal
kubectl describe deployment nginx-demo
Sortie (extrait)
Name: nginx-demo
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
RollingUpdateStrategy: 25% max unavailable, 25% max surge
NewReplicaSet: nginx-demo-75984c689f (3/3 replicas created)

Les informations clés :

  • StrategyType : RollingUpdate ou Recreate
  • RollingUpdateStrategy : paramètres de mise à jour progressive
  • NewReplicaSet : le ReplicaSet actif qui gère les Pods
Fenêtre de terminal
kubectl get pods -l app=nginx-demo
Sortie
NAME READY STATUS RESTARTS AGE
nginx-demo-75984c689f-6zw4w 1/1 Running 0 2m
nginx-demo-75984c689f-ln2zn 1/1 Running 0 2m
nginx-demo-75984c689f-wzs4s 1/1 Running 0 2m

Le nom du Pod suit le format <deployment>-<replicaset-hash>-<pod-hash>.

Maintenant que vous avez vu un Deployment vivre, voici sa structure complète. La plupart de ces champs ont un défaut raisonnable : le manifeste minimal n'en porte que trois, replicas, selector et template. Les autres sont montrés ici parce qu'ils décident du comportement en production.

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-demo
spec:
replicas: 3 # Nombre de Pods souhaités
revisionHistoryLimit: 5 # Nombre d'anciennes versions conservées
progressDeadlineSeconds: 300 # Timeout pour une mise à jour
minReadySeconds: 10 # Temps avant de considérer un Pod disponible
strategy:
type: RollingUpdate # ou Recreate
rollingUpdate:
maxUnavailable: 1 # Pods indisponibles max pendant update
maxSurge: 1 # Pods supplémentaires max pendant update
selector:
matchLabels:
app: nginx-demo # Doit correspondre aux labels du template
template: # Template des Pods créés
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.26@sha256:41b194461e4bae16f9b25d68b0976ed4735b89ca625c89aad88e1c1c3b7e8860
ChampPar défautDescription
replicas1Nombre de Pods souhaités
revisionHistoryLimit10Nombre de ReplicaSets conservés pour rollback
progressDeadlineSeconds600Secondes avant timeout d'une mise à jour
minReadySeconds0Temps minimal pendant lequel un Pod doit rester prêt avant d'être considéré disponible
maxUnavailable25%Pods indisponibles max pendant rolling update
maxSurge25%Pods supplémentaires max pendant rolling update

Deux de ces champs méritent d'être écrits explicitement en production, plutôt que laissés au défaut. revisionHistoryLimit conserve dix anciens ReplicaSets, ce qui encombre le cluster sans servir : cinq suffisent pour revenir en arrière. Et progressDeadlineSeconds, fixé à dix minutes par défaut, doit refléter le temps de démarrage réel de votre application, sans quoi un déploiement bloqué met dix minutes à se signaler.

Un rolling update n'est réellement fiable que si Kubernetes sait quand un Pod est prêt à recevoir du trafic. En pratique, cela repose sur une readinessProbe correctement configurée. Sans elle, Kubernetes peut envoyer du trafic vers des Pods encore en phase d'initialisation.

Combinez avec minReadySeconds pour ajouter un délai de stabilité avant de considérer le Pod comme disponible.

Pour aller plus loin, consultez le guide sur les Probes Kubernetes.

Un Deployment ne met à jour les Pods que si le template change (image, variables, resources...). Un scaling ne déclenche pas de rolling update.

La commande set image modifie le champ image du template de Pod, ce qui suffit à déclencher un rolling update. La syntaxe attend <nom-du-conteneur>=<nouvelle-image> : ici nginx est le nom du conteneur dans le manifest, pas celui du Deployment. Une erreur sur ce nom fait échouer la commande sans rien modifier :

error: unable to find container named "mauvais-nom"
Fenêtre de terminal
kubectl set image deployment/nginx-demo nginx=nginx:1.27

rollout status bloque le terminal et affiche l'avancement du remplacement jusqu'à ce que tous les nouveaux Pods soient disponibles, ou jusqu'au dépassement de progressDeadlineSeconds. C'est la commande à mettre dans un script de déploiement : elle renvoie un code de sortie non nul si la mise à jour échoue, ce qui permet d'enchaîner un rollback automatique en CI.

Fenêtre de terminal
kubectl rollout status deployment/nginx-demo
Sortie
Waiting for deployment "nginx-demo" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-demo" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-demo" successfully rolled out

Kubernetes crée un nouveau ReplicaSet et ajuste progressivement les replicas :

Processus de Rolling Update d'un Deployment Kubernetes

L'ancien ReplicaSet est conservé (avec 0 replicas) pour permettre un rollback.

Ce remplacement progressif ne prend tout son sens qu'avec un Service : pendant toute la mise à jour, le Service ne dirige le trafic que vers les Pods prêts, et jamais vers ceux qui démarrent encore.

Le Deployment ne crée jamais de Pod lui-même : il délègue à un ReplicaSet, qu'il crée à neuf à chaque changement de template. Vous n'interagissez pratiquement jamais avec eux, mais kubectl get rs les montre, et c'est là qu'on voit combien d'anciennes versions restent disponibles pour un rollback.

Chaque changement de template crée une révision numérotée, et l'ancien ReplicaSet est conservé avec zéro Pod. Revenir en arrière consiste donc à le réactiver, ce qui se fait en une commande et sans interruption.

Fenêtre de terminal
kubectl rollout history deployment/nginx-demo
Sortie
deployment.apps/nginx-demo
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>

Les trois révisions affichent <none> parce que rien n'a renseigné CHANGE-CAUSE. Un historique dans cet état dit qu'il y a eu trois changements, jamais lesquels.

Pour voir les détails d'une révision :

Fenêtre de terminal
kubectl rollout history deployment/nginx-demo --revision=2

Sans argument, rollout undo revient à la révision immédiatement précédente, ce qui est le geste réflexe quand une mise à jour vient de mal tourner. Le rollback est lui-même un rolling update : Kubernetes réactive l'ancien ReplicaSet (conservé avec 0 replica) et remonte progressivement ses Pods, sans interruption.

Fenêtre de terminal
kubectl rollout undo deployment/nginx-demo

--to-revision vise un numéro précis de l'historique, ce qui sert quand la révision précédente était elle aussi mauvaise. Le numéro se lit dans rollout history.

Fenêtre de terminal
kubectl rollout undo deployment/nginx-demo --to-revision=1

Documenter ses révisions, et le piège de l'annotation

Section intitulée « Documenter ses révisions, et le piège de l'annotation »

Un historique de révisions sans CHANGE-CAUSE ne sert à rien : il dit qu'il y a eu un changement, jamais lequel. L'annotation kubernetes.io/change-cause remplit cette colonne.

Fenêtre de terminal
kubectl annotate deployment/nginx-demo \
kubernetes.io/change-cause="Passage en nginx 1.28" --overwrite
Historique après l'annotation
REVISION CHANGE-CAUSE
1 <none>
2 Passage en nginx 1.28

Le piège tient en une phrase : cette annotation PERSISTE. Elle vit sur le Deployment, pas sur la révision. Le déploiement suivant la recopie telle quelle, et l'historique se met à mentir :

Après un passage en 1.29, sans retoucher l'annotation
REVISION CHANGE-CAUSE
2 Passage en nginx 1.28
3 Passage en nginx 1.28

La révision 3 porte nginx 1.29 et affirme être un passage en 1.28. Un collègue qui lit cet historique pendant un incident sera induit en erreur.

La règle qui en découle : réécrire l'annotation à chaque déploiement, juste avant ou juste après, et jamais une seule fois. En pratique, cela se place dans le script de déploiement, à côté du set image.

Pour appliquer plusieurs modifications sans déclencher de rollout intermédiaire :

Fenêtre de terminal
# Mettre en pause
kubectl rollout pause deployment/nginx-demo
# Appliquer plusieurs changements
kubectl set image deployment/nginx-demo nginx=nginx:1.28
kubectl set resources deployment/nginx-demo -c=nginx --limits=cpu=200m,memory=256Mi
# Reprendre (un seul rollout pour tous les changements)
kubectl rollout resume deployment/nginx-demo
Fenêtre de terminal
kubectl scale deployment/nginx-demo --replicas=5

Le scaling est instantané et ne crée pas de nouvelle révision.

Pour un scaling automatique basé sur la charge :

Fenêtre de terminal
kubectl autoscale deployment/nginx-demo --min=3 --max=10 --cpu=80%

Cela crée un HorizontalPodAutoscaler.

Kubernetes n'en propose que deux, et le choix se résume à une question : vos deux versions peuvent-elles tourner en même temps ? Si oui, le remplacement progressif s'impose ; si non, il faut accepter une coupure.

Remplace progressivement les Pods sans interruption.

spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # ou "25%"
maxSurge: 1 # ou "25%"
ParamètreEffet
maxUnavailable: 0Toujours au moins N replicas disponibles (plus lent)
maxSurge: 0Jamais plus de N replicas (économise les ressources)
Les deux à 0Refusé à l'application par l'API, voir le message ci-dessous

Mettre les deux à zéro demanderait à Kubernetes de remplacer des Pods sans jamais en retirer ni en ajouter : la demande n'a pas de solution, et l'API la refuse explicitement.

The Deployment "demo" is invalid: spec.strategy.rollingUpdate.maxUnavailable:
Invalid value: 0: may not be 0 when `maxSurge` is 0

Cas d'usage : la majorité des applications web, APIs, microservices.

Supprime tous les anciens Pods avant de créer les nouveaux. Provoque une interruption.

spec:
strategy:
type: Recreate

Cas d'usage :

  • Application qui ne peut pas coexister en plusieurs versions (schéma de BDD incompatible)
  • Environnements de dev/test où l'interruption n'est pas critique

Blue-Green : deux Deployments (blue et green), on bascule le Service.

Canary : nouveau Deployment avec peu de replicas, on ajuste progressivement le trafic.

Ces patterns sont décrits en détail dans le guide Stratégies de déploiement avancées.

CritèreDeploymentStatefulSet
ApplicationStatelessStateful
Identité des PodsAléatoireStable et ordonnée
StockageÉphémère (ou PVC partagé)PVC persistant par Pod
ExemplesAPI, frontend, workersBases de données, Kafka, Elasticsearch

Règle simple : si votre application stocke des données locales ou a besoin d'identités réseau stables, utilisez un StatefulSet.

Un déploiement qui ne finit pas a presque toujours sa cause dans les Pods, pas dans le Deployment. La démarche consiste donc à descendre : constater le blocage au niveau du Deployment, puis chercher la raison au niveau du Pod.

Symptôme : kubectl rollout status ne rend pas la main. C'est le comportement normal de la commande tant que le déploiement progresse ; elle devient un signal d'alerte quand rien ne bouge pendant plusieurs minutes.

Fenêtre de terminal
# Vérifier les conditions
kubectl describe deployment nginx-demo | grep -A5 Conditions
# Voir les événements
kubectl get events --sort-by=.lastTimestamp

Causes fréquentes :

  • Image introuvable (ImagePullBackOff)
  • Ressources insuffisantes (Pending)
  • Readiness probe qui échoue

Ces trois commandes s'enchaînent du général au précis. get pods donne le statut (ImagePullBackOff, CrashLoopBackOff, Pending), describe pod remonte les événements du planificateur et du kubelet, qui expliquent pourquoi le Pod est coincé, et logs montre la sortie du conteneur lui-même quand il démarre mais s'arrête aussitôt. Un ImagePullBackOff se diagnostique dans describe ; une erreur applicative se lit dans logs.

Fenêtre de terminal
kubectl get pods -l app=nginx-demo
kubectl describe pod <nom-du-pod>
kubectl logs <nom-du-pod>

Si progressDeadlineSeconds est dépassé, le Deployment passe en condition Progressing: False avec raison ProgressDeadlineExceeded.

Fenêtre de terminal
kubectl describe deployment nginx-demo | grep ProgressDeadlineExceeded

Le déploiement n'est pas automatiquement rollback. Vous devez le faire manuellement :

Fenêtre de terminal
kubectl rollout undo deployment/nginx-demo

Ce court quiz reprend les points qui posent le plus souvent problème en pratique : la différence entre RollingUpdate et Recreate, le rôle du ReplicaSet, et le comportement du retour arrière. Répondez sans revenir en arrière : ce qui bloque désigne précisément le passage à relire.

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 Deployment gère des Pods stateless avec auto-healing et rolling updates
  2. RollingUpdate (défaut) remplace progressivement les Pods sans interruption
  3. Recreate supprime tout avant de recréer (interruption de service)
  4. maxUnavailable et maxSurge contrôlent la vitesse du rolling update
  5. Rollback : kubectl rollout undo pour revenir en arrière
  6. Pause/Resume : appliquer plusieurs changements en un seul rollout
  7. L'ancien ReplicaSet est conservé, revisionHistoryLimit contrôle combien
  8. Pour du stateful, utilisez StatefulSet, pas Deployment

Ces questions reviennent régulièrement quand on débute avec les Deployments Kubernetes. Les réponses ci-dessous synthétisent les points développés dans ce guide, différence avec un Pod, mise à jour, rollback, choix du nombre de replicas.

Ce lab porte sur la vie d'un Deployment après sa première livraison. Il vous fait revenir sur la révision qui marchait puis livrer la bonne image, et la validation lit les ReplicaSets avec leurs numéros de révision : ils racontent ce qui s'est passé, là où un Deployment recréé de zéro ne raconte rien.

Décliner ce Deployment en plusieurs environnements sans le dupliquer relève de Kustomize, qui porte son propre lab.

La livraison complète d'une application, donnée comme un cahier des charges et non comme un mode d'emploi, est le capstone des exercices CKAD.

  • Les Services : L'adresse stable qui rend joignables les Pods créés par votre Deployment.
  • Rolling Updates et Rollbacks : Le détail des paramètres maxSurge et maxUnavailable pendant une mise à jour.
  • Les StatefulSets : Le contrôleur à choisir quand vos Pods ont besoin d'une identité et d'un disque stables.
  • Horizontal Pod Autoscaler : L'ajustement automatique du nombre de réplicas selon la charge mesurée.

Ce site vous est utile ?

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

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. 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