Éviter les répétitions : manifestes Kubernetes avec Kustomize
Arrêtez de vous répéter lors de la création de manifestes Kubernetes grâce à Kustomize. Qu'est-ce que Kustomize, comment fonctionne-t-il et de quoi est-il capable ? Répondons à ces questions dans cet article.
Qu'est-ce que Kustomize
Kustomize est un outil en ligne de commande qui peut être utilisé pour transformer/personnaliser de manière « déclarative » les manifestes Kubernetes de manière à éviter les répétitions et à faciliter la maintenance et la réutilisation des manifestes existants.
Il fonctionne avec du YAML brut et des ressources Kubernetes natives. Il est disponible sous forme de binaire autonome et est également partiellement intégré à « kubectl » via « kubectl kustomize » et « kubectl apply -k ».
« Kustomize » est facile à apprendre et à utiliser par rapport aux outils incluant du templating comme helm et helmfile. Voici l'article de blog Kubernetes présentant « Kustomize » : Annonce de Kustomize.
Comment fonctionne Kustomize
- « Kustomize » fonctionne avec des manifestes Kubernetes bruts qu'il prend en entrée
- Il transforme ensuite les manifestes d'entrée en fonction de sa configuration et génère le résultat
- Les configurations Kustomize sont définies dans le fichier « kustomization.yaml »
- C'est là que nous indiquons à « Kustomize » quels fichiers manifestes Kubernetes il doit prendre en entrée et quelles transformations doivent leur être appliquées.
- Vous trouverez des informations sur le format et la syntaxe du fichier 'kustomization.yaml' ainsi que des explications détaillées sur chaque champ qu'il prend en charge, dans la page du fichier de Kustomization.
Exemple : Kustomization des manifestes de déploiement Kubernetes
Dans cet exemple, nous allons créer deux variantes d’un manifeste de ressources de déploiement Kubernetes pour les environnements de staging et de production.
Les manifestes spécifiques aux environnements seront générés à partir d'une base commune via « Kustomize ». Cela évite de dupliquer les manifestes de ressources Kubernetes.
- Exemple d'arborescence :
$ tree kustomize-example/
kustomize-example/
├── common
│ ├── deploy.yml
│ └── kustomization.yaml
├── prod
│ └── kustomization.yaml
└── staging
└── kustomization.yaml
- Contenu des fichiers :
# Common
$ cat common/deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: ubuntu
resources:
limits:
memory: "300Mi"
requests:
memory: "300Mi"
$ cat common/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
# Staging
$ cat staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../common/
commonLabels:
env: staging
# Prod
$ cat prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../common/
commonLabels:
env: prod
replicas:
- count: 4
name: myapp
- Manifestes Kustomizés résultants
# Staging
$ kustomize build staging/
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
env: staging # <= specific config for staging
name: myapp
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
env: staging
template:
metadata:
labels:
app: myapp
env: staging
spec:
containers:
- image: ubuntu
name: myapp
resources:
limits:
memory: 300Mi
requests:
memory: 300Mi
# Prod
$ kustomize build prod/
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
env: prod # <= specific config for prod
name: myapp
namespace: myapp
spec:
replicas: 4 # <= specific config for prod
selector:
matchLabels:
app: myapp
env: prod
template:
metadata:
labels:
app: myapp
env: prod
spec:
containers:
- image: ubuntu
name: myapp
resources:
limits:
memory: 300Mi
requests:
memory: 300Mi
Plus d'informations sur l'installation de « Kustomize » et la personnalisation facile des manifestes de ressources Kubernetes dans les sections suivantes.
Installer Kustomize
- Parfois, il peut être utile d'installer « Kustomize » pour le développement car certaines de ses fonctionnalités CLI utiles ne sont pas disponibles avec la commande « kubectl kustomize » au moment de la rédaction.
- La liste des versions de « Kustomize » peut être trouvée ici
- Pour installer « Kustomize » sous Linux, procédez comme suit :
$ kustomize_version=v5.4.2 # choose version
$ linux_arch=amd64 # choose OS arch
# Get Kustomize binary
$ wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${kustomize_version}/kustomize_${kustomize_version}_linux_${linux_arch}.tar.gz
# Install Kustomize binary
$ sudo tar xzvf kustomize_${kustomize_version}_linux_${linux_arch}.tar.gz -C /usr/local/bin/
# Verify
$ kustomize version
Créer et mettre à jour le fichier de kustomization
- Pour obtenir de l'aide sur l'utilisation et des exemples pour n'importe quelle commande CLI « Kustomize », exécutez les commandes suivies de « -h » ou « --help »
- Utilisez la CLI ou mettez à jour directement le fichier « kustomization.yaml » avec les paramètres de configuration souhaités
Initialiser le fichier de kustomization
Cela peut être utile pour initialiser rapidement un fichier « kustomization.yaml » avec des fichiers YAML autodétectés à partir du répertoire actuel, ajoutés en tant que ressources de configuration « Kustomize ».
$ tree k8s-resources/
k8s-resources/
├── deploy.yml
├── vpa.yml
├── ingress.yml
└── service.yml
$ kustomize create --autodetect
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- vpa.yml
- ingress.yml
- service.yml
Ajouter ou supprimer des ressources du fichier de Kustomization
- k8s-kustomization-resources pour plus d'infos
# Remove resource
$ kustomize edit remove resource vpa.yml
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.ym
# Add resource after creating the hpa.yml manifest
$ kustomize edit add resource hpa.yml
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.yml
- hpa.yml
Ajouter ou supprimer des labels et annotations communs du fichier de Kustomization
- k8s-kustomization-commonlabels et k8s-kustomization-commonannotations pour plus d'infos
# Add labels and annotations
# Multiple labels and annotations values are separeted by whitespace
$ kustomize edit add label app:myapp env:staging
$ kustomize edit add annotation myapp/version:0.0.1
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.yml
- hpa.yml
commonAnnotations:
myapp/version: 0.0.1
commonLabels:
app: myapp
env: staging
# Remove labels and annotations
# Only use the keys to remove labels or annotations
# Multiple keys values are separeted by comma
$ kustomize edit remove label app,env
$ kustomize edit remove annotation myapp/version
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.yml
- hpa.yml
Ajouter ou supprimer des patches du fichier de kustomization
- k8s-kustomization-patches pour plus d'infos
# Add patches
$ kustomize edit add patch --name myapp --kind Deployment --group apps --version v1 --path deploy-patch.yml
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.yml
- hpa.yml
patches:
- path: deploy-patch.yml
target:
group: apps
kind: Deployment
name: myapp
version: v1
# Remove patches
$ kustomize edit remove patch --name myapp --kind Deployment --group apps --version v1 --path deploy-patch.yml
$ cat kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
- service.yml
- ingress.yml
- hpa.yml
Comme indiqué précédemment, la configuration des patchs « Kustomize » comporte un champ « target » qui identifie de manière unique la ressource à patcher (en utilisant au moins un des éléments de ressources suivants : « group », « version », « kind », « name », « namespace », « labelSelector » et « annotationSelector ») et un champ « path » qui spécifie le chemin d'accès (par rapport au fichier « kustomization.yaml ») au fichier contenant les patchs. Le contenu des fichiers de patchs peut être écrit avec deux formats, présentés ci-dessous.
Patchs utilisant le standard json6902
# Syntax
- op: <operation type> # Possible values: add, remove, replace
path: <path to the field to modified on the resource>
value: <value we want for the field selected with path>
# Examples
# Patching container image
# File: deploy-patch.yml
- op: replace
path: /spec/template/spec/containers/0/image
value: nginx:1.25.3
Patchs utilisant le standard de fusion stratégique (strategic merge)
Kustomize patchesStrategicMerge
- Dans ce cas, le champ « target » de la configuration des patchs « Kustomize » peut être omis
- La ressource cible est mise en correspondance à l'aide des champs « apiVersion », « kind » et « metadata.name » des fichiers de correctifs
# Syntax
apiVersion: <apiVersion of the resource>
kind: <kind of the resource>
metadata:
name: <name of the resource>
spec:
<patches>
# Examples
# Patching container name and image on a Deployment named nginx
# File: deploy-patch.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
template:
spec:
containers:
- name: nginx
image: nginx:1.25.3
Définir le préfixe et le suffixe pour les noms de ressources
- k8s-kustomization-nameprefix et k8s-kustomization-namesuffix pour plus d'infos
$ kustomize edit set nameprefix -- prefix-
$ kustomize edit set namesuffix -- -suffix
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
(...)
- deploy.yml
(...)
namePrefix: prefix-
nameSuffix: -suffix
# Resulting Kubernetes resources
$ kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
name: prefix-myapp-suffix
(...)
Définir l'espace de noms des ressources
- k8s-kustomization-namespace pour plus d'infos
$ kustomize edit set namespace myapp-namespace
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
(...)
- deploy.yml
(...)
namespace: myapp-namespace
# Resulting Kubernetes resources
$ kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
(...)
namespace: myapp-namespace
(...)
Configurer le nombre de replicas
- k8s-kustomization-replicas pour plus d'infos
$ kustomize edit set replicas myapp=3
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
(...)
- deploy.yml
(...)
replicas:
- count: 3
name: myapp
# Resulting Kubernetes resources
$ kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
(...)
spec:
replicas: 3
Définir des images de conteneurs
- k8s-kustomization-images pour plus d'infos
# Original manifest
$ cat deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
(...)
spec:
(...)
spec:
containers:
- name: myapp
image: ubuntu
(...)
# Edit images matching ubuntu as original name
# Set the new image name to debian and new tag to latest
$ kustomize edit set image ubuntu=debian:latest
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deploy.yml
(...)
images:
- name: ubuntu
newName: debian
newTag: latest
# Resulting Kubernetes resources
$ kustomize build
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
(...)
spec:
(...)
spec:
containers:
- image: debian:latest
name: myapp
(...)
Ajoutez des configmaps dans le fichier de kustomization
- k8s-kustomization-configmapgenerator et k8s-kustomization-generatoroptions pour plus d'infos
# From literals
$ kustomize edit add configmap myapp-literals --from-literal key1=value1 --from-literal key2=value2
# From file
$ cat config.yml
hello
$ kustomize edit add configmap myapp-files --from-file=config.yml
# From env file
$ cat .env
db_host=127.0.0.1
db_user=myapp
db_name=myapp
$ kustomize edit add configmap myapp-envs --from-env-file=.env
# Resulting kustomization file
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
(...)
configMapGenerator:
- literals:
- key1=value1
- key2=value2
name: myapp-literals
- files:
- config.yml
name: myapp-files
- envs:
- .env
name: myapp-envs
# Resulting Kubernetes resources
$ kustomize build
apiVersion: v1
data:
db_host: 127.0.0.1
db_name: myapp
db_user: myapp
kind: ConfigMap
metadata:
name: myapp-envs-kgh2b6hhdc
---
apiVersion: v1
data:
config.yml: |
hello
kind: ConfigMap
metadata:
name: myapp-files-k472b254hd
---
apiVersion: v1
data:
key1: value1
key2: value2
kind: ConfigMap
metadata:
name: myapp-literals-ch29b7t2m8
- Notez qu'un hash a été rajouté comme suffixe au nom des ressources Kubernetes résultantes. Pour éviter cet ajout, vous pouvez utiliser l'option CLI « --disableNameSuffixHash ». Voici un exemple :
$ kustomize edit add configmap myapp-envs-no-suffix --from-env-file=.env --disableNameSuffixHash
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
(...)
- envs:
- .env
name: myapp-envs-no-suffix
options:
disableNameSuffixHash: true
$ kustomize build
(...)
---
apiVersion: v1
data:
db_host: 127.0.0.1
db_name: myapp
db_user: myapp
kind: ConfigMap
metadata:
name: myapp-envs-no-suffix
Ajoutez des secrets dans le fichier de kustomization
- k8s-kustomization-secretgenerator et k8s-kustomization-generatoroptions pour plus d'infos
# From literals
$ kustomize edit add secret myapp-literals --from-literal key1=value1 --from-literal key2=value2
# From files
$ kustomize edit add secret myapp-files-from-dir --from-file=secret-files/*
# From env file
$ cat .env
db_password=superpassword
$ kustomize edit add secret myapp-envs --from-env-file=.env
# Resulting kustomization file
$ cat kustomization.yml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
(...)
secretGenerator:
- literals:
- key1=value1
- key2=value2
name: myapp-literals
type: Opaque
- files:
- secret-files/secret1
- secret-files/secret2
name: myapp-files-from-dir
type: Opaque
- envs:
- .env
name: myapp-envs
options:
disableNameSuffixHash: true
type: Opaque
# Resulting Kubernetes resources
apiVersion: v1
data:
db_password: c3VwZXJwYXNzd29yZA==
kind: Secret
metadata:
name: myapp-envs
type: Opaque
---
apiVersion: v1
data:
secret1: c2VjcmV0MQo=
secret2: c2VjcmV0Mgo=
kind: Secret
metadata:
name: myapp-files-from-dir-52tfht2h62
type: Opaque
---
apiVersion: v1
data:
key1: dmFsdWUx
key2: dmFsdWUy
kind: Secret
metadata:
name: myapp-literals-kk658chggc
type: Opaque
Injecter dynamiquement des données dans les configmaps et les secrets de l'environnement
Dans les projets du monde réel, nos sources de manifestes Kubernetes « Kustomisées » seront placées dans un système de gestion de versions de code source (comme Git) afin de faciliter le travail d'équipe et de suivre les modifications.
Dans le système de gestion de versions, nous ne souhaitons pas mettre de valeurs secrètes comme le mot de passe de la base de données de l'application. Supposons que notre application ait besoin de variables d'environnement spécifiques pour se connecter à sa base de données (hôte, nom d'utilisateur, mot de passe...).
Voici comment nous pourrions générer la ressource « configmap » ou « secret » Kubernetes contenant les variables d'environnement d'application requises sans définir de valeurs de variables secrètes dans les fichiers sources des manifestes :
- Définissez les paires de variables non secrètes « clé = valeur » dans un fichier et définissez uniquement la « clé » pour les secrets :
$ cat .env
db_host=127.0.0.1
db_name=myapp
db_user=myapp
db_password
- Créez une configuration de générateur de secret ou de configmap « Kustomize » en utilisant ce fichier comme fichier de variables d'environnement :
$ kustomize edit add configmap myapp-envs --from-env-file=.env
- Renseignez la variable d'environnement
db_password=<password_value>avant la construction des manifestes « Kustomizés » :
$ export db_password=superpassword
Cela sera de préférence réalisé dans un pipeline CI/CD après avoir récupéré le secret à partir d'un gestionnaire de secrets (comme Vault) ou d'autres emplacements appropriés.
- Après avoir créé les manifestes « Kustomizés », les données « secret » ou « configmap » seront automatiquement renseignées avec la variable d'environnement « db_password » précédemment exportée :
$ kustomize build
apiVersion: v1
data:
db_host: 127.0.0.1
db_name: myapp
db_password: superpassword
db_user: myapp
kind: ConfigMap
(...)
Déployer des ressources gérées avec Kustomize
Voici comment nous pouvons déployer des ressources Kubernetes à partir de manifestes générés avec « Kustomize » :
# Deploy all resources
$ kubectl apply -k /path/to/kustomized/dir
# Deploy only resources with specific labels
$ kubectl apply -k /path/to/kustomized/dir -l app=myapp
Il est également possible de le faire comme ceci :
$ kustomize build | kubectl apply -f -
Créer des variantes à l'aide des superpositions (overlays)
Pour un aperçu de l'idée « Kustomize » des « superpositions » (overlays), jetez un œil à Exemple de superpositions (overlays) Kustomize.