Dans cet article nous allons traiter de la mise en place d’un système de fichier multiniveau au sein d’une image docker dans un contexte Kubernetes, avec un déploiement kind.
Problématique
Bien souvent, il convient lors du déploiement d’une application sous Kubernetes de s’assurer que les fichiers de configuration applicatifs soient présents sur l’image. Certes, il n’est pas préconisé d’injecter de la configuration par système de fichier (on préfère souvent les variables d’environnement), mais quand on porte une application sous k8s c’est hélas souvent une problématique à laquelle on est confronté. D’autant que les dit fichiers doivent évolués en fonction des environnements de déploiement.
Une approche simple consisterait à mettre en place une config map par fichier, mais, le travail peut être long et fastidieux quand on est dans le cas de plusieurs dizaines de fichiers.
Je vous présente donc ici la solution que j’ai mise en oeuvre dans de multiples projets pour me simplifier la tâche.
Prérequis
Voici la liste de prérequis pour le ce tutoriel:
- disposer d’un environnement Kubernetes, nous utiliserons k3d ici
- avoir des connaissances sur la solution de déploiement HELM
- maitriser les concepts Kubernetes de configuration map / déploiement / …
Solution
Nous allons mettre en place un mécanisme de construction dynamique de configuration map que nous allons ensuite monter dans une image. Les fichiers présentés dans la configuration map seront des fichiers texte dans lequel il conviendra de changer le contenu en fonction de valeur définie dans le fichier de values.yaml du chart.
Définition de l’attendu
Pour illustrer notre configuration map multiniveau nous allons construire dans un container le filesystem suivant:
App
┣ subfolder
┃ ┗ file3.cfg
┣ file1.cfg
┗ file2.cfg
Dans le file1.cfg nous allons faire en sorte d’injecter des données de configuration en provenance du fichier de configuration du chart : le fichier values.yaml
Étape du tutoriel
Installation de k3d
Après avoir installé l’outil k3d en suivant la procédure d’installation, vérifiez la bonne installation de l’outil en lançant la commande suivante:
k3d --version
Vous devez obtenir le résultat suivant:
k3d version v3.2.0
k3s version v1.18.9-k3s1 (default)
Créer votre premier cluster en lançant la commande
k3d cluster create mycluter
qui vous donne le résultat suivant:
vous devez pouvoir voir la liste des pods de votre tout nouveau cluster en lançant la commande suivante:
kubectl get pods --all-namespaces
qui vous donne ce résultat:
Installation de HELM3
La procédure d’installation de l’outil est présente ici https://helm.sh/docs/intro/install/.
Dans mon cas je suis sur une machine Ubuntu je lance donc simplement le script suivant comme indiqué dans la documentation:
curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
vous pouvez vérifier que helm3 est correctement installé en lançant la commande suivante:
helm version
Qui doit vous retourner l’information suivante:
version.BuildInfo{Version:"v3.5.1", GitCommit:"32c22239423b3b4ba6706d450bd044baffdcf9e6", GitTreeState:"clean", GoVersion:"go1.15.7"}
Création du chart à partir du modèle
Passons maintenant à la mise en place du chart helm à proprement dit. Créez un dossier de projet, dans lequel nous allons travailler.
mkdir ~/home/multilevel && cd ~/home/multilevel
et lancer la commande de création du chart Helm:
helm create multilevelcm
Cette commande crée le squelette du chart dans le dossier ~/home/multilevel/
.
vous obtenez la structure de fichier suivante:
📦multilevelcm
┣ 📂charts
┣ 📂templates
┃ ┣ 📂tests
┃ ┃ ┗ 📜test-connection.yaml
┃ ┣ 📜NOTES.txt
┃ ┣ 📜_helpers.tpl
┃ ┣ 📜deployment.yaml
┃ ┣ 📜hpa.yaml
┃ ┣ 📜ingress.yaml
┃ ┣ 📜service.yaml
┃ ┗ 📜serviceaccount.yaml
┣ 📜.helmignore
┣ 📜Chart.yaml
┗ 📜values.yaml
il s’agit d’un chart de base qui crée déploie un serveur nginx.
Pour plus d’information sur l’anatomie des chart la documentation est ici https://helm.sh/docs/helm/helm_create/.
Création de la configuration map dynamique
création de la structure de fichier dans le chart
Dans le dossier de chart, créer un dossier files qui contient la structure de notre dossier. Vous devez obtenir la structure de fichier suivant:
📦multilevelcm
┣ 📂charts
┣ 📂files
┃ ┣ 📂subfolder
┃ ┃ ┗ 📜file3.cfg
┃ ┣ 📜file1.cfg
┃ ┗ 📜file2.cfg
┣ 📂templates
┃ ┣ 📂tests
┃ ┃ ┗ 📜test-connection.yaml
┃ ┣ 📜NOTES.txt
┃ ┣ 📜_helpers.tpl
┃ ┣ 📜deployment.yaml
┃ ┣ 📜hpa.yaml
┃ ┣ 📜ingress.yaml
┃ ┣ 📜service.yaml
┃ ┗ 📜serviceaccount.yaml
┣ 📜.helmignore
┣ 📜Chart.yaml
┗ 📜values.yaml
Dans les fichiers file2.cfg
et file3.cfg
mettez le contenu que vous souhaitez. Dans le file1.cfg
, positionnez le contenu suivant:
{{ .Values.configuration.file1 }}
Ceci permettra au moteur de template d’aller chercher la valeur dans le fichier de chart. Pour cela à la fin du fichier values.yaml, ajoutez le contenu suivant:
configuration:
file1: |-
contenu du fichier 1
création de la configmap
Dans le dossier du Chart, créer un dossier configmap pour loger le fichier de définition de notre objet.
dans ce fichier, positionner le contenu suivant:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "multilevelcm.fullname" . }}-config
labels:
{{- include "multilevelcm.labels" . | nindent 4 }}
data:
{{ $root := . }}
{{- range $path, $bytes := $root.Files.Glob (printf "files/**") -}}
{{ $name := base $path }}
{{- sha256sum (printf "%s" (index (regexSplit "files/" ($path) -1 ) 1))}}{{ print ": |- " }}
{{- tpl ($root.Files.Get ($path)) $ | nindent 4 }}
{{end }}
l’usage de la fonction sha256sum permet de s’affranchir des caractères spéciaux éventuels dans le nom du fichier. La fonction tpl permet de considérer les fichiers comme des templates helm et donc d’y injecter des données en provenance du helm chart.
montage de la configuration map dans le pod
Il reste a monter la configuration map en tant que volume dans le container. Pour ce faire, éditer le fichier de déploiement pour y ajouter les éléments suivants:
Dans la partie du container, ajouter la déclaration du module:
containers:
- name:
securityContext:
image: ":"
imagePullPolicy:
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
volumeMounts:
- name: config
mountPath: "/app"
puis à la fin du fichier ajouter la déclaration du volume:
volumes:
- name: config
configMap:
name: {{ include "multilevelcm.fullname" . }}-config
items:
{{- range $path, $bytes := .Files.Glob (printf "files/**") -}}
{{ $name := base $path }}
- key: {{ sha256sum (printf "%s" (index (regexSplit "files/" ($path) -1) 1)) }}
path: {{ printf "%s" (index (regexSplit "files/" ($path) -1) 1) }}
{{- end}}
Résultat
Notre chart est pret, pour le déployer sur le cluster k3d. positionnez vous dans votre dossier ~/multilevel et lancer la commande suivante:
helm install -name myrelease -n myrelease --create-namespace ./multilevelcm/
Avec l’outil lens connectez vous sur votre cluster, puis entrez dans votre pod. En navigant dans le dossier /app, vous constatez que tout vos fichiers sont la et que le contenu de votre fichier file1.cfg corresponds à ce que vous avez mis dans le fichier de values.
le code du chart est disponible sur mon github