kubectl apply vs set : Choisir la bonne commande pour les mises à jour de ressources

Comprenez quand utiliser kubectl apply, set et edit sans créer de dérive entre les objets Kubernetes en direct et Git.

kubectl apply vs set : Choisir la bonne commande pour les mises à jour de ressources

La différence entre kubectl apply et kubectl set n'est pas seulement une question de syntaxe. C'est la différence entre la gestion de Kubernetes à partir d'une source de vérité déclarée et la modification directe d'objets en direct. Les deux sont utiles. Les deux peuvent vous nuire si vous les utilisez au mauvais endroit.

Utilisez kubectl apply lorsque la modification doit devenir l'état souhaité du système. Utilisez kubectl set lorsque vous avez besoin d'une modification ciblée en direct, généralement temporaire ou urgente. Utilisez kubectl edit lorsque vous devez inspecter et corriger un objet en direct de manière interactive, mais comprenez que c'est le moyen le plus simple de créer une dérive par rapport à Git.

Un objet Kubernetes a un état souhaité stocké dans le serveur API. Un Deployment indique combien de répliques doivent exister, quelle image doit s'exécuter, quelles étiquettes identifient les pods, quelles ressources sont demandées, etc. Les contrôleurs travaillent pour faire correspondre la réalité à cet état souhaité. Votre commande de mise à jour modifie l'état souhaité ; les contrôleurs font le reste.

Avec kubectl apply, vous conservez cet état souhaité dans des fichiers YAML ou JSON. Le fichier est la chose que vous examinez, validez, promouvez et annulez. Une commande typique est simple :

kubectl apply -f deployment.yaml

Si l'objet n'existe pas, Kubernetes le crée. S'il existe, Kubernetes le met à jour pour correspondre au manifeste. Appliquer le même fichier à nouveau ne devrait pas provoquer un nouveau changement de comportement. Cette idempotence est l'une des raisons pour lesquelles apply fonctionne bien dans les workflows CI/CD et GitOps.

kubectl apply côté client utilisait historiquement une annotation de dernière application pour calculer les modifications. L'application côté serveur, activée avec --server-side, suit la propriété des champs via des champs gérés dans le serveur API. Les détails diffèrent, mais l'idée opérationnelle est la même : une configuration déclarée possède l'état souhaité.

Voici un petit manifeste de Deployment :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Si vous modifiez l'image dans le fichier et exécutez kubectl apply -f deployment.yaml, le Deployment se met à jour. Si le fichier est dans Git, la modification peut être examinée. Si le déploiement échoue, vous pouvez annuler le commit ou utiliser l'historique des déploiements Kubernetes selon la façon dont votre processus de déploiement enregistre les révisions.

kubectl set fonctionne différemment. Il modifie un champ spécifique sur un objet en direct. L'exemple courant est le changement d'une image de conteneur :

kubectl set image deployment/web nginx=nginx:1.26

Cette commande est rapide et lisible. Lors d'un incident, la vitesse compte. Si l'image actuelle est cassée et que vous devez déplacer un Deployment vers une image connue comme bonne, kubectl set image peut être le chemin le plus rapide. Le danger est ce qui se passe ensuite. Si deployment.yaml indique toujours nginx:1.25, le prochain kubectl apply -f deployment.yaml peut ramener la charge de travail à 1.25.

Ce décalage est une dérive de configuration. Le cluster en direct dit une chose. Le fichier source en dit une autre. La dérive n'est pas toujours catastrophique, mais elle rend le débogage plus difficile car les gens cessent de faire confiance au dépôt. Quelqu'un demande : "Qu'est-ce qui tourne en production ?" et la réponse honnête devient : "Laissez-moi vérifier le cluster."

kubectl set a plusieurs sous-commandes utiles :

kubectl set image deployment/web nginx=nginx:1.26
kubectl set env deployment/web FEATURE_FLAG=true
kubectl set resources deployment/web -c=nginx --requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi

Celles-ci sont pratiques pour les clusters de développement, les démos, les tests de courte durée et les changements d'urgence en production avec un commit de suivi. Elles ne remplacent pas les manifestes maintenus.

kubectl edit récupère l'objet en direct, l'ouvre dans votre éditeur et renvoie l'objet modifié au serveur API lorsque vous enregistrez :

kubectl edit deployment/web

C'est pratique car vous pouvez voir le YAML en direct complet, y compris les champs ajoutés par les contrôleurs. C'est aussi risqué car les objets en direct contiennent de nombreux champs que vous ne devriez pas gérer manuellement, tels que status, les métadonnées générées, les versions de ressources et les champs gérés. Kubernetes ignorera ou rejettera certaines modifications invalides, mais toutes les mauvaises modifications ne sont pas syntaxiquement invalides.

Une utilisation courante et sûre de kubectl edit est une expérience rapide hors production : augmenter les répliques, modifier une annotation ou tester une valeur de sonde. Une utilisation courante et dangereuse est de modifier manuellement des Deployments de production chaque semaine sans jamais mettre à jour les manifestes. Cela crée un cluster que personne ne peut reconstruire en toute confiance.

La règle pratique est la suivante : si vous voulez que la modification survive au prochain déploiement, mettez-la dans le manifeste et utilisez apply. Si vous avez seulement besoin de modifier l'objet en direct, utilisez set ou edit, puis annulez la modification ou rétroportez-la dans Git.

Il y a quelques cas où les commandes impératives sont non seulement acceptables mais utiles. Pendant le débogage, vous pouvez temporairement ajouter une variable d'environnement qui augmente la verbosité des logs :

kubectl set env deployment/api LOG_LEVEL=debug

Après avoir collecté les logs, supprimez-la :

kubectl set env deployment/api LOG_LEVEL-

Si le paramètre de débogage doit devenir permanent, validez-le dans le manifeste à la place. Ne comptez pas sur la mémoire.

Un autre cas est le rollback d'urgence. Si votre pipeline de déploiement est bloqué et que les clients sont affectés, définir l'image directement peut être raisonnable :

kubectl set image deployment/api api=registry.example.com/api:2026-05-23-good
kubectl rollout status deployment/api

Le suivi doit avoir lieu immédiatement : ouvrez une pull request ou un commit qui fait correspondre le manifeste déclaré à l'état d'urgence, ou exécutez le processus de rollback normal une fois le pipeline sain. Le correctif en direct fait gagner du temps ; il ne devrait pas devenir la nouvelle méthode de déploiement non documentée.

kubectl apply a aussi des pièges. Si vous mélangez plusieurs outils qui gèrent les mêmes champs, vous pouvez obtenir des conflits ou des écrasements surprenants. Par exemple, un contrôleur GitOps, Helm et un humain exécutant kubectl apply contre le même Deployment peuvent tous croire qu'ils possèdent une partie de l'objet. Choisissez une propriété claire. Si Helm gère la ressource, mettez à jour les valeurs Helm et exécutez le processus de release Helm. Si Argo CD ou Flux la gère, modifiez Git et laissez le contrôleur se réconcilier.

Pour les secrets et la configuration, soyez particulièrement prudent. kubectl set env peut mettre des modifications rapides dans un Deployment, mais cela peut exposer des valeurs dans l'historique du shell ou les journaux d'audit. Pour les valeurs sensibles, mettez à jour le Secret via votre processus de gestion des secrets normal. Ne collez pas d'identifiants de production dans une commande ad hoc à moins que votre équipe n'ait explicitement accepté ce workflow.

Avant de modifier un objet en direct, inspectez-le :

kubectl get deployment web -o yaml
kubectl diff -f deployment.yaml

kubectl diff est sous-utilisé. Il montre ce que apply changerait avant que vous ne fassiez le changement. En production, cet aperçu peut détecter des erreurs comme la suppression accidentelle d'un sélecteur d'étiquettes, la suppression d'une limite de ressources ou l'application du manifeste du mauvais environnement.

Pour l'application côté serveur, la commande ressemble à ceci :

kubectl apply --server-side -f deployment.yaml

L'application côté serveur peut être utile lorsque plusieurs acteurs gèrent différents champs, mais elle ne supprime pas le besoin de discipline de propriété. Si deux gestionnaires tentent de posséder le même champ, Kubernetes peut signaler un conflit. C'est une fonctionnalité ; cela vous dit que le workflow est ambigu.

Voici un guide de décision simple que j'utilise dans de vrais clusters. Nouvelle version d'application ? Modifiez le manifeste et utilisez apply via le pipeline. Augmenter les répliques pour un test de charge en staging ? kubectl scale ou kubectl set est acceptable si vous l'annulez. Correction à chaud d'une image cassée en production ? kubectl set image peut être acceptable, mais créez le changement de source de vérité immédiatement. Ajuster les demandes CPU de manière permanente ? Mettez à jour le manifeste. Explorer quels champs existent sur une ressource ? Utilisez kubectl get -o yaml avant d'utiliser edit.

Lorsque les équipes font cela correctement, Kubernetes devient plus facile à raisonner. Le dépôt raconte l'histoire. Le cluster correspond au dépôt la plupart du temps. Les modifications temporaires en direct sont étiquetées comme temporaires et nettoyées. Les incidents sont toujours stressants, mais la configuration ne devient pas un deuxième mystère.

La commande elle-même n'est pas le point. Le point est de savoir si vous pouvez reconstruire l'état du cluster demain à partir de fichiers de confiance. kubectl apply soutient cette habitude. kubectl set et kubectl edit sont des outils tranchants pour les moments où une action directe est utile. Gardez cette limite claire et vous éviterez beaucoup de confusion évitable avec Kubernetes.

Il y a une autre commande que les gens mettent dans le même panier mental : kubectl patch. Elle est aussi impérative, mais elle est meilleure pour les changements scriptés précis que edit. Par exemple, vous pouvez patcher une annotation de Deployment pour déclencher un redémarrage ou mettre à jour un petit champ dans l'automatisation. La même règle de dérive s'applique. Si le champ patché représente un état souhaité à long terme, mettez aussi à jour le manifeste source.

kubectl patch deployment web   -p '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-05-24T10:00:00Z"}}}}}'

Pour les redémarrages, préférez la commande dédiée :

kubectl rollout restart deployment/web

Cette commande modifie toujours l'objet en direct, mais son intention est claire : démarrer un nouveau déploiement à partir du modèle de pod actuel. Ce n'est pas un substitut à la modification de la configuration dans Git.

Dans les environnements GitOps, la limite est encore plus stricte. Si Argo CD ou Flux possède un objet, une commande manuelle kubectl set image peut être automatiquement annulée car le contrôleur voit la dérive et se réconcilie avec Git. Cela peut être surprenant lors d'un incident. Avant de faire un changement manuel en production, sachez si un contrôleur GitOps vous combattra. Parfois, l'action d'urgence correcte est de mettre en pause la réconciliation pour cette application, faire le correctif, puis valider le changement Git correspondant et reprendre la réconciliation.

Vous devriez aussi savoir comment capturer une différence en direct sans valider aveuglément les champs générés. kubectl get deployment web -o yaml inclut le statut, les versions de ressources, les champs gérés et d'autres données qui ne devraient pas aller dans un manifeste propre. Si vous devez rétroporter un correctif à chaud, modifiez le manifeste source à la main ou utilisez un outil comme Kustomize ou les valeurs Helm, puis exécutez kubectl diff pour vérifier le changement prévu. Ne remplacez pas votre fichier source par du YAML en direct brut sauf si vous le nettoyez soigneusement.

Pour les équipes, la politique la plus saine est généralement courte et explicite. Les changements de production passent par Git. Les changements en direct d'urgence sont autorisés si nécessaire, mais ils nécessitent un changement source de suivi ou un rollback. Les clusters de développement sont plus souples, mais tout ce qui est promu au-delà du développement doit être déclaré. Cette politique est plus facile à suivre qu'une longue liste de commandes interdites.

Il y a aussi un côté humain à cela. Lors d'une panne, la personne ayant accès au cluster peut faire la correction la plus rapide possible. C'est acceptable lorsque l'équipe traite cela comme une exception d'urgence. Cela devient dangereux lorsque ces exceptions deviennent des opérations normales. Si la production est régulièrement corrigée à la main, le processus de déploiement est soit trop lent, trop fragile, ou pas fiable. Corrigez ce processus plutôt que d'enseigner à tout le monde plus de trucs d'édition en direct.

RBAC peut renforcer le workflow. De nombreuses équipes autorisent un accès large à kubectl en développement mais restreignent les écritures en production aux systèmes CI/CD, aux contrôleurs GitOps ou à un petit groupe d'astreinte. Ce n'est pas de la bureaucratie pour le plaisir. Cela réduit le nombre de chemins qui peuvent modifier l'état souhaité. Quand quelque chose change, les journaux d'audit et l'historique Git sont plus faciles à suivre.

Pour l'apprentissage, il vaut toujours la peine de pratiquer les trois commandes dans un namespace jetable. Créez un Deployment avec apply, changez son image avec set, inspectez la dérive avec kubectl diff, puis mettez à jour le manifeste et appliquez à nouveau. Voir la dérive se produire une fois dans un environnement sûr rend la règle de production beaucoup plus facile à retenir.