Aller au contenu
Conteneurs & Orchestration medium

kubectl create et apply : créer et déployer des ressources Kubernetes

23 min de lecture

logo kubernetes

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.

À 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 apply sans écraser les modifications manuelles
  • Valider avant d'appliquer avec --dry-run et kubectl 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 :

Fenêtre de terminal
# « 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=ClusterIP

Avantages : 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 :

deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
Fenêtre de terminal
kubectl apply -f deployment-nginx.yaml

Avantages : reproductible, versionnable dans Git, traçable, idéal pour le CI/CD.

Limites : nécessite d'écrire des fichiers YAML (plus de code initial).

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.

SituationApproche recommandéePourquoi
Test rapide en développementkubectl create (impératif)Pas besoin de traçabilité
Déploiement en productionkubectl apply -f (déclaratif)Versionné, reproductible
Pipeline CI/CDkubectl apply -f (déclaratif)Automatisable, idempotent
Créer un namespace ponctuelkubectl create (impératif)Action unique et simple
Modifier un deployment existantkubectl apply -f (déclaratif)Préserve les modifications
Générer un squelette YAMLkubectl create --dry-run=client -o yamlGain 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.

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.

Fenêtre de terminal
kubectl create <type> <nom> [options]
# ou depuis un fichier
kubectl create -f <fichier.yaml>

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) :

Fenêtre de terminal
# Syntaxe minimale
kubectl create deployment mon-app --image=nginx:1.27
# Avec réplicas et port
kubectl create deployment mon-app --image=nginx:1.27 --replicas=3 --port=80

Vérification :

Fenêtre de terminal
kubectl get deployment mon-app
# NAME READY UP-TO-DATE AVAILABLE AGE
# mon-app 3/3 3 3 12s

Astuce : 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 :

Fenêtre de terminal
# Générer le YAML d'un deployment
kubectl 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 service
kubectl create service clusterip mon-service --tcp=80:80 \
--dry-run=client -o yaml > service-mon-service.yaml
# Générer le YAML d'un secret
kubectl 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 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.

Quand vous exécutez kubectl apply, Kubernetes compare trois versions de la ressource :

  1. Le fichier local (votre YAML)
  2. L'annotation last-applied (stockée par le dernier apply)
  3. 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)

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.

Fenêtre de terminal
# Créer ou mettre à jour une ressource
kubectl apply -f deployment.yaml
# Appliquer dans un namespace spécifique
kubectl apply -f deployment.yaml -n staging

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.

Fenêtre de terminal
# 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 fois
kubectl apply -f deployment.yaml -f service.yaml -f configmap.yaml

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.

Fenêtre de terminal
# Depuis un dépôt Git (raw)
kubectl apply -f https://raw.githubusercontent.com/org/repo/main/deploy.yaml

Kustomize est intégré nativement à kubectl. Il permet de personnaliser des manifests sans les modifier directement :

Fenêtre de terminal
# Appliquer un projet kustomize
kubectl apply -k ./overlay/production/
# Prévisualiser ce que kustomize va générer
kubectl kustomize ./overlay/production/

Structure typique d'un projet kustomize :

├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
└── overlay/
├── staging/
│ └── kustomization.yaml
└── production/
└── kustomization.yaml

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 :

Fenêtre de terminal
kubectl apply -f deployment.yaml --server-side
# Forcer l'adoption des champs en conflit
kubectl apply -f deployment.yaml --server-side --force-conflicts

Le 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.

Voici la procédure recommandée pour appliquer des changements de façon sûre.

  1. É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.

  2. Validez la structure avec --dry-run

    L'option --dry-run=server envoie 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.

  3. Comparez avec l'état actuel via kubectl diff

    kubectl diff compare 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, comme generation, qu'il ne faut pas confondre avec vos propres changements :

    Fenêtre de terminal
    kubectl diff -f deployment.yaml

    Exemple de sortie :

    replicas: 2
    replicas: 3
    image: nginx:1.26
    image: nginx:1.27

    Relisez attentivement les changements avant de continuer.

  4. Appliquez les changements

    Fenêtre de terminal
    kubectl apply -f deployment.yaml
    # deployment.apps/mon-app configured

    Trois réponses possibles :

    SortieSignification
    createdRessource créée (n'existait pas)
    configuredRessource mise à jour
    unchangedAucun changement détecté
  5. Vérifiez le résultat

    Fenêtre de terminal
    # L'état de la ressource
    kubectl get deployment mon-app
    # Le détail (events, conditions)
    kubectl describe deployment mon-app
    # Le rollout (pour les deployments)
    kubectl rollout status deployment/mon-app

    Si le déploiement échoue, consultez le guide Diagnostiquer avec kubectl.

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/
Fenêtre de terminal
# Déployer tout le projet
kubectl apply -f k8s/ -R
# Déployer seulement le backend
kubectl apply -f k8s/apps/backend/

Pour supprimer les ressources créées par un fichier ou un dossier :

Fenêtre de terminal
# Supprimer tout ce qui a été créé par le fichier
kubectl delete -f deployment.yaml
# Supprimer tout le contenu d'un dossier
kubectl delete -f k8s/apps/backend/

Vous pouvez chaîner des commandes pour des workflows avancés :

Fenêtre de terminal
# Appliquer la sortie de kustomize
kubectl kustomize ./overlay/prod/ | kubectl apply -f -
# Appliquer un manifest généré dynamiquement
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: dynamic-config
namespace: default
data:
APP_VERSION: "2.1.0"
DEPLOY_DATE: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
EOF

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=server avant chaque apply, la validation côté serveur détecte les erreurs que le client ne voit pas (CRD manquants, quotas dépassés).
  • Exécutez kubectl diff systématiquement, comprenez exactement ce qui va changer avant d'appliquer.
  • Ajoutez des labels à toutes vos ressources, app, env, version au minimum. Cela facilite le filtrage et le nettoyage. Voir le guide labels et annotations.
  • Un namespace par environnement, séparez dev, staging et production pour limiter les erreurs de déploiement.
  • Préférez apply à create dès que la ressource peut évoluer, apply est 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é.

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ômeCause probableSolution
error: resource already existsRessource créée avec create, déjà présenteUtilisez kubectl apply à la place
error: the object has been modifiedConflit 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 annotationRessource créée avec create puis mise à jour avec applyNormal au premier apply, l'annotation sera ajoutée
error: unable to recognize "fichier.yaml"apiVersion ou kind incorrect/manquantVé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éeInstallez le CRD ou mettez à jour l'apiVersion
The Deployment is invalid: spec.selectorLe sélecteur ne correspond pas aux labels du templateLes labels du selector.matchLabels doivent correspondre exactement au template.metadata.labels
forbidden: User cannot create resourcePermissions RBAC insuffisantesVérifiez avec kubectl auth can-i create deployments
kubectl diff retourne une erreur sans diffLe KUBECONFIG n'est pas configuré ou le cluster est injoignableVérifiez votre contexte avec kubectl config current-context
  • kubectl create cré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 apply cré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 apply préserve les modifications manuelles et ne touche qu'aux champs que vous avez changés.
  • --dry-run=client -o yaml est 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.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. 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