PerfectScalePerfectScale

PerfectScale

kubectl rollout : gérer, restaurer et redémarrer vos déploiements

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

Tania Duggal
By Tania Duggal
Sep 7, 202611 min read

kubectl rollout est la commande qui vous permet de contrôler et d'inspecter la manière dont Kubernetes déploie les modifications apportées à un workload. Lorsque vous modifiez un Deployment, Kubernetes remplace les anciens pods par de nouveaux, et kubectl rollout vous permet de suivre ce processus, de le mettre en pause, de l'annuler, de le redémarrer et d'en consulter l'historique.

Dans ce guide, vous découvrirez comment Kubernetes exécute réellement un rollout en coulisses, chaque sous-commande de kubectl rollout avec des exemples, pourquoi les rollouts se bloquent et comment les diagnostiquer, ainsi que les pratiques qui rendent les rollouts sûrs en production.

Qu'est-ce que kubectl rollout ?

kubectl rollout est un ensemble de commandes permettant de gérer le rollout d'un workload après une modification. Un rollout est le processus de remplacement des pods exécutant l'ancienne version par des pods exécutant la nouvelle. La commande ne modifie pas votre workload en soi. Elle vous permet plutôt d'observer et de contrôler le rollout déclenché par une modification : vérifier s'il est terminé, examiner ce qui a changé, l'annuler, le mettre en pause et le reprendre, ou redémarrer les pods.

Elle fonctionne avec les workloads qui gèrent les rollouts pour vous, à savoir les Deployments, StatefulSets et DaemonSets. La majeure partie de ce guide utilise un Deployment, car c'est là que les rollouts sont les plus courants.

Comment Kubernetes exécute-t-il réellement un rollout ?

Lorsque vous modifiez le template de pods d'un Deployment, Kubernetes ne modifie pas les pods en cours d'exécution. Il crée un nouveau ReplicaSet pour la nouvelle version et déplace progressivement les pods de l'ancien ReplicaSet vers le nouveau. Chaque ReplicaSet, et chaque pod qu'il possède, porte un label pod-template-hash, un hash du template de pods. C'est grâce à ce label que Kubernetes distingue les versions et rattache chaque pod au bon ReplicaSet. Lorsque vous effectuez un rollback plus tard, Kubernetes ne fait en réalité que remonter en charge un ancien ReplicaSet.

L'essentiel est de savoir quelles modifications déclenchent réellement un rollout. Seules les modifications du template de pods, le champ .spec.template, créent un nouveau ReplicaSet et une nouvelle révision. Autrement dit, une nouvelle image, une variable d'environnement modifiée ou une request de ressources mise à jour déclenchent toutes un rollout. Une modification du nombre de replicas, en revanche, n'en déclenche pas, car l'augmentation ou la réduction ne fait que redimensionner le ReplicaSet actuel au lieu d'en créer un nouveau. C'est pourquoi le scaling d'un Deployment n'apparaît jamais dans son historique de rollout.

La vitesse du rollout est contrôlée par deux champs de la stratégie de rolling update. Le champ maxSurge définit combien de pods supplémentaires peuvent exister au-delà du nombre souhaité pendant le rollout, avec une valeur par défaut de 25 %, arrondie à l'entier supérieur. Le champ maxUnavailable définit combien de pods peuvent manquer en dessous du nombre souhaité pendant le rollout, avec une valeur par défaut de 25 %, arrondie à l'entier inférieur. Ensemble, ils déterminent la rapidité avec laquelle Kubernetes remplace les anciens pods par les nouveaux. Définir maxSurge: 1 et maxUnavailable: 0 est un choix sûr et courant, car cela ajoute un nouveau pod avant d'en retirer un ancien et ne descend jamais en dessous de la pleine capacité.

Trois autres paramètres contrôlent la progression du rollout. Un nouveau pod n'est considéré comme disponible qu'une fois sa readiness probe validée : sans une bonne readiness probe, Kubernetes considérera un pod comme prêt avant qu'il ne puisse servir du trafic et passera à la suite trop tôt. Le paramètre minReadySeconds impose au pod, une fois prêt, un délai avant d'être compté comme disponible, ce qui permet de détecter un pod qui valide sa probe puis plante quelques secondes plus tard. Enfin, progressDeadlineSeconds, dont la valeur par défaut est 600 (10 minutes), correspond au temps pendant lequel Kubernetes attend que le rollout progresse avant de marquer le Deployment comme échoué avec ProgressDeadlineExceeded.

media

Les sous-commandes de kubectl rollout et les ressources compatibles

kubectl rollout compte six sous-commandes : status, history, undo, pause, resume et restart. Elles ne s'appliquent pas toutes à chaque workload. Les commandes status, history, undo et restart fonctionnent sur les Deployments, StatefulSets et DaemonSets. Les commandes pause et resume fonctionnent uniquement sur les Deployments, car seul un Deployment dispose d'un rollout pouvant être mis en pause. Les sections ci-dessous détaillent chacune d'elles, à l'aide d'un Deployment nommé api.

kubectl rollout status

kubectl rollout status suit un rollout et vous indique quand il est terminé :

kubectl rollout status deployment/api

Pendant son exécution, la commande affiche la progression et se termine lorsque le rollout est achevé. Vous verrez des lignes comme Waiting for deployment "api" rollout to finish: 2 out of 4 new replicas have been updated... et enfin deployment "api" successfully rolled out. Chaque ligne reflète la montée en charge du nouveau ReplicaSet et la disponibilité progressive des pods.

Par défaut, la commande affiche le flux en continu et attend. Deux flags modifient ce comportement : --timeout évite qu'elle attende indéfiniment, ce qui compte dans un script, et --watch=false lui fait afficher l'état actuel une seule fois puis se terminer au lieu de suivre le flux :

kubectl rollout status deployment/api --timeout=5m
kubectl rollout status deployment/api --watch=false

L'atout majeur de rollout status est son code de sortie. La commande renvoie 0 lorsque le rollout réussit et un code différent de zéro en cas d'échec ou de timeout. Cela la rend précieuse dans les pipelines CI/CD : le pipeline peut attendre la fin du rollout et échouer si le Deployment ne devient pas prêt, au lieu de considérer un kubectl apply réussi comme un déploiement réussi.

kubectl rollout history

kubectl rollout history liste les révisions passées d'un workload, afin de voir ce qui a changé et de choisir celle vers laquelle revenir :

kubectl rollout history deployment/api

La sortie est un tableau de numéros de révision avec une colonne CHANGE-CAUSE. Pour afficher le template de pods complet d'une révision, utilisez --revision :

kubectl rollout history deployment/api --revision=2

La colonne CHANGE-CAUSE n'est renseignée que si vous définissez l'annotation kubernetes.io/change-cause. L'ancien flag --record qui la remplissait est déprécié ; la méthode actuelle consiste donc à définir vous-même l'annotation après une modification :

kubectl annotate deployment/api kubernetes.io/change-cause="update image to api:1.4.0"

Sans cette annotation, la colonne affiche <none>, ce qui rend plus difficile de savoir ce qui a changé dans chaque révision.

La profondeur de rollback possible dépend de revisionHistoryLimit, dont la valeur par défaut est 10. Kubernetes conserve ce nombre d'anciens ReplicaSets et supprime les plus anciens. Si la limite est trop basse, la révision vers laquelle vous souhaitez revenir peut ne plus exister.

kubectl rollout undo

kubectl rollout undo effectue le rollback d'un workload. Sans argument, la commande revient à la révision précédente ; avec --to-revision, elle revient à une révision précise de l'historique :

kubectl rollout undo deployment/api
kubectl rollout undo deployment/api --to-revision=2

Cela fonctionne parce que Kubernetes dispose toujours de l'ancien ReplicaSet et le remonte simplement en charge. Un rollback est lui-même un rollout : faites-le suivre d'un rollout status pour confirmer qu'il est terminé.

Une limite importante : undo ne restaure que le template de pods. Cela inclut l'image du conteneur, les variables d'environnement et les paramètres de ressources. La commande n'annule pas les modifications effectuées en dehors du template de pods. Par exemple, si la release a également modifié un ConfigMap, un Secret, un schéma de base de données ou un système externe, le rollback du Deployment n'annule pas ces changements.

Pour cette raison, considérez rollout undo comme un outil de récupération rapide, et non comme votre stratégie de déploiement habituelle. Il peut restaurer rapidement une version précédente des pods, mais ne peut pas annuler tout ce qui a pu changer au cours d'une release.

kubectl rollout restart

kubectl rollout restart redémarre tous les pods d'un workload sans changer l'image :

kubectl rollout restart deployment/api

La commande ajoute au template de pods une annotation kubectl.kubernetes.io/restartedAt avec l'horodatage actuel ; comme cela modifie le template de pods, Kubernetes le traite comme un rollout normal. Il crée un nouveau ReplicaSet et remplace progressivement les anciens pods, en respectant maxSurge, maxUnavailable et les readiness probes. Avec des probes correctement configurées, l'application peut ainsi redémarrer sans interruption de service.

Un cas d'usage courant consiste à prendre en compte des changements qui ne redémarrent pas automatiquement les pods. Par exemple, lorsque vous mettez à jour un ConfigMap ou un Secret que l'application ne lit qu'au démarrage, les pods existants continuent d'utiliser les anciennes valeurs. Un rollout restart remplace ces pods afin qu'ils démarrent avec les nouvelles valeurs.

Un rollout restart est plus maîtrisé que la suppression manuelle des pods ou la mise à zéro du nombre de replicas d'un Deployment. La suppression manuelle des pods les remplace, mais sans le même processus de rollout contrôlé, et la mise à zéro arrête tous les pods avant d'en démarrer de nouveaux, ce qui provoque une interruption. Un rollout restart remplace les pods progressivement tout en respectant les paramètres de rollout du Deployment.

kubectl rollout pause et resume

kubectl rollout pause empêche un Deployment d'appliquer les modifications, et kubectl rollout resume lui permet de continuer :

kubectl rollout pause deployment/api
kubectl rollout resume deployment/api

Cela s'avère utile dans deux cas. Le premier consiste à regrouper plusieurs modifications en un seul rollout. Si vous mettez d'abord en pause, puis modifiez l'image, les ressources et l'environnement, avant de reprendre, Kubernetes effectue un seul rollout avec toutes les modifications au lieu d'un rollout distinct pour chaque changement :

kubectl rollout pause deployment/api
kubectl set image deployment/api api=api:1.5.0
kubectl set resources deployment/api -c=api --limits=cpu=500m,memory=512Mi
kubectl rollout resume deployment/api

Le second consiste à mettre en pause au milieu d'un rollout pour valider un canary partiel. Vous lancez un rollout en changeant l'image, laissez quelques nouveaux pods démarrer, puis mettez en pause. Une petite partie du trafic passe alors par la nouvelle version pendant que le reste demeure sur l'ancienne, et vous pouvez surveiller ses métriques et ses logs. Si tout semble sain, reprenez pour terminer le rollout ; sinon, effectuez un undo pour revenir en arrière. Gardez à l'esprit qu'un Deployment en pause ne peut pas faire l'objet d'un rollback : reprenez-le avant d'exécuter undo.

Pourquoi les rollouts se bloquent-ils et comment les diagnostiquer ?

Un rollout se bloque lorsque les nouveaux pods ne parviennent pas à devenir disponibles, et le Deployment finit par signaler ProgressDeadlineExceeded. Voici les causes les plus courantes :

a. Capacité insuffisante du cluster pour les pods de surge : un rolling update crée des pods supplémentaires (maxSurge) avant de retirer les anciens ; le rollout a donc besoin de CPU et de mémoire disponibles pour les planifier. Si le cluster n'a plus de place, les pods de surge restent en Pending, et le rollout ne peut pas avancer. Vérifiez avec kubectl get pods et kubectl describe pod sur le pod en attente, et regardez si le Cluster Autoscaler peut ajouter un nœud.

b. Échecs de readiness probe et CrashLoopBackOff : si les nouveaux pods démarrent mais ne valident jamais leur readiness probe, ou plantent et redémarrent en boucle, ils ne sont jamais comptés comme disponibles et le rollout stagne. Consultez les logs du nouveau pod avec kubectl logs et ses événements avec kubectl describe pod. C'est là qu'apparaissent une probe mal configurée ou une nouvelle image défectueuse.

c. OOMKills dus à des requests et limits mémoire sous-dimensionnées : si la nouvelle version a besoin de plus de mémoire que sa limite ne l'autorise, le noyau tue chaque nouveau pod à son démarrage ; le pod affiche alors OOMKilled avec le code de sortie 137 et le rollout ne se termine jamais. Les logs du pod sont généralement vides, car le conteneur a été tué plutôt que d'avoir planté : le signal se trouve dans kubectl describe pod, sous le dernier état.

d. Les PodDisruptionBudgets ne bloquent pas le rollout lui-même : un PodDisruptionBudget ne contraint pas le rolling update d'un Deployment. Les PDB ne limitent pas les rolling updates des workloads, car le rollout remplace les pods directement plutôt que via l'API d'éviction. Ce qu'un PDB contraint, ce sont les évictions volontaires : drains de nœuds, scale-down du Cluster Autoscaler, etc. Un PDB peut donc bloquer un drain de nœud qui se produit en même temps que votre rollout, et un PDB mal configuré (par exemple un minAvailable égal au nombre de replicas) peut bloquer entièrement les drains, mais ce n'est pas lui qui retarde le rollout lui-même.

e. Conflits entre Horizontal Pod Autoscaler et replicas : si un HPA gère les replicas d'un Deployment et que vous codez également replicas en dur dans le manifeste, chaque kubectl apply réinitialise le nombre à la valeur du manifeste jusqu'à ce que le HPA le corrige de nouveau. Cela peut provoquer un scaling déroutant pendant un rollout. La solution consiste à omettre replicas du manifeste pour tout Deployment géré par un HPA.

La plupart de ces problèmes reviennent à une question de dimensionnement des ressources. Des pods de surge qui ne tiennent pas sur le cluster et de nouveaux pods OOMKilled pointent tous deux vers des paramètres de ressources incorrects. C'est là que PerfectScale entre en jeu. Sa plateforme de gouvernance Kubernetes observe la manière dont vos workloads utilisent réellement le CPU et la mémoire et la transforme en recommandations de right-sizing concrètes et automatisées, que vous pouvez appliquer manuellement ou de façon autonome. Avec des requests et des limits conformes à la réalité, vos pods de surge trouvent leur place et vos nouveaux pods disposent de la mémoire nécessaire : les rollouts se terminent proprement au lieu de rester bloqués. Des équipes comme Paramount Pictures et Creditas utilisent PerfectScale pour maintenir l'efficacité de leurs clusters ; vous pouvez créer un compte ou réserver une session technique.

media

Bonnes pratiques pour utiliser kubectl rollout en production

Voici quelques pratiques simples pour garder des rollouts sûrs et fluides en production :

a. Ajustez les requests et limits avant le rollout : vous devez définir des requests et limits de ressources précises avant de lancer un rollout. Cela donne aux pods de surge assez de place pour être planifiés et réduit le risque que les nouveaux pods soient OOMKilled.

b. Vérifiez les métriques et les logs, pas seulement le rollout status : un rollout status réussi signifie seulement que les nouveaux pods sont devenus prêts. Cela ne veut pas dire que l'application fonctionne correctement. Vérifiez les taux d'erreur, la latence et les logs après un rollout, en particulier lorsque vous utilisez un canary en pause.

c. Définissez explicitement progressDeadlineSeconds et --timeout : définissez un progressDeadlineSeconds raisonnable afin que Kubernetes marque comme échoué un Deployment bloqué. Utilisez --timeout avec rollout status pour que votre pipeline cesse d'attendre après un délai défini.

d. Ajoutez une annotation change-cause à chaque modification : définissez kubernetes.io/change-cause lors de vos modifications afin que le rollout history indique clairement ce qui a changé dans chaque révision. Cela facilite le choix de la bonne révision lors d'un rollback.

e. Gardez un revisionHistoryLimit suffisamment élevé pour un rollback en toute sécurité : la valeur par défaut de 10 convient à la plupart des workloads, mais si vous déployez très fréquemment, assurez-vous qu'elle couvre encore les révisions vers lesquelles vous pourriez réellement devoir revenir.

f. Réduisez la zone d'impact en déployant progressivement : évitez d'envoyer une modification risquée vers tous les namespaces ou clusters à la fois. Déployez-la par étapes afin de détecter les problèmes tôt et de vous arrêter avant qu'ils n'affectent tout votre environnement.

g. Passez des commandes manuelles au GitOps et à la livraison progressive : kubectl rollout est utile pour apprendre et gérer les rollouts manuellement. Pour des environnements de production plus vastes, des outils comme Argo CD ou Flux peuvent gérer les déploiements via GitOps, tandis qu'Argo Rollouts ou Flagger peuvent automatiser les déploiements canary et blue-green.