Blog | WeScale

Simplifiez le déploiement de vos applications avec le templating Helm

Rédigé par Antoine Mayer | 12/10/2023

Introduction

Ces dernières années, le domaine du cloud est en constante évolution, la capacité à déployer des applications de manière rapide, cohérente et efficace est devenue incontournable. Le templating Helm est une des solutions pour simplifier ce processus dans des environnements Kubernetes.

Le templating consiste à utiliser des modèles ou des patrons pour générer automatiquement des configurations en fonction de paramètres spécifiques. Imaginez-le comme un moyen d'éviter de créer chaque configuration manuellement, ce qui serait fastidieux et sujet aux erreurs. Au lieu de cela, vous définissez un modèle, spécifiez quelques paramètres, et le système génère la configuration pour vous.

Helm, souvent décrit comme le "gestionnaire de packages pour Kubernetes", va au-delà de la simple encapsulation d'applications. Il offre un système de templating qui permet de générer des configurations personnalisées en fonction de vos besoins, tout en éliminant les répétitions et les erreurs associées.

Au fil de cet article, nous allons démystifier le concept du templating Helm, des bases jusqu'à des fonctionnalités plus avancées.

Présentation de Helm

Cette section est destinée à vous familiariser avec les bases de Helm, en expliquant ce que c'est, pourquoi c'est important, et comment il fonctionne.

C’est un projet open source qui simplifie considérablement le processus de déploiement et de gestion des applications dans Kubernetes. Chaque package est appelé un "chart". Ce sont des collections de fichiers YAML, de templates et de valeurs qui décrivent l'ensemble des ressources Kubernetes nécessaires pour une application. Helm permet de déployer ces charts de manière reproductible, en évitant la complexité du paramétrage manuel.

Mais alors Jamy, pourquoi devrions-nous utiliser Helm dans nos déploiements Kubernetes ?

 Voici quelques-unes des raisons :

  • La réutilisation : Helm permet de créer des charts réutilisables. Vous pouvez en développer pour une application, puis le partager avec d'autres équipes ou projets.
  • L’automatisation : Helm automatise le déploiement en utilisant des templates et des valeurs, ce qui réduit les erreurs humaines lors de la configuration des ressources Kubernetes.
  • L’évolutivité : Helm facilite la gestion de configurations complexes en permettant la personnalisation des charts en fonction des besoins spécifiques de chaque environnement (développement, test, production, etc.).
  • Les mises à jour facilitées : Vous pouvez mettre à jour vos applications plus facilement en appliquant simplement une nouvelle version du chart (il faut tout de même rester attentifs aux breaking changes si l’on ne veut pas avoir de mauvaises surprises).

Intéressons-nous au fonctionnement des templates et comment ils peuvent être utilisés pour générer des configurations dynamiques !

Les fondamentaux du templating Helm

Maintenant, que nous avons une compréhension de base de ce qu'est Helm, voyons la création de configurations dynamiques à l'aide du templating.

Plutôt que d'avoir une configuration statique pour notre application, la templatisation nous permet d'ajuster celle-ci en fonction de paramètres spécifiques à chaque déploiement.

Les templates Helm utilisent la syntaxe de templating Go, qui est puissante et flexible. Voici quelques éléments clés :

  • : Les doubles accolades sont utilisées pour délimiter les expressions de templating dans les fichiers Helm.
  • Variables : Vous pouvez définir des variables dans vos templates pour stocker des valeurs temporaires ou des résultats de calcul.
    • Variables personnalisées : Vous pouvez définir des variables personnalisées dans vos templates Helm en utilisant le symbole :=. Ces variables sont spécifiques à votre chart et vous permettent de stocker des valeurs temporaires ou des résultats de calcul.
    • Variables prédéfinies : En plus des variables personnalisées, Helm fournit également un ensemble de variables prédéfinies telles que .Values, .Release, .Chart,.Capabilities, etc. Elles contiennent des informations sur l’environnement Helm et sur le chart en cours de traitement.
  • Fonctions : Helm propose un ensemble de fonctions prédéfinies qui peuvent être utilisées dans les templates pour effectuer des opérations telles que la concaténation de chaînes, la conversion de types, etc.
  • Conditions : Vous pouvez utiliser des structures comme if, else, range, et with pour générer des configurations basées sur des conditions spécifiques.

L'une des caractéristiques phares du templating Helm est la gestion des variables et des valeurs. Comprendre leur fonctionnement est essentiel pour personnaliser vos charts. Voici un aperçu :

  • Les valeurs par défaut : Chaque chart peut inclure des valeurs par défaut pour ses paramètres. Ces valeurs sont stockées dans le fichier values.yaml et servent de point de départ pour les configurations.
  • Les valeurs personnalisées : Lors du déploiement du chart, nous pouvons spécifier des valeurs personnalisées qui remplacent les valeurs par défaut. Cela permet d'adapter le chart à des environnements spécifiques.
  • La hiérarchie des valeurs : Helm suit une hiérarchie pour déterminer quelles valeurs sont utilisées, en combinant les valeurs par défaut, les valeurs personnalisées et les valeurs spécifiées au niveau de la ligne de commande.

Personnalisation avec les valeurs

L'une des caractéristiques les plus puissantes de Helm réside dans sa capacité à personnaliser les charts en utilisant des valeurs. Nous allons voir comment les utiliser pour adapter nos déploiements en fonction de nos besoins, comment elles sont hiérarchisées et comment elles nous permettent de maintenir la flexibilité de nos configurations.

Pour personnaliser un chart Helm, nous utilisons des fichiers de valeurs qui sont généralement à l'intérieur du répertoire de notre chart. Voici comment cela fonctionne :

Chaque chart débute, bien souvent, avec un fichier values.yaml qui contient des valeurs par défaut pour les paramètres du chart. Nous pouvons y spécifier des valeurs telles que des ports, des images de conteneurs, des noms de ressources, etc.

Nous pouvons également créer des fichiers de valeurs supplémentaires pour différents environnements ou besoins. Par exemple, nous pouvons avoir un fichier values-dev.yaml pour le développement et un fichier values-prod.yaml pour la production.

Lors du déploiement du chart, nous spécifions quel fichier de valeurs utiliser. Cela permet d'adapter la configuration en fonction de l'environnement.

Helm suit une hiérarchie pour déterminer quelles valeurs sont utilisées lors du déploiement. Voici comment cela fonctionne :

  • Les valeurs par défaut : définies dans values.yaml, elles servent de point de départ. Si une valeur n'est pas spécifiée ailleurs, la valeur par défaut est utilisée.
  • Les valeurs personnalisées : Les valeurs spécifiées dans ces fichiers remplacent celles des valeurs par défaut. Par exemple `helm upgrade monapp ./monapp-chart -f values-prod.yml`
  • Les valeurs de la ligne de commande : Enfin, nous pouvons spécifier des valeurs directement depuis la ligne de commande lors du déploiement en utilisant l'option --set. Ces valeurs ont la priorité la plus élevée et écrasent les valeurs des fichiers.

Cette hiérarchie permet une grande flexibilité. Nous pouvons définir des valeurs par défaut pour l'ensemble de notre chart, puis personnaliser celles-ci en fonction de chaque environnement ou cas d'utilisation spécifique.

Supposons que nous travaillons sur un chart Helm pour déployer une application web, Dans notre fichier values.yaml, on défini des valeurs par défaut pour votre charte, par exemple :

image:
  repository: mon-app-repo
  tag: latest
replicaCount: 2

Pour notre environnement de développement, on peut créer un fichier values-dev.yaml pour personnaliser certaines valeurs spécifiques à cet environnement :

replicaCount: 1

Pour notre environnement de production, on peut créer un fichier values-prod.yaml pour personnaliser les valeurs pour cette configuration spécifique :

image:
  repository: mon-app-repo-prod
  tag: v1.0.0
replicaCount: 3


Aller plus loin avec les templates Helm

Nous avons déjà une bonne compréhension des bases du templating Helm. Mais il y a des fonctionnalités plus avancées, qui nous permettent de gérer des configurations complexes, d'automatiser davantage nos déploiements et de personnaliser nos charts de manière plus avancée.

Helm offre un ensemble de fonctions prédéfinies que nous pouvons utiliser dans nos templates pour effectuer diverses opérations (mathématiques, manipulations de chaînes, opérations logiques…). Voyons ensemble ce qu’il est possible de faire.

Substituer le contenu d’une variable : 

Si l’on souhaite, par exemple, substituer le contenu de la variable appName déclarée dans un fichier values.yaml nous procédons ainsi :

# templates/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
 name: -deployment
spec:
 replicas: 3
 template:
   spec:
     containers:
     - name: my-app
        image: nginx

Dans le cas où la variable équivaudrait à la valeur mon-app, la sortie sera :

...
metadata:
 name: mon-app-deployment
...

Les blocs conditionnels :

Le langage supporte les blocs comme, if/then/else. Il est possible d’afficher le contenu d’un bloc en fonction d’une condition. Par exemple, nous avons une valeur enableDebug dans votre fichier values.yaml :

# values.yaml
enableDebug: true

En utilisant un bloc conditionnel dans notre template nous pouvons activer ou désactiver une section en fonction de la valeur de enableDebug :

# templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
 name: my-config
data:
 
 debug.enabled: "true"
 
 debug.enabled: "false"
 

Dans notre cas il renverra :

apiVersion: v1
kind: ConfigMap
metadata:
 name: my-config
data:
 debug.enabled: "true"

Il faut savoir qu’avec le templating go, les variables prennent automatiquement la valeur “false” si :

  • une variable est non déclarée, exemple :
  • une variable contenant une structure vide
  • une variable contenant la valeur false, 0 ou null

Afficher le contenu d’un tableau :

Le templating Helm supporte les itérations sur des listes d’éléments avec le mot-clé range. Il est suffixé par le nom d’une variable et commence par le signe $. Par exemple, une liste de ports dans votre fichier values.yaml :

ports:
 - 80
  - 443

On peut itérer à travers cette liste pour créer des ports d'exposition dans notre template :

# templates/service.yaml

apiVersion: v1
kind: Service
metadata:
 name: my-service
spec:
 ports:
   
   - port:
   
 selector:
   app: my-app

L'exécution renverra la sortie suivante :

apiVersion: v1
kind: Service
metadata:
 name: my-service
spec:
 ports:
   - port: 80
   - port: 443
 selector:
   app: my-app

À présent, prenons cette déclaration :

os:
 linux:
   type: debian
 microsoft:
   type: Windows

Pour itérer sur cette structure, on peut utiliser le mot-clé range suivi du nom de nos deux variables, séparée par une virgule :


J'adore c'est pour cela que j'utilise

La sortie sera : 

J'adore linux c'est pour cela que j'utilise debian
J'adore microsoft c'est pour cela que j'utilise windows

Accéder aux variables globales :

Dans une boucle, les variables globales (par exemple, .Values, .Chart ou .Release) ne seront plus accessibles.

Voici un exemple :


J'adore c'est pour cela que j'utilise sur mon

Le moteur de templating renverra une erreur, indiquant qu’il n’arrive pas à évaluer la valeur de .Values.computer_type

Afin d’accéder à la variable computer_type il est possible d’utiliser le signe $ référençant le contexte global : 


J'adore c'est pour cela que j'utilise sur mon

Cette fois, le templating Helm reverra la sortie suivante : 

J'adore linux c'est pour cela que j'utilise debian sur mon laptop
J'adore microsoft c'est pour cela que j'utilise windows sur mon laptop

Gestion des Espaces dans les Templates Helm :

Dans les templates Helm, la gestion des espaces est un aspect important à prendre en compte, elle peut influencer la mise en forme des données générées. L'ajout ou la suppression d'espaces avant ou après des éléments dans les templates peut changer le rendu final.

L'une des techniques utilisées pour contrôler les espaces dans les templates Helm est d'utiliser des tirets (-) à la fin des déclarations. Par exemple, dans le code précédent :


J'adore c'est pour cela que j'utilise sur mon

Les tirets à la fin de la déclaration indiquent à Helm de supprimer tout espace blanc (y compris les retours à la ligne) après la fin de la boucle range

Les filtres :

Avec les filtres, on peut réaliser des opérations sur les valeurs des variables comme convertir une chaîne de caractère en entier ou calculer une somme de hachage. Supposons que vous ayez une valeur numérique dans votre fichier values.yaml :

# values.yaml
myNumber: 42

Le filtre int va convertir cette valeur en un nombre entier, puis l'utiliser dans votre template :

# templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
 name: my-config
data:
 my-number:

Un autre filtre intéressant est sha256sum va convertir la valeur en une somme sha256 :

# templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
 name: my-config
data:
 check-release:

Outre les opérations de base, Helm offre un ensemble de filtres avancés lorsque l’on souhaite faire des manipulations de chaînes de caractères ou des constructions de valeurs dynamiques.

Le filtre quote est l'outil de choix pour entourer une chaîne de caractères avec des guillemets. Il est largement utilisé pour garantir que les valeurs générées dans les templates Helm sont correctement formatées. Voici comment l'utiliser :

my-key: 

Dans cet exemple, assure que la valeur sera entourée de guillemets.

Le filtre printf permet de créer des chaînes de caractères en utilisant des modèles avec des espaces réservés pour les valeurs. Voici un exemple :

my-message: 

Dans cet exemple, printf permet de créer une chaîne de caractères en remplaçant les espaces réservés %s et %d par les valeurs de .Values.appName et .Values.appVersion.

Les valeurs par défaut :

Cette fonction permet de spécifier des valeurs par défaut :

image: ":"

Celui-ci combine le nom du registre Docker (image.repository) avec la version du chart (.Chart.AppVersion) pour créer le nom complet de l'image Docker. Mais, si l’on a spécifié un tag dans .Values.image.tag, il sera utilisé à la place de la version du chart. Cela permet de construire dynamiquement le nom de l'image Docker en fonction de vos configurations Helm.

Conclusion

Au fil de cet article, nous avons découvert Helm en explorant les composants clés de son architecture, la syntaxe de ses templates et la personnalisation à l'aide de valeurs.

L'une des caractéristiques phare de cet outil est sa flexibilité. Il peut s'adapter à des projets de toutes tailles, que ce soit pour des petites applications ou des infrastructures cloud complexes. 

Il réduit la barrière à l'entrée de Kubernetes tout en améliorant la qualité des déploiements. Toutefois, il est à noter que Helm n'est qu'un outil parmi d’autres pour gérer des configurations Kubernetes. Dans certains scénarios, notamment pour des configurations plus simples, des outils tels que Kustomize peuvent être plus appropriés.

Les avantages du templating Helm sont indéniables. Il accélère les déploiements tout en réduisant les erreurs humaines et en améliorant la cohérence des configurations.

Alors maintenant, lorsque vous aborderez votre prochain projet, n'oubliez pas les avantages que le templating Helm peut vous apporter ! 😉 Et si vous souhaitez en savoir plus sur Helm, vous pouvez de consulter notre article Helm pour les nuls et les moins nuls