kubectl diff montre ce qu'un apply va changer avant de le lancer ;
kubectl wait bloque jusqu'à ce qu'une ressource atteigne un état précis.
Cette leçon facultative prolonge
kubectl create et apply
pour le cas où ce n'est plus vous qui tapez les commandes, mais un script de
déploiement ou un pipeline CI/CD. Elle couvre les codes de sortie de
diff, les conditions de wait et son délai par défaut, le piège du Job en
échec, et ce que prouve vraiment chaque attente. Vous pouvez passer
directement à la leçon Kustomize et y revenir quand vous automatiserez vos
déploiements.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lire une sortie de
kubectl diffet distinguer vos changements des champs gérés par Kubernetes - Exploiter les codes de sortie de
diff: 0, 1 ou 2 - Attendre une condition avec
kubectl wait, en sachant qu'il abandonne après 30 secondes par défaut - Attendre la fin d'un Job sans rester bloqué quand il échoue
- Choisir entre
kubectl waitetkubectl rollout statuspour un Deployment - Écrire un script
diff,apply, attente qui s'arrête au bon moment
Prérequis
Section intitulée « Prérequis »- La leçon kubectl create et apply :
apply, sa sortie et le 3-way merge - Rolling Updates et Rollbacks :
kubectl rollout status - Des bases de script Bash : code de sortie
$?,if,set -e - Un cluster kind en Kubernetes 1.37 pour rejouer les exemples
Quand utiliser diff, quand utiliser wait ?
Section intitulée « Quand utiliser diff, quand utiliser wait ? »Les deux commandes encadrent un apply et ne se remplacent pas. diff
sert avant, pour décider s'il y a quelque chose à déployer et le relire.
wait sert après, pour que la suite du script ne démarre pas avant que
la ressource soit dans l'état voulu. Un apply réussi dit seulement que l'API a
accepté le manifest, jamais que les Pods tournent.
| Moment | Commande | Ce qu'elle fait |
|---|---|---|
Avant apply | kubectl diff -f manifest.yaml | Affiche l'écart entre le cluster et le fichier |
Après apply | kubectl wait --for=condition=... --timeout=... | Bloque jusqu'à une condition, ou échoue au délai |
Après apply d'un Deployment | kubectl rollout status deployment/... --timeout=... | Bloque jusqu'à la fin du déploiement de la nouvelle version |
kubectl diff : que va changer mon apply ?
Section intitulée « kubectl diff : que va changer mon apply ? »kubectl diff -f demande au serveur API ce que deviendrait l'objet si vous
lanciez apply, par une requête à blanc (dry-run côté serveur), puis
compare ce résultat à l'objet actuel. La sortie est donc toujours du
YAML complet, valeurs par défaut du serveur comprises, présenté au format
diff unifié : - pour ce qui part, + pour ce qui arrive.
Comment lire la sortie ?
Section intitulée « Comment lire la sortie ? »Voici la sortie réelle après avoir changé l'image d'un Deployment dans le
fichier. Deux blocs apparaissent, et un seul vient de vous : le second, sur
l'image. Le premier, generation, est un compteur que Kubernetes
incrémente à chaque modification de la spec ; il sort dans tout diff qui change
quelque chose.
kubectl diff -f api-gateway.yaml@@ -6,7 +6,7 @@ creationTimestamp: "2026-10-13T15:47:33Z"- generation: 1+ generation: 2 labels: app: api-gateway@@ -31,7 +31,7 @@ spec: containers:- - image: nginx:1.30@sha256:9bf97bd7714f5e24c1ccd545ecb9eb5435cb6d109c97cebb15e7e455e0239edb+ - image: nginx:1.29@sha256:1881968aff6f7cdcc4b888c00a11f4ce241ad7ec957e0cb4a9e19e93a3ff87ea imagePullPolicy: IfNotPresent name: nginxSur une ressource qui n'existe pas encore, le diff montre l'objet entier en
lignes +, avec des champs que vous n'avez jamais écrits :
progressDeadlineSeconds, strategy, terminationGracePeriodSeconds. Ce
sont les valeurs par défaut posées par le serveur, et leur présence prouve
que le calcul a bien été fait par l'API, pas par votre poste.
Quels codes de sortie renvoie kubectl diff ?
Section intitulée « Quels codes de sortie renvoie kubectl diff ? »kubectl diff suit la convention de l'utilitaire Unix diff, documentée
dans kubectl diff --help et vérifiée sur un cluster 1.37. C'est ce code, et
non le texte affiché, qu'un script doit lire. Retenez surtout que 1 n'est
pas une erreur : c'est la réponse « il y a des changements ».
| Code | Signification | Cas mesurés |
|---|---|---|
| 0 | Aucune différence | Fichier identique au cluster |
| 1 | Des différences existent | Image modifiée ; ressource pas encore créée |
| 2 (plus de 1) | kubectl ou diff a échoué | kind mal orthographié, fichier absent, droits insuffisants |
Deux conséquences pratiques. Un enchaînement
kubectl diff -f . && kubectl apply -f . fait l'inverse de ce qu'on attend : apply ne part que lorsqu'il
n'y a rien à faire. Et sous set -e, le code 1 arrête le script : il
faut capturer le code explicitement, comme le fait le script complet plus bas.
Comparer un dossier ou un overlay Kustomize
Section intitulée « Comparer un dossier ou un overlay Kustomize »diff accepte les mêmes sources qu'apply : plusieurs -f, un dossier
avec -R pour descendre dans les sous-dossiers, ou un overlay Kustomize
avec -k, que la leçon Kustomize détaille. Le code de sortie porte sur
l'ensemble : il vaut 1 dès qu'un seul objet diffère.
kubectl diff -f ./k8s/prod/ -Rkubectl diff -k ./overlays/production/Changer l'outil d'affichage
Section intitulée « Changer l'outil d'affichage »kubectl diff appelle la commande diff de votre système avec les options
-u -N. La variable KUBECTL_EXTERNAL_DIFF la remplace, options comprises,
par exemple pour afficher des libellés lisibles à la place des chemins
temporaires.
L'outil choisi doit respecter la même convention de codes 0, 1 et 2, sans
quoi votre script se trompera.
export KUBECTL_EXTERNAL_DIFF="diff -u --label cluster --label fichier"kubectl diff -f api-gateway.yamldiff --server-side : quand s'en servir ?
Section intitulée « diff --server-side : quand s'en servir ? »Le calcul passe toujours par le serveur. L'option --server-side
change seulement la façon de fusionner : elle simule un server-side apply
au lieu de l'apply classique. Utilisez-la si vous déployez vous-même avec
kubectl apply --server-side : le diff montre alors exactement ce que ce
mode fera, conflits de field manager compris.
Quels droits faut-il pour un diff ?
Section intitulée « Quels droits faut-il pour un diff ? »Une requête à blanc est autorisée comme une vraie écriture. Un compte qui peut lire un Deployment sans pouvoir le modifier obtient un refus, avec le code 2 :
Error from server (Forbidden): error when patching "api-gateway.yaml": deployments.apps "api-gateway" is forbidden:User "system:serviceaccount:...:lecteur" cannot patch resource "deployments" in API group "apps" ...Le compte d'un pipeline qui lance diff a donc besoin des mêmes verbes
RBAC (les droits d'accès de Kubernetes) qu'apply : get, patch, et
create pour une ressource nouvelle.
kubectl wait : attendre un état précis
Section intitulée « kubectl wait : attendre un état précis »kubectl wait surveille une ou plusieurs ressources et rend la main dès
qu'une condition est remplie, avec le code 0, ou à l'expiration du
délai, avec le code 1. C'est l'outil qui synchronise un script avec ce
qui se passe réellement dans le cluster.
Quel est le délai par défaut de kubectl wait ?
Section intitulée « Quel est le délai par défaut de kubectl wait ? »Sans --timeout, kubectl wait attend 30 secondes, puis échoue :
c'est la valeur affichée par kubectl wait --help en 1.37, et la mesure le
confirme. --timeout=0 vérifie une seule fois sans attendre ; une valeur
négative attend une semaine. Fixez donc toujours le délai vous-même,
adapté à ce que vous attendez : 30 secondes suffisent rarement à un
déploiement qui tire une image.
kubectl wait --for=condition=Ready pod/pod-koerror: timed out waiting for the condition on pods/pod-koQuelles conditions attendre ?
Section intitulée « Quelles conditions attendre ? »Chaque type publie ses conditions dans son status, et --for les
désigne par leur nom. Pour une ressource précise,
kubectl get <type>/<nom> -o yaml montre celles qui existent et leur
valeur du moment. Les CRD des opérateurs publient souvent les leurs, une
condition Ready le plus souvent, et wait les attend de la même façon.
--for= | Sur quoi | Ce que ça attend |
|---|---|---|
condition=Ready | Pod | La readiness probe passe (sans probe : dès le démarrage du conteneur) |
condition=Available | Deployment | Le minimum de réplicas disponibles est atteint |
condition=Complete | Job | Le Job a réussi |
condition=Failed | Job | Le Job a échoué |
delete | Toute ressource | La ressource a disparu |
create | Toute ressource | La ressource apparaît dans l'API |
jsonpath='{...}'=valeur | Toute ressource | Un champ du status vaut la valeur donnée |
Plusieurs --for se combinent par un ET, et create est toujours
attendu en premier. La commande suivante attend qu'un Pod apparaisse, puis qu'il
soit prêt, là où un simple --for=condition=Ready échouerait aussitôt avec
Error from server (NotFound) :
kubectl wait --for=create --for=condition=Ready pod/web-0 --timeout=120sAttendre tous les Pods d'un label
Section intitulée « Attendre tous les Pods d'un label »Avec -l, wait attend que tous les objets sélectionnés remplissent
la condition, et affiche une ligne par objet. Si le sélecteur ne trouve
rien, la commande échoue immédiatement avec le code 1, sans attendre : un
label mal tapé se voit donc tout de suite.
kubectl wait --for=condition=Ready pods -l app=api-gateway --timeout=120serror: no matching resources foundAttendre la fin d'un Job, réussi ou en échec
Section intitulée « Attendre la fin d'un Job, réussi ou en échec »Un Job lance un ou plusieurs Pods jusqu'à ce qu'une tâche se termine,
une migration de base par exemple ; la leçon Jobs et CronJobs le détaille.
--for=condition=Complete n'est rempli que par un Job réussi. Mesuré
sur un Job qui échoue en 3 secondes : --for=condition=Failed répond
aussitôt, mais --for=condition=Complete attend jusqu'au bout du délai
avant de rendre le code 1.
Un script qui veut sortir dès que le Job est fixé, dans un sens ou dans
l'autre, interroge les deux conditions à tour de rôle avec --timeout=0,
qui vérifie sans attendre. La variable Bash SECONDS compte les secondes
écoulées depuis le début du script et sert de délai global :
JOB=job/migration-dbuntil kubectl wait --for=condition=Complete "$JOB" --timeout=0 >/dev/null 2>&1; do if kubectl wait --for=condition=Failed "$JOB" --timeout=0 >/dev/null 2>&1; then echo "Le Job a échoué." >&2 exit 1 fi if [ "$SECONDS" -ge 300 ]; then echo "Délai dépassé." >&2 exit 1 fi sleep 2doneecho "Job terminé avec succès."Rejouée sur deux Jobs, cette boucle a rendu « Job terminé avec succès. » en
9 secondes pour le premier et « Le Job a échoué. », code 1, en 6 secondes
pour le second, au lieu des 300 secondes d'un wait sur Complete seul.
Attendre la valeur d'un champ avec jsonpath
Section intitulée « Attendre la valeur d'un champ avec jsonpath »--for=jsonpath attend qu'un champ quelconque prenne une valeur, ce
qui couvre les ressources sans condition adaptée. La valeur est comparée sous
forme de texte, et un champ absent fait attendre jusqu'au délai : vérifiez
d'abord ce que contient réellement le champ avec kubectl get -o jsonpath.
kubectl wait --for=jsonpath='{.status.succeeded}'=1 job/migration-db --timeout=120skubectl wait --for=jsonpath='{.status.availableReplicas}'=2 deployment/api-gateway --timeout=120sAttention à ce que vous attendez : un Pod dont la sonde échoue est bien en
phase Running, et --for=jsonpath='{.status.phase}'=Running le déclare
prêt aussitôt. Pour savoir si un Pod reçoit du trafic, c'est la condition
Ready qu'il faut attendre.
Attendre une suppression
Section intitulée « Attendre une suppression »--for=delete rend la main quand l'objet a disparu de l'API. Utile
après un kubectl delete --wait=false, ou avant de recréer un objet du même
nom : un Pod met jusqu'à son délai de grâce, 30 secondes par défaut, à
s'arrêter si son processus ignore le signal d'arrêt.
kubectl delete pod api-server --wait=falsekubectl wait --for=delete pod/api-server --timeout=60sPourquoi Available ne prouve pas que la nouvelle version tourne ?
Section intitulée « Pourquoi Available ne prouve pas que la nouvelle version tourne ? »--for=condition=Available sur un Deployment dit seulement que le
minimum de réplicas est disponible, quelle que soit leur version.
Mesuré sur un cluster 1.37 : après un apply qui pose une image
inexistante, wait --for=condition=Available rend « condition met » en
0 seconde, servi par les anciens Pods encore en place. Dans le même temps,
kubectl rollout status attend la nouvelle version et échoue au délai :
Waiting for deployment "api-gateway" rollout to finish: 1 out of 2 new replicas have been updated...error: timed out waiting for the conditionPour valider un déploiement dans un script, utilisez donc
kubectl rollout status --timeout=..., qui suit la nouvelle version. Gardez kubectl wait
pour les Pods, les Jobs, les suppressions et les ressources sans rollout.
Un script de déploiement complet
Section intitulée « Un script de déploiement complet »Ce script assemble la leçon : il décide avec le code de diff,
applique, puis attend la nouvelle version avec rollout status. Il a
été rejoué sur un cluster kind 1.37 dans les quatre cas qui comptent :
première création, relance sans changement, nouvelle image, image cassée,
plus un manifest invalide.
#!/usr/bin/env bashset -euo pipefail
NAMESPACE="${NAMESPACE:-prod}"MANIFESTS="${MANIFESTS:-./k8s/prod/}"DEPLOY="api-gateway"
echo "=== 1. Ce qui va changer ==="rc=0kubectl diff -n "$NAMESPACE" -f "$MANIFESTS" || rc=$?case "$rc" in 0) echo "Aucun changement, rien à déployer."; exit 0 ;; 1) echo "Changements détectés, application." ;; *) echo "kubectl diff a échoué (code $rc)." >&2; exit "$rc" ;;esac
echo "=== 2. Application ==="kubectl apply -n "$NAMESPACE" -f "$MANIFESTS"
echo "=== 3. Attente du déploiement ==="if ! kubectl rollout status "deployment/$DEPLOY" -n "$NAMESPACE" --timeout=180s; then echo "Déploiement non terminé dans le délai." >&2 kubectl get pods -n "$NAMESPACE" -l "app=$DEPLOY" exit 1fiecho "Déploiement terminé."La ligne || rc=$? est le point clé : elle empêche set -e d'arrêter
le script sur le code 1 de diff tout en conservant ce code pour le
case. Avec l'image cassée, le script s'arrête au délai, code 1, et
affiche les Pods : le nouveau en ImagePullBackOff, les deux anciens
toujours Running.
Le même script se lance tel quel dans un job de CI. Il lui faut un accès au
cluster et un compte doté des droits d'apply, et rien d'autre : la sortie
du diff reste dans le journal du job, où un relecteur peut la consulter
avant de valider une étape manuelle.
Dépannage
Section intitulée « Dépannage »Les erreurs se répartissent entre les deux commandes. Côté diff, la surprise
la plus fréquente est un écart sur des champs que vous n'avez jamais
écrits ; côté wait, une attente qui se termine par un délai dépassé. Dans
ce cas, kubectl describe et les événements de la ressource disent
presque toujours pourquoi la condition n'arrive pas.
| Symptôme | Cause probable | Solution |
|---|---|---|
Le script s'arrête juste après kubectl diff | set -e et code 1, qui signifie « changements » | Capturez le code avec || rc=$? |
diff montre generation ou des champs jamais écrits | Compteur et valeurs par défaut posés par le serveur | Normal : lisez seulement les lignes qui viennent de votre fichier |
diff rend 2 avec Forbidden ... cannot patch | Le compte n'a que des droits de lecture | Donnez-lui les verbes get, patch et create |
error: timed out waiting for the condition après 30 s | Pas de --timeout, délai par défaut | Fixez un délai adapté, et lisez kubectl describe |
wait --for=condition=Complete bloque jusqu'au délai | Le Job a échoué | Attendez aussi condition=Failed |
error: no matching resources found | Aucun objet ne porte le label | Vérifiez avec kubectl get pods -l <sélecteur> |
Error from server (NotFound) sur wait | L'objet n'existe pas encore | Ajoutez --for=create |
Available atteint, mais l'ancienne version tourne | Available ignore la version des Pods | Utilisez kubectl rollout status |
À retenir
Section intitulée « À retenir »kubectl diffcalcule le résultat d'unapplypar une requête à blanc au serveur, et l'affiche au format diff unifié.- Ses codes de sortie : 0 rien à faire, 1 changements (ressource nouvelle comprise), 2 ou plus pour une erreur ; sous
set -e, capturez-les avec|| rc=$?. diffexige les mêmes droits qu'apply: une requête à blanc est autorisée comme une écriture.kubectl waitabandonne après 30 secondes par défaut : fixez toujours--timeout.--for=condition=Completen'est rempli que par un Job réussi ; un Job en échec se détecte aveccondition=Failed.- Un sélecteur sans résultat fait échouer
waitimmédiatement ;--for=createattend qu'un objet apparaisse. - Pour un Deployment,
kubectl rollout status --timeoutvalide la nouvelle version ;condition=Availablepeut être servi par les anciens Pods.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Six questions pour vérifier que vous savez lire les codes de sortie de
kubectl diff, régler le délai de kubectl wait, attendre un Job sans rester
bloqué et choisir la bonne attente pour un Deployment.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
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
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Kustomize
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications