Aller au contenu
English
English
Conteneurs & Orchestration medium

Kustomize : Factorisez vos manifests Kubernetes

17 min de lecture

logo Kustomize

Ce guide vous permet de gérer plusieurs environnements Kubernetes (dev, staging, prod) sans dupliquer vos fichiers YAML. Vous apprendrez à créer une base commune, appliquer des overlays par environnement, et déployer avec kubectl apply -k. Prérequis : connaître les manifests Kubernetes de base (Deployment, Service).

  • Structurer vos manifests avec une base et des overlays
  • Personnaliser les déploiements sans modifier les fichiers d'origine
  • Utiliser kubectl apply -k et kubectl diff -k au quotidien
  • Éviter les pièges courants (secrets, patches, versions)

Kustomize est un outil natif intégré à Kubectl qui permet de personnaliser des fichiers YAML sans utiliser de templates. Contrairement à Helm, qui repose sur un système de charts avec des valeurs dynamiques, Kustomize utilise des patches et des overlays pour modifier des configurations existantes.

L'idée principale est simple : au lieu de dupliquer des fichiers YAML, on applique des modifications ciblées à une base commune. Cela permet de gérer plusieurs environnements sans complexifier la maintenance des manifests.

La question se pose au moment où la même application doit vivre sur plusieurs environnements. La réponse spontanée consiste à copier le dossier de manifests, et le résultat est toujours le même : au bout de quelques mois, une correction appliquée à la production manque à la recette, et personne ne sait dire ce qui diffère volontairement de ce qui diffère par oubli. Kustomize répond par la composition, ce qui rend l'écart entre deux environnements lisible d'un coup d'œil.

Avec Kustomize, vous pouvez :

  • Éviter la duplication (DRY) des fichiers YAML en réutilisant une base commune.
  • Personnaliser les déploiements en appliquant des overlays spécifiques à chaque environnement.
  • Gérer les secrets et les ConfigMaps sans les inclure directement dans mes manifests.
  • Modifier facilement les images et les labels d’un déploiement Kubernetes.

Voici un tableau comparatif des différences entre Kustomize et Helm :

CritèreKustomizeHelm
ApprochePatch des fichiers YAMLTemplates avec valeurs dynamiques
ComplexitéSimple et natifPlus puissant mais plus complexe
Gestion des dépendancesPas de gestion intégréeSupport des chart dependencies
Utilisation avec kubectlOui (intégré depuis v1.14)Non, nécessite helm
ApprentissageFacile pour débutantsPeut être complexe

Si je veux juste modifier mes manifests existants sans apprendre un nouvel outil, Kustomize est la solution idéale. Pour des déploiements plus avancés avec gestion des dépendances, Helm reste plus adapté.

Kustomize est intégré à kubectl depuis la version 1.14. Vous n'avez donc pas besoin de l'installer séparément.

Pour gérer efficacement les configurations Kubernetes, il est essentiel de comprendre les concepts fondamentaux de Kustomize. Cet outil offre une approche structurée pour personnaliser et déployer des ressources Kubernetes sans dupliquer les fichiers YAML.

Au cœur de Kustomize se trouve le fichier kustomization.yaml. Ce fichier définit comment assembler et personnaliser les ressources Kubernetes. Voici les principaux champs que l'on peut y trouver :

  • resources : liste des fichiers ou répertoires contenant les manifests à inclure.
  • patches : modifications à appliquer aux ressources existantes.
  • configMapGenerator et secretGenerator : pour générer des ConfigMaps et Secrets à partir de fichiers ou de littéraux.
  • labels et annotations : labels et annotations à ajouter à toutes les ressources.

Le bloc labels mérite une précision, parce qu'elle décide du sort du Service. Par défaut il étiquette les objets sans toucher aux selectors ; l'option includeSelectors: true les y pousse aussi. Les deux comportements sont utiles et le mauvais choix est silencieux : un label d'environnement posé sur les Pods mais absent du selector du Service donne un Service qui ne route plus vers rien, sans le moindre événement pour le signaler.

labels:
- pairs:
env: prod
includeSelectors: true

C'est aussi pour cette raison que l'ancien champ commonLabels est déprécié : il modifiait toujours les selectors, y compris ceux d'un Deployment déjà déployé, alors que spec.selector est immuable.

Kustomize utilise une hiérarchie de configurations :

  • Base : ensemble de ressources communes à plusieurs environnements.
  • Overlay : personnalisation spécifique à un environnement (développement, staging, production) qui s'appuie sur une base.

Cette structure permet de réutiliser les configurations et de les adapter selon les besoins sans duplication.

Kustomize propose des outils pour créer et modifier des ressources :

  • Générateurs : créent des ConfigMaps et des Secrets à partir de sources externes.
  • Transformateurs : modifient les ressources existantes, par exemple en ajoutant des labels ou en changeant les noms.

Les patches permettent d'appliquer des modifications ciblées aux ressources.

Nous commençons par un exemple simple pour comprendre comment Kustomize fonctionne. Nous allons créer un deployement et le personnaliser pour deux environnements : dev et prod.

Voici l'arborescence de notre projet :

  • Répertoirekustomize-example/
    • Répertoirebase/
      • kustomization.yaml
      • deployment.yaml
    • Répertoireoverlays/
      • Répertoiredev/
        • kustomization.yaml
        • deployment-patch.yaml
      • Répertoireprod/
        • kustomization.yaml
        • deployment-patch.yaml

Commencer par créer le répertoire base/ dans le dossier de votre projet :

Fenêtre de terminal
mkdir base

Dans ce répertoire, créez le fichier deployment.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:1.31.3@sha256:5a88c9c45479443d7be2eadc894b4ed0a9801bae03d97a5760ae13b5c2005942
ports:
- containerPort: 80

On définit ensuite la configuration de base dans le fichier base/kustomization.yaml :

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml

On déclare la ressource deployment.yaml dans le fichier kustomization.yaml.

Nous allons maintenant définir des overlays pour personnaliser le Namespace selon l’environnement.

Commencez par créer les répertoires dev/ et prod/ dans le dossier overlays/.

Fenêtre de terminal
mkdir -p overlays/{dev,prod}

Créez les fichiers de patch dans chaque répertoire d'overlay.

Le fichier deployment-patch.yaml pour dev (1 réplica + label environnement) :

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
template:
metadata:
labels:
env: dev

Ce patch modifie le nombre de réplicas et ajoute un label env: dev.

Le fichier deployment-patch.yaml pour la prod (3 réplicas + label environnement) :

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
template:
metadata:
labels:
env: prod

On créé ensuite les fichiers kustomization.yaml dans les répertoires dev/ et prod/ pour appliquer les patches :

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: deployment-patch.yaml

Le bon réflexe tient en trois commandes, dans cet ordre :

Avant de déployer, toujours prévisualiser et valider :

  1. kustomize build overlays/dev/ (ou kubectl kustomize overlays/dev/), Voir le YAML généré
  2. kubectl diff -k overlays/dev/, Comparer avec l'existant
  3. kubectl apply -k overlays/dev/, Appliquer

Générez les manifests pour dev :

Fenêtre de terminal
# Avec kubectl intégré
kubectl kustomize overlays/dev/
# Ou avec le binaire standalone
kustomize build overlays/dev/

Résultat produit :

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
env: dev
spec:
containers:
- image: nginx:1.31.3@sha256:5a88c9c45479443d7be2eadc894b4ed0a9801bae03d97a5760ae13b5c2005942
name: my-app
ports:
- containerPort: 80

Pour la prod :

Fenêtre de terminal
kubectl kustomize overlays/prod/

Résultat attendu :

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
env: prod
spec:
containers:
- image: nginx:1.31.3@sha256:5a88c9c45479443d7be2eadc894b4ed0a9801bae03d97a5760ae13b5c2005942
name: my-app
ports:
- containerPort: 80

Le nombre de réplicas et le label env sont différents pour dev et prod.

Appliquer au cluster :

Fenêtre de terminal
# Prévisualiser les différences avec l'existant
kubectl diff -k overlays/dev/
# Appliquer
kubectl apply -k overlays/dev/

Pour gérer les namespaces avec Kustomize, il suffit d'ajouter dans le fichier kustomization.yaml de chaque overlay le champ namespace :

namespace: my-app-dev

Pour le dev et :

namespace: my-app-prod

Pour la prod.

Lançons à nouveau la commande kubectl kustomize overlays/prod/ pour voir le résultat.

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: my-app-prod
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
env: prod
spec:
containers:
- image: nginx:1.31.3@sha256:5a88c9c45479443d7be2eadc894b4ed0a9801bae03d97a5760ae13b5c2005942
name: my-app
ports:
- containerPort: 80

Le namespace my-app-prod est automatiquement injecté dans toutes les ressources de l'overlay.

Kustomize permet de personnaliser les ressources Kubernetes de plusieurs manières sans modifier directement les fichiers YAML d’origine. Ces customisations sont définies dans le fichier kustomization.yaml.

On peut ajouter un préfixe à toutes les ressources définies dans un kustomization.yaml :

namePrefix: dev-

Une ressource Deployment nommée web-app deviendra dev-web-app.

De la même manière, on peut ajouter un suffixe :

nameSuffix: -v1

Une ressource web-app deviendra web-app-v1.

Ajouter une annotation commune (commonAnnotations)

Section intitulée « Ajouter une annotation commune (commonAnnotations) »

Les annotations ne servent pas à sélectionner des objets, contrairement aux labels : elles portent des informations destinées aux humains et aux outils, une référence de ticket, un propriétaire, une date de livraison. Les poser depuis la surcouche évite de les recopier dans chaque manifeste, et garantit qu'aucun objet produit ne les perd en route.

On peut aussi ajouter une annotation :

commonAnnotations:
owner: "admin@company.com"

Toutes les ressources auront cette annotation.

Au lieu d'écrire un fichier YAML à la main, on peut générer une ConfigMap directement :

configMapGenerator:
- name: app-config
literals:
- ENV=production
- LOG_LEVEL=debug

Résultat généré :

apiVersion: v1
data:
ENV: production
LOG_LEVEL: debug
kind: ConfigMap
metadata:
name: app-config-f8269b54dd # Hash ajouté automatiquement

Ce suffixe n'est pas un bruit, c'est le mécanisme lui-même :

Par défaut, Kustomize ajoute un suffixe hash aux ConfigMaps et Secrets générés (ex: app-config-f8269b54dd). C'est intentionnel : quand le contenu change, le nom change aussi, ce qui force un redéploiement des Pods qui l'utilisent.

Pour désactiver ce comportement (déconseillé) :

generatorOptions:
disableNameSuffixHash: true

De la même façon, on peut générer un Secret. Privilégiez les fichiers plutôt que les literals pour éviter de committer des secrets dans Git :

secretGenerator:
- name: db-secret
files:
- secrets/db-password.txt # Fichier dans .gitignore
type: Opaque

Avec secrets/db-password.txt contenant uniquement le mot de passe (sans retour à la ligne final).

Résultat généré :

apiVersion: v1
data:
db-password.txt: c3VwZXJzZWNyZXQxMjM= # Base64
kind: Secret
metadata:
name: db-secret-gcf5mcd8td # Hash ajouté
type: Opaque

Un détail décide du manifeste qui consommera ce Secret : la clé vaut le nom du fichier, db-password.txt dans l'exemple ci-dessus, et non un nom que vous auriez choisi. La syntaxe CLE=chemin la fixe explicitement, ce qui évite de devoir nommer un fichier d'après une variable d'environnement :

files:
- PASSWORD=secrets/db-password.txt # Clé = PASSWORD

Avec images, on remplace le nom, le tag ou le digest d’une image sans modifier le manifeste de base :

images:
- name: nginx
newName: registry.example.net/nginx-durci
newTag: "1.31.3"

Appliqué à la base de ce guide, le rendu devient registry.example.net/nginx-durci:1.31.3. Un détail mérite votre attention, et il se voit dans cette sortie : la base était épinglée par digest, et newTag produit une référence par tag, donc l'épinglage disparaît. Pour le conserver, c'est le champ digest: qu'il faut employer à la place de newTag.

Kustomize est nativement supporté par les outils GitOps :

  • Argo CD : détecte automatiquement les kustomization.yaml et applique les overlays
  • Flux : supporte Kustomize via les Kustomization CRDs

C'est l'une des raisons pour lesquelles Kustomize est populaire en production : il s'intègre sans friction dans un workflow GitOps.

Les deux premières lignes couvrent la quasi-totalité des appels à l'aide sur ce sujet, et elles ont un point commun : le message d'erreur ne nomme jamais Kustomize. Il parle d'un champ immuable ou d'un objet introuvable, parce que le cluster reçoit du YAML sans savoir d'où il vient. Le réflexe utile est donc de lire le rendu avec kubectl kustomize avant de chercher plus loin.

SymptômeCause probableSolution
Patch non appliquéMauvais name dans le patchVérifier que metadata.name correspond à la ressource cible
error: no objects passed to applyresources vide ou mal pointéVérifier le chemin dans resources: [../../base]
ConfigMap/Secret introuvableNom avec hash vs nom fixeLe nom inclut un hash ; utiliser kubectl get configmap pour voir le nom réel
unknown fieldVersion kubectl trop ancienneMettre à jour kubectl ou utiliser le binaire kustomize
Labels non fusionnésPatch partiel mal forméInclure le chemin complet (spec.template.metadata.labels)
Différence kustomize build vs kubectl kustomizeVersions différentesComparer kustomize version et kubectl version
field is immutable sur spec.selectorUn label a été poussé jusque dans les selectors d'un objet déjà déployéSupprimer et recréer l'objet : spec.selector ne se modifie pas après création
Le Service ne route plus vers ses PodsLe label d'environnement est sur les Pods mais pas dans le selectorPoser includeSelectors: true dans le bloc labels
  • Kustomize permet de personnaliser des manifests Kubernetes sans templates ni duplication
  • La structure base + overlays sépare la config commune des spécificités par environnement
  • Utilisez toujours kubectl diff -k avant kubectl apply -k
  • Le champ patches: remplace les anciens patchesStrategicMerge et patchesJson6902
  • Les generators ajoutent un hash au nom des ConfigMaps/Secrets (c'est normal)
  • Ne jamais committer de secrets en clair, même avec secretGenerator
  • La version intégrée à kubectl peut différer du binaire standalone

Une base, deux overlays, et la preuve que les deux environnements sortent bien du même fichier. Ce lab vous fait décrire l'application une seule fois, la déployer dans deux namespaces avec un nombre de replicas différent, puis vérifier que les deux déploiements partagent la même image et la même structure. Le piège du selector y est posé : sans includeSelectors, le Service ne trouve plus ses Pods.

Les questions portent sur ce qui décide en pratique : le champ qui déclare la base, l'empreinte que les generators ajoutent au nom, la différence entre rendre et appliquer, et le piège du selector immuable. Une réponse ratée désigne la section à relire.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
8 min.
70% requis

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

  • Kyverno : Transformer et valider les manifests à l'admission, quand la modification doit s'appliquer à ce que les autres déploient.
  • Operators : L'étage au-dessus, quand la variation entre environnements devient de la logique et non plus du YAML.
  • Certification CKAD : Kustomize y est attendu, au même titre que les manifests écrits à la main.

Ce site vous est utile ?

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

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. 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