Pour rappel une chart est un ensemble de templates (services, deployments...) avec ses propres values (values.yaml) et des métadatas.
On va créer le squelette d'un projet "web" :
helm create web
$ tree
└── web
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
4 directories, 10 files
Si on détail les fichiers :
Chart.yaml (obligatoire) :
values.yaml (non obligatoire) :
Dossier charts (non obligatoire) :
README (non obligatoire) :
License (non obligatoire) :
.helmignore (non obligatoire) :
Dossier templates (obligatoire) :
Dossier contenant les templates et des fichiers en lien avec les templates
NOTES.txt :
_helpers.tpl :
Nous allons créer notre premier template de création de config map.
Nous allons supprimer tous les templates du dossier pour partir de 0 :
$ ls
Chart.yaml charts templates values.yaml
$ cd templates/
$ ls
NOTES.txt _helpers.tpl deployment.yaml hpa.yaml ingress.yaml service.yaml serviceaccount.yaml tests
$ rm -rf *.yaml tests _helpers.tpl
$ vim NOTES.txt
Déploiement réussi !
Maintenant que nous avons nettoyé le dossier, nous allons nettoyer le fichier values.yaml
en enlevant toutes les valeurs.
Nous allons créer le fichier yaml configmap.yaml
dans le dossier template (mais sans templating pour le moment) :
apiVersion: v1
kind: ConfigMap
metadata:
name: web-cm
namespace: default
data:
key1: "Clé 1"
key2: "Clé 2"
On peut ensuite déployer la chart :
$ helm install my-web .
NAME: my-web
LAST DEPLOYED: Thu Aug 12 12:08:55 2021
NAMESPACE: wordpress
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Déploiement réussi !
Si on fait un get/describe de cette chart :
$ kubectl get configmaps
NAME DATA AGE
kube-root-ca.crt 1 18d
web-cm 2 15m
$ kubectl describe configmaps web-cm
Name: web-cm
Namespace: default
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: my-web
meta.helm.sh/release-namespace: wordpress
Data
====
key1:
----
Clé 1
key2:
----
Clé 2
Events: <none>
Nous allons maintenant ajouter des valeurs par défaut dans notre values.yaml
:
cm:
- key: "key1"
data: "valeur par défaut key1"
- key: "key2"
data: "valeur par défaut key2"
On va ensuite modifier notre template configmap.yaml
:
apiVersion: v1
kind: ConfigMap
metadata:
name: web-cm
namespace: default
data:
{{- range $cm := .Values.cm }} # Equivalent for
{{ $cm.key }}: {{ $cm.data }} # On respecte l'indentation
{{- end}}
.Values va accéder à toutes les variables de notre fichier values.yaml
. On va parcourir la liste "cm" que l'on a crée au-dessus.
On incrémente ensuite la version de notre chart dans Chart.yaml
. Puis on upgrade la chart actuellement déployée.
$ helm upgrade my-web .
Release "my-web" has been upgraded. Happy Helming!
NAME: my-web
LAST DEPLOYED: Thu Aug 12 12:35:27 2021
NAMESPACE: wordpress
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Déploiement réussi !
$ kubectl describe configmaps web-cm
...
Data
====
key1:
----
valeur par défaut key1
key2:
----
valeur par défaut key2
Events: <none>
On va maintenant mapper un ensemble de configmaps. Pour se faire remplacer le fichier values.yaml
par cette configuration :
configMaps:
cm1:
- key: "key1"
data: "Clé 1 par défaut"
- key: "key2"
data: "Clé 2 par défaut"
cm2:
- key: "key3"
data: "Clé 3 par défaut"
- key: "key4"
data: "Clé 4 par défaut"
Pour récupérer toutes les configmaps, nous allons devoir faire une boucle sur les éléments :
{{- range $cfgMaps,$content := .Values.configMaps }}
apiVersion: v1
kind: ConfigMap
metadata:
name: my-web-{{ $cfgMaps }} # Nom à partir de la variable : cm1, cm2...
namespace: default
data:
{{- range $cm := $content }} # Equivalent for
{{ $cm.key }}: {{ $cm.data }} # On respecte l'indentation
{{- end }}
--- # Séparation entre les X ConfigMaps
{{- end }}
Ici on map les variables $cfgMaps
sur cm1, cm2... et $content
sur la valeur de ces configmaps.
Une fois la chart upgrade :
$ kubectl get config map
NAME DATA AGE
kube-root-ca.crt 1 18d
my-web-cm1 2 21s
my-web-cm2 2 21s
$ kubectl describe configmaps my-web-cm1
...
Data
====
key1:
----
Clé 1 par défaut
key2:
----
Clé 2 par défaut
Pour une release, des variables génériques sont disponibles :
.Release.Name
.Release.Namespace
.Release.IsUpgrade
.Release.IsInstall
.Release.Revision
.Release.Service
On peut donc par exemple ajouter ces variables dans notre fichier configMaps :
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cm-{{ .Release.Revision }}
namespace: default
data:
upgrade: "{{ .Release.IsUpgrade }}"
install: "{{ .Release.IsInstall }}"
Une fois la configuration appliquée (helm install / helm upgrade) :
$ kubectl get configmaps
NAME DATA AGE
my-web-cm-1 2 40s
$ kubectl describe configmaps my-web-cm-1
...
Data
====
upgrade:
----
false
install:
----
true
Events: <none>
Des variables génériques sont disponibles pour les Charts :
.Chart.Name
.Chart.Version
.Chart.AppVersion
.Chart.Description
On peut aussi récupérer le contenu d'un fichier :
.Files.Get "monfichier.txt"
On va créer un répertoire files
avec un fichier test.txt
:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cm-{{ .Release.Revision }}
namespace: default
data:
key: {{ .Files.Get "files/test.txt" }}
Une fois la configuration appliquée on a donc :
$ kubectl get configmaps
NAME DATA AGE
my-web-cm-2 1 17s
$ kubectl get configmaps my-web-cm-2 -o yaml
apiVersion: v1
data:
key: test de fichier
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: my-web
meta.helm.sh/release-namespace: default
...
Ce cas de figure fonctionne qu'avec un fichier qui ne contient qu'une seule ligne.
Si l'on veut passer en paramètre un fichier avec plusieurs lignes on utilisera .Files.Lines "path"
:
data:
key: |- {{ range .Files.Lines "files/test.txt" }}
{{.}}{{- end}} # Opérateur
Le résultat sera donc :
kubectl get configmaps my-web-cm-3 -o yaml 1 ✘ docker-desktop ⎈
apiVersion: v1
data:
key: |-
test de fichier
test 2eme ligne
kind: ConfigMap
...
Il existe d'autres types de .Files
:
.Files.GetBytes
: Récupérer le contenu de fichier sous forme de bytes.Files.Glob
: Liste de fichier selon un pattern exemple :data:
key: |- {{- range $file, $content := .Files.Glob "files/test*.txt" }}
{{ $file }} # Affiche le nom du fichier
{{- end }}
.Files.AsConfig
: Converti le contenu en base64data:
{{ (.Files.Glob "files/test*.txt").AsConfig | indent 2 }} # Indentation de 2 espaces
ou test*.txt contient key: value
:
key1: "test key 1"
.Files.AsSecrets
: Converti en format yamlDes variables génériques sont disponibles pour les capabilities :
.Capabilities.APIVersions
.Capabilities.KubeVersion
.Capabilities.KubeVersion.Major
.Capabilities.KubeVersion.Minor
Des variables génériques sont disponibles pour les templates :
.Template.Name
.Template.BasePath
If / Else :
{{ if condition }}
{{ else if condition }}
{{ else }}
{{ end }}
En pratique cela donnerait :
{{- if .Values.var1 }}
key: "set"
{{- else }}
key: "not set"
{{- end }}
Si nous avons un var1
dans le values.yaml
on aura donc key
avec la valeur set
.
{{- if and .Values.var1 .Values.var2 }}
key: "set"
{{- else }}
key: "not set"
{{- end }}
{{- if or .Values.var1 .Values.var2 }}
key: "set"
{{- else }}
key: "not set"
{{- end }}
{{- if and (not .Values.var1) (not .Values.var2) }}
key: "set"
{{- else }}
key: "not set"
{{- end }}
{{- if eq .Values.var1 0.0 }} # Précise que c'est une valeur numérique
key: "zero"
{{- else }}
key: "not zero"
{{- end }}
Fonctionne également avec "neq", "lt", "le", "gt", "ge".
data:
key: {{- default "valeur par défaut" .Values.var1 }}
empty .Values.var1
metadata:
name: {{ required "Name of ConfigMap is required" .Values.configMap }}
Dans ce cas on exige l'existence de la valeur .Values.configMap
sinon le message sera retourné à l'utilisateur.
{{- if eq .Values.var1 0.0 }} # Précise que c'est une valeur numérique
key: "zero"
{{- else }}
{{- fail "Invalid value for var1" }}
{{- end }}
coalesce 0 1 2 # Retourne 1
ternary "valeur1" "valeur2" (test)
Soit :
data:
key: {{ ternary "zero" "autre" ( eq .Values.var1 0.0 ) }}