
kubectl create crée une ressource Kubernetes en une commande, kubectl apply déploie et met à jour des ressources à partir de fichiers YAML versionnés. La différence fondamentale : create échoue si la ressource existe déjà, apply la met à jour intelligemment. Ce guide vous apprend à utiliser les deux commandes, à choisir la bonne approche selon le contexte, et à adopter un workflow sûr pour vos déploiements.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À la fin de ce guide, vous saurez :
- Distinguer l'approche impérative (
create) de l'approche déclarative (apply) et choisir selon le contexte - Créer des ressources rapidement avec
kubectl create(deployments, services, configmaps, secrets, namespaces) - Déployer et mettre à jour des ressources avec
kubectl applysans écraser les modifications manuelles - Valider avant d'appliquer avec
--dry-runetkubectl diff - Gérer des manifests multi-fichiers : dossiers, récursif, kustomize, URLs
- Éviter les erreurs courantes : conflits, ressources orphelines, YAML invalide
Impératif vs déclaratif : deux façons de gérer Kubernetes
Section intitulée « Impératif vs déclaratif : deux façons de gérer Kubernetes »Avant de plonger dans les commandes, il est essentiel de comprendre les deux approches de gestion des ressources.
Approche impérative : « fais cette action maintenant »
Section intitulée « Approche impérative : « fais cette action maintenant » »Vous dites à Kubernetes quoi faire, action par action. Chaque commande produit un appel à l'API et modifie le cluster immédiatement, sans qu'aucun fichier ne conserve la trace de l'intention :
# « Crée un deployment nginx avec 3 réplicas »kubectl create deployment nginx --image=nginx --replicas=3
# « Expose-le sur le port 80 »kubectl expose deployment nginx --port=80 --type=ClusterIPAvantages : rapide pour du prototypage, des tests ou des opérations ponctuelles.
Limites : aucune trace de ce qui a été fait. Si vous voulez reproduire l'action sur un autre cluster, vous devez vous souvenir des commandes.
Approche déclarative : « voici l'état souhaité »
Section intitulée « Approche déclarative : « voici l'état souhaité » »Vous décrivez dans un fichier YAML l'état final que vous voulez, et Kubernetes se charge d'y arriver :
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx labels: app: nginxspec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 80kubectl apply -f deployment-nginx.yamlAvantages : reproductible, versionnable dans Git, traçable, idéal pour le CI/CD.
Limites : nécessite d'écrire des fichiers YAML (plus de code initial).
Tableau de décision
Section intitulée « Tableau de décision »Le critère de tri tient en une question : ce que vous créez doit-il survivre à
la session en cours ? Si oui, la ressource a vocation à être décrite dans un
fichier versionné. Si non, l'impératif est plus court et personne ne perd rien.
La dernière ligne du tableau est la plus utile au quotidien : elle combine les
deux approches, avec create comme générateur et apply comme moyen de
déploiement.
| Situation | Approche recommandée | Pourquoi |
|---|---|---|
| Test rapide en développement | kubectl create (impératif) | Pas besoin de traçabilité |
| Déploiement en production | kubectl apply -f (déclaratif) | Versionné, reproductible |
| Pipeline CI/CD | kubectl apply -f (déclaratif) | Automatisable, idempotent |
| Créer un namespace ponctuel | kubectl create (impératif) | Action unique et simple |
| Modifier un deployment existant | kubectl apply -f (déclaratif) | Préserve les modifications |
| Générer un squelette YAML | kubectl create --dry-run=client -o yaml | Gain de temps sur l'écriture |
kubectl create : créer des ressources en mode impératif
Section intitulée « kubectl create : créer des ressources en mode impératif »La commande kubectl create crée une nouvelle ressource. Si la ressource existe déjà, elle échoue avec l'erreur AlreadyExists.
Syntaxe de base
Section intitulée « Syntaxe de base »create accepte deux formes qui n'ont pas le même pouvoir. La forme
kubectl create <type> <nom> ne fonctionne que pour une liste restreinte de
types connus du client : deployment, service, configmap, secret, namespace,
job, cronjob, role, serviceaccount et quelques autres. Tout le reste, à commencer
par les ressources personnalisées apportées par un opérateur, passe
obligatoirement par un fichier avec -f.
kubectl create <type> <nom> [options]# ou depuis un fichierkubectl create -f <fichier.yaml>Créer les ressources les plus courantes
Section intitulée « Créer les ressources les plus courantes »Chaque onglet ci-dessous couvre un type de ressource, avec sa commande minimale
puis ses variantes utiles. Deux détails à surveiller dans tous les cas : le
namespace de destination, qui est celui du contexte courant si vous ne passez
pas -n, et le fait que ces commandes créent des objets sans limites de
ressources ni sonde de santé. Ce qui sort de create est un point de départ à
compléter, pas un objet prêt pour la production.
Crée un deployment (un pod managé avec rolling updates) :
# Syntaxe minimalekubectl create deployment mon-app --image=nginx:1.27
# Avec réplicas et portkubectl create deployment mon-app --image=nginx:1.27 --replicas=3 --port=80Vérification :
kubectl get deployment mon-app# NAME READY UP-TO-DATE AVAILABLE AGE# mon-app 3/3 3 3 12sCrée un service pour exposer un deployment :
# ClusterIP (interne au cluster)kubectl create service clusterip mon-service --tcp=80:80
# NodePort (accessible depuis l'extérieur)kubectl create service nodeport mon-service --tcp=80:80 --node-port=30080Stocke de la configuration non confidentielle :
# Depuis des valeurs littéraleskubectl create configmap app-config \ --from-literal=DB_HOST=postgres.default.svc \ --from-literal=DB_PORT=5432
# Depuis un fichierkubectl create configmap nginx-conf --from-file=nginx.conf
# Depuis un dossier entierkubectl create configmap app-configs --from-file=configs/Vérification :
kubectl get configmap app-config -o yamlStocke des données sensibles (encodées en base64) :
# Depuis des valeurs littéraleskubectl create secret generic db-credentials \ --from-literal=username=admin \ --from-literal=password=S3cur3P@ss
# Depuis un fichier (ex: certificat TLS)kubectl create secret tls mon-tls \ --cert=tls.crt --key=tls.key
# Secret de type docker-registry (pour puller des images privées)kubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=deploy \ --docker-password=token123Le namespace isole un ensemble de ressources, le Job exécute une tâche qui
se termine et le CronJob la replanifie. Tout ce qui suit le -- est la
commande du conteneur, pas une commande shell : les redirections, les tubes
et les variables sont interprétés par votre terminal local, jamais dans le pod.
Pour rediriger une sortie à l'intérieur du conteneur, il faut passer
explicitement par un shell.
# Créer un namespacekubectl create namespace staging
# Créer un job ponctuel : le shell du conteneur gère la redirectionkubectl create job backup-db --image=postgres:16 \ -- sh -c 'pg_dump -h postgres -U admin mydb > /backup/dump.sql'
# Créer un cronjobkubectl create cronjob backup-daily --image=postgres:16 \ --schedule="0 2 * * *" \ -- pg_dump -h postgres -U admin mydbAstuce : générer un squelette YAML avec --dry-run
Section intitulée « Astuce : générer un squelette YAML avec --dry-run »L'option --dry-run=client -o yaml transforme n'importe quelle commande create en générateur de manifest YAML, sans rien créer dans le cluster. C'est la façon la plus rapide de produire un fichier de base :
# Générer le YAML d'un deploymentkubectl create deployment mon-app --image=nginx:1.27 --replicas=3 \ --dry-run=client -o yaml > deployment-mon-app.yaml
# Générer le YAML d'un servicekubectl create service clusterip mon-service --tcp=80:80 \ --dry-run=client -o yaml > service-mon-service.yaml
# Générer le YAML d'un secretkubectl create secret generic db-creds \ --from-literal=password=secret \ --dry-run=client -o yaml > secret-db-creds.yamlÉditez ensuite le fichier généré pour ajouter labels, annotations, resource limits, et appliquez-le avec kubectl apply -f.
kubectl apply : l'approche déclarative
Section intitulée « kubectl apply : l'approche déclarative »kubectl apply est la commande de référence pour les déploiements en conditions réelles. Elle crée la ressource si elle n'existe pas, ou la met à jour si elle existe déjà, en fusionnant intelligemment les modifications.
Comment fonctionne la fusion (3-way merge)
Section intitulée « Comment fonctionne la fusion (3-way merge) »Quand vous exécutez kubectl apply, Kubernetes compare trois versions de la ressource :
- Le fichier local (votre YAML)
- L'annotation last-applied (stockée par le dernier
apply) - L'état actif dans le cluster (modifications manuelles comprises)
Cette comparaison en 3 points (appelée 3-way merge) permet à apply de :
- Ajouter les champs présents dans votre fichier mais absents du cluster
- Modifier les champs dont la valeur a changé dans votre fichier
- Conserver les champs modifiés manuellement dans le cluster mais absents de votre fichier (ex: réplicas ajustés par un HPA)
Appliquer un fichier
Section intitulée « Appliquer un fichier »La même commande sert à la création et à la mise à jour : c'est ce qui rend
apply idempotent et utilisable dans un pipeline sans condition. Regardez le
mot final de la sortie, il vous dit ce qui s'est réellement passé : created,
configured ou unchanged. Un -n sur la ligne de commande ne l'emporte pas
sur un namespace: écrit dans le fichier : si les deux divergent, kubectl
refuse l'opération.
# Créer ou mettre à jour une ressourcekubectl apply -f deployment.yaml
# Appliquer dans un namespace spécifiquekubectl apply -f deployment.yaml -n stagingAppliquer un dossier complet
Section intitulée « Appliquer un dossier complet »Sans -R, kubectl ne descend pas dans les sous-dossiers : c'est la cause
la plus fréquente d'un déploiement partiel qui ne remonte aucune erreur. L'ordre
de traitement suit l'ordre alphabétique des noms de fichiers, ce qui ne
correspond pas forcément aux dépendances. Nommer les fichiers avec un préfixe
numérique reste le moyen le plus simple de garantir qu'un namespace ou une
CustomResourceDefinition soit créé avant ce qui en dépend.
# Tous les fichiers YAML d'un dossier (non récursif)kubectl apply -f manifests/
# Récursif (tous les sous-dossiers)kubectl apply -f manifests/ -R
# Plusieurs fichiers à la foiskubectl apply -f deployment.yaml -f service.yaml -f configmap.yamlAppliquer depuis une URL
Section intitulée « Appliquer depuis une URL »Les procédures d'installation d'outils Kubernetes proposent presque toutes cette
commande. Elle fonctionne, mais elle exécute dans votre cluster un manifest dont
le contenu peut changer entre deux lectures : pointer vers main revient à faire
confiance à l'état du dépôt au moment exact de l'appel. Préférez une URL
figée sur un tag ou un commit, et gardez à l'esprit qu'un manifest peut créer
des ClusterRole avec des droits étendus sur tout le cluster.
# Depuis un dépôt Git (raw)kubectl apply -f https://raw.githubusercontent.com/org/repo/main/deploy.yamlAppliquer avec Kustomize
Section intitulée « Appliquer avec Kustomize »Kustomize est intégré nativement à kubectl. Il permet de personnaliser des manifests sans les modifier directement :
# Appliquer un projet kustomizekubectl apply -k ./overlay/production/
# Prévisualiser ce que kustomize va générerkubectl kustomize ./overlay/production/Structure typique d'un projet kustomize :
├── base/│ ├── deployment.yaml│ ├── service.yaml│ └── kustomization.yaml└── overlay/ ├── staging/ │ └── kustomization.yaml └── production/ └── kustomization.yamlServer-side apply (SSA)
Section intitulée « Server-side apply (SSA) »Depuis Kubernetes 1.22, le server-side apply délègue la fusion au serveur API plutôt qu'au client. C'est l'approche recommandée pour les contrôleurs et les outils qui gèrent des champs partagés :
kubectl apply -f deployment.yaml --server-side
# Forcer l'adoption des champs en conflitkubectl apply -f deployment.yaml --server-side --force-conflictsLe SSA utilise un système de field managers : chaque outil ou utilisateur qui modifie un champ est identifié, ce qui évite les écrasements involontaires entre outils.
Workflow complet : du manifest au cluster
Section intitulée « Workflow complet : du manifest au cluster »Voici la procédure recommandée pour appliquer des changements de façon sûre.
-
Écrivez ou modifiez votre manifest YAML
Partez d'un fichier existant ou générez un squelette avec
--dry-run=client -o yaml. Validez la syntaxe YAML dans votre éditeur. -
Validez la structure avec --dry-run
L'option
--dry-run=serverenvoie le manifest au serveur API pour validation sans l'appliquer :Fenêtre de terminal kubectl apply -f deployment.yaml --dry-run=server# deployment.apps/mon-app created (server dry run)Si le YAML est invalide ou le type de ressource inconnu, l'erreur apparaît ici.
-
Comparez avec l'état actuel via kubectl diff
kubectl diffcompare votre fichier local à l'état du cluster et affiche le résultat au format diff unifié. La sortie contient aussi des champs gérés par Kubernetes, commegeneration, qu'il ne faut pas confondre avec vos propres changements :Fenêtre de terminal kubectl diff -f deployment.yamlExemple de sortie :
replicas: 2replicas: 3image: nginx:1.26image: nginx:1.27Relisez attentivement les changements avant de continuer.
-
Appliquez les changements
Fenêtre de terminal kubectl apply -f deployment.yaml# deployment.apps/mon-app configuredTrois réponses possibles :
Sortie Signification createdRessource créée (n'existait pas) configuredRessource mise à jour unchangedAucun changement détecté -
Vérifiez le résultat
Fenêtre de terminal # L'état de la ressourcekubectl get deployment mon-app# Le détail (events, conditions)kubectl describe deployment mon-app# Le rollout (pour les deployments)kubectl rollout status deployment/mon-appSi le déploiement échoue, consultez le guide Diagnostiquer avec kubectl.
Gérer les manifests en pratique
Section intitulée « Gérer les manifests en pratique »Organiser ses fichiers
Section intitulée « Organiser ses fichiers »Une organisation claire facilite la maintenance et le travail en équipe :
k8s/├── base/ # Ressources communes│ ├── namespace.yaml│ ├── configmap.yaml│ └── networkpolicy.yaml├── apps/│ ├── frontend/│ │ ├── deployment.yaml│ │ ├── service.yaml│ │ └── ingress.yaml│ └── backend/│ ├── deployment.yaml│ ├── service.yaml│ └── secret.yaml└── monitoring/ ├── prometheus/ └── grafana/# Déployer tout le projetkubectl apply -f k8s/ -R
# Déployer seulement le backendkubectl apply -f k8s/apps/backend/Supprimer les ressources gérées
Section intitulée « Supprimer les ressources gérées »Pour supprimer les ressources créées par un fichier ou un dossier :
# Supprimer tout ce qui a été créé par le fichierkubectl delete -f deployment.yaml
# Supprimer tout le contenu d'un dossierkubectl delete -f k8s/apps/backend/Piping et stdin
Section intitulée « Piping et stdin »Vous pouvez chaîner des commandes pour des workflows avancés :
# Appliquer la sortie de kustomizekubectl kustomize ./overlay/prod/ | kubectl apply -f -
# Appliquer un manifest généré dynamiquementcat <<EOF | kubectl apply -f -apiVersion: v1kind: ConfigMapmetadata: name: dynamic-config namespace: defaultdata: APP_VERSION: "2.1.0" DEPLOY_DATE: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"EOFBonnes pratiques
Section intitulée « Bonnes pratiques »Ces règles ne sont pas des préférences de style : chacune ferme un incident déjà vu en production. Les deux premières concernent la traçabilité de ce que vous déployez, les deux suivantes la validation avant impact, les dernières l'hygiène de vos objets. Si vous n'en retenez qu'une, gardez la validation côté serveur : c'est la seule qui confronte votre manifest aux CRD et aux quotas réellement présents dans le cluster.
- Versionnez vos manifests dans Git, ne déployez jamais un YAML écrit à la volée en production.
- Utilisez
--dry-run=serveravant chaqueapply, la validation côté serveur détecte les erreurs que le client ne voit pas (CRD manquants, quotas dépassés). - Exécutez
kubectl diffsystématiquement, comprenez exactement ce qui va changer avant d'appliquer. - Ajoutez des labels à toutes vos ressources,
app,env,versionau minimum. Cela facilite le filtrage et le nettoyage. Voir le guide labels et annotations. - Un namespace par environnement, séparez
dev,stagingetproductionpour limiter les erreurs de déploiement. - Préférez
applyàcreatedès que la ressource peut évoluer,applyest idempotent (vous pouvez le relancer sans risque),createéchoue si la ressource existe. - En CI/CD, appliquez toujours depuis un fichier, jamais de commandes impératives dans un pipeline automatisé.
Dépannage
Section intitulée « Dépannage »Les messages de kubectl sont préfixés par leur origine, et c'est l'indice le
plus utile pour trier. Un message commençant par Error from server vient de
l'API Kubernetes : votre fichier est syntaxiquement correct mais le cluster
le refuse, souvent pour une question de RBAC, de quota ou de ressource
inconnue. Un message commençant par error: sans préfixe vient du client :
le problème est dans le fichier ou la ligne de commande, et le cluster n'a rien
reçu.
| Symptôme | Cause probable | Solution |
|---|---|---|
error: resource already exists | Ressource créée avec create, déjà présente | Utilisez kubectl apply à la place |
error: the object has been modified | Conflit de version (quelqu'un a modifié entre-temps) | Refaites kubectl apply (il re-fusionnera) |
Warning: resource is missing the kubectl.kubernetes.io/last-applied-configuration annotation | Ressource créée avec create puis mise à jour avec apply | Normal au premier apply, l'annotation sera ajoutée |
error: unable to recognize "fichier.yaml" | apiVersion ou kind incorrect/manquant | Vérifiez apiVersion et kind dans le fichier |
error: no matches for kind "X" in version "Y" | CRD non installé ou version API dépréciée | Installez le CRD ou mettez à jour l'apiVersion |
The Deployment is invalid: spec.selector | Le sélecteur ne correspond pas aux labels du template | Les labels du selector.matchLabels doivent correspondre exactement au template.metadata.labels |
forbidden: User cannot create resource | Permissions RBAC insuffisantes | Vérifiez avec kubectl auth can-i create deployments |
kubectl diff retourne une erreur sans diff | Le KUBECONFIG n'est pas configuré ou le cluster est injoignable | Vérifiez votre contexte avec kubectl config current-context |
À retenir
Section intitulée « À retenir »kubectl createcrée une ressource, si elle existe déjà, la commande échoue. Idéal pour les tests rapides et la génération de squelettes YAML.kubectl applycrée ou met à jour une ressource de façon déclarative, c'est la commande de référence pour la production et le CI/CD.- Le 3-way merge de
applypréserve les modifications manuelles et ne touche qu'aux champs que vous avez changés. --dry-run=client -o yamlest le moyen le plus rapide de générer un manifest YAML sans écrire une ligne.- Le workflow sûr : écrire → dry-run → diff → apply → vérifier.
- Les manifests versionnés dans Git sont la norme en production : reproductibilité, traçabilité, revue par les pairs.