
Nelm : Redécouvrez le Déploiement de Charts Helm sur Kubernetes
Dans l'écosystème Kubernetes, Helm s'est imposé comme le gestionnaire de paquets de facto, simplifiant la définition, l'installation et la mise à niveau des applications. Cependant, malgré ses qualités, Helm 3 présente certaines limitations et complexités qui peuvent frustrer les équipes DevOps. C'est là qu'intervient Nelm, une alternative open-source construite sur les fondations de Helm 3, mais repensée pour offrir plus de contrôle, de prévisibilité et de robustesse dans vos déploiements.
Utilisé comme moteur de déploiement principal par l'outil CI/CD werf, Nelm conserve une compatibilité de premier ordre avec les Charts Helm existants tout en introduisant des fonctionnalités puissantes inspirées d'autres outils éprouvés comme Terraform.
Ce billet explore en profondeur ce qu'est Nelm, pourquoi vous pourriez l'envisager à la place de Helm, et comment ses fonctionnalités clés peuvent améliorer vos workflows de déploiement Kubernetes.
Qu'est-ce que Nelm ? Une Alternative Améliorée à Helm 3
Nelm n'est pas une réécriture complète de Helm, mais plutôt une évolution. Il reprend la base de code de Helm 3, assure la compatibilité avec ses concepts fondamentaux (Charts, Releases), mais réimplémente ou améliore des parties cruciales, notamment le moteur de déploiement.
Les objectifs principaux de Nelm sont de résoudre des problèmes connus de Helm 3 et d'introduire des capacités plus avancées :
-
Prévisualisation Fiable des Changements : Offrir une fonctionnalité similaire à
terraform plan
pour savoir exactement ce qui va changer dans le cluster avant d'appliquer. -
Gestion des Mises à Jour Robuste : Remplacer le mécanisme de "Fusion à Trois Voies" (3-Way Merge) de Helm par l'Application Côté Serveur (Server-Side Apply) de Kubernetes, plus fiable.
-
Ordonnancement Avancé : Permettre un contrôle fin sur l'ordre de déploiement des ressources, y compris les dépendances externes.
-
Gestion Sécurisée des Secrets : Intégrer nativement le chiffrement des fichiers de valeurs ou de fichiers arbitraires.
-
Suivi Détaillé et Visibilité : Améliorer le suivi de l'état des ressources, afficher les logs et événements en continu pendant le déploiement.
-
Correction de Bugs Helm : Résoudre des problèmes récurrents de Helm, comme les erreurs liées aux versions d'API obsolètes.
Tout en offrant ces améliorations, Nelm maintient la compatibilité avec le format des Charts Helm et le stockage des informations de release (Secrets Kubernetes), permettant une transition potentielle depuis Helm.
Pourquoi Envisager Nelm ? Les Fonctionnalités Clés
Explorons les aspects qui différencient Nelm et peuvent apporter une valeur significative à vos processus de déploiement.
1. Planification Précise avec nelm release plan install
L'un des défis avec Helm est de comprendre précisément l'impact d'une commande helm upgrade
. Nelm s'attaque à ce problème avec nelm release plan install
. Cette commande utilise un dry-run basé sur Server-Side Apply pour générer un diff fiable entre l'état actuel dans le cluster et l'état désiré après application du Chart.
Exemple : Planifier la mise à jour d'une application web
Imaginons un Chart simple pour une application web my-webapp
avec un Déploiement et un Service.
Chart.yaml
:
apiVersion: v2
name: my-webapp
version: 0.1.0
appVersion: "1.0"
values.yaml
:
replicaCount: 1
image:
repository: my-registry/my-webapp
tag: "1.0"
service:
type: ClusterIP
port: 80
templates/deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-app
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: web
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080 # Supposons que l'app écoute sur 8080
templates/service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-svc
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: 8080 # Port du container
selector:
app: {{ .Release.Name }}
Après un premier déploiement (nelm release install -n web -r myapp ./my-webapp
), nous voulons mettre à jour l'image vers la version "1.1" et passer à 2 réplicas. Planifions ce changement :
nelm release plan install -n web -r myapp ./my-webapp \
--set image.tag="1.1" \
--set replicaCount=2
Nelm affichera un résultat clair, indiquant uniquement les modifications prévues sur le Déploiement :
Planning release install "myapp" (namespace: "web")
┌ Update Deployment/myapp-app
│ namespace: web
│ spec:
│ - replicas: 1
│ + replicas: 2
│ template:
│ spec:
│ containers:
│ - name: web
│ - image: "my-registry/my-webapp:1.0"
│ + image: "my-registry/my-webapp:1.1"
│ ports:
└ Update Deployment/myapp-app
Planned changes summary for release "myapp" (namespace: "web"):
- update: 1 resource(s)
Cette clarté permet d'éviter les surprises et de valider les changements avant de les appliquer réellement avec nelm release install
.
2. Server-Side Apply (SSA) au lieu de 3-Way Merge
Le mécanisme de "Fusion à Trois Voies" (3-Way Merge) utilisé par Helm pour calculer les patchs de mise à jour est basé sur l'état connu de la dernière release Helm réussie. Si des modifications manuelles ont eu lieu (kubectl edit
), ou si une release précédente a échoué partiellement, Helm peut générer des patchs incorrects ou écraser des changements inattendus.
Nelm utilise l'Application Côté Serveur (Server-Side Apply), une fonctionnalité native de Kubernetes. Avec SSA, c'est le serveur d'API Kubernetes lui-même qui calcule le patch en se basant sur l'état réel de la ressource dans le cluster et l'état désiré soumis par Nelm. Chaque champ est "possédé" par un gestionnaire (ici, Nelm). Cela résout les problèmes de désynchronisation et assure des mises à jour beaucoup plus robustes et prévisibles. C'est la méthode adoptée par des outils modernes comme FluxCD.
3. Ordonnancement Avancé des Ressources
Helm propose un ordonnancement basique via les Hooks et leurs poids (helm.sh/hook-weight
). Nelm étend considérablement ces capacités :
-
Annotation
werf.io/weight
: Similaire àhelm.sh/hook-weight
, mais applicable à toutes les ressources (pas seulement les hooks). Les ressources avec le même poids sont déployées en parallèle. Les groupes de poids sont déployés séquentiellement (du plus petit au plus grand).Exemple : Déployer une ConfigMap avant un Déploiement.
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
annotations:
werf.io/weight: "-10" # Déployé en premier
data:
config.json: |
{"setting": "value"}
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
annotations:
werf.io/weight: "0" # Déployé après la ConfigMap
spec:
# ... spec utilisant la ConfigMap
-
Annotation
werf.io/deploy-dependency-<id>
: La méthode la plus puissante. Permet à une ressource d'attendre qu'une autre ressource de la même release atteigne un état spécifique (present
ouready
) avant de se déployer.Exemple : Un Job qui initialise une base de données (StatefulSet) avant le démarrage de l'application (Deployment).
# templates/database-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp-db
spec:
# ... spec du StatefulSet
# templates/init-db-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: myapp-init-db
annotations:
# Attend que le StatefulSet soit prêt avant de lancer le Job
werf.io/deploy-dependency-db: "state=ready,kind=StatefulSet,name=myapp-db"
# Note: Le Job lui-même est souvent un hook Helm (pre-install/pre-upgrade)
helm.sh/hook: pre-install, pre-upgrade
helm.sh/hook-weight: "5" # Exécuté après le STS mais avant le déploiement applicatif
spec:
# ... spec du Job d'initialisation
# templates/app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-app
annotations:
# Attend que le Job d'initialisation soit terminé (présent suffit souvent pour un Job)
# Ou si le Job doit absolument réussir, on pourrait pointer vers un état Ready hypothétique si le Job le supportait.
# Ici, on suppose que la présence du Job terminé est suffisante.
# Alternativement, si le Job crée une ressource signal (comme un Secret), on pourrait dépendre de cette ressource.
# Pour cet exemple, nous allons supposer que le hook Helm suffit à séquencer.
# Si le Job n'était PAS un hook, cette dépendance serait cruciale :
# werf.io/deploy-dependency-init: "state=present,kind=Job,name=myapp-init-db"
werf.io/weight: "10" # Assure qu'il se déploie après les hooks de poids inférieur
spec:
# ... spec de l'application
(Note : L'exemple combine hooks Helm et dépendances Nelm pour illustrer. Souvent, deploy-dependency
remplace le besoin de certains hooks complexes.)*
-
Annotations
*.external-dependency.werf.io/*
: Permet d'attendre la disponibilité de ressources hors de la release actuelle, typiquement gérées par des opérateurs (ex: unClusterIssuer
de cert-manager, uneDatabase
de KubeDB).Exemple : Une Ingress qui nécessite un
ClusterIssuer
géré séparément.
# templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
# ID unique pour cette dépendance externe
certissuer.external-dependency.werf.io/resource: "ClusterIssuer.v1.cert-manager.io/letsencrypt-prod"
# Si le ClusterIssuer était dans un namespace spécifique (non applicable ici car ClusterIssuer est cluster-scoped) :
# certissuer.external-dependency.werf.io/namespace: "cert-manager"
# Annotation standard pour utiliser le ClusterIssuer
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
# ... spec de l'Ingress
Nelm attendra que la ressource ClusterIssuer
nommée letsencrypt-prod
(avec le groupe d'API cert-manager.io/v1
) soit prête avant de créer l'Ingress.
4. Suivi Amélioré des Ressources et Affichage des Logs
Pendant une commande nelm release install
, Nelm fournit une sortie beaucoup plus riche que Helm :
- Tableau de Suivi : Un tableau est affiché périodiquement, montrant l'état de chaque ressource gérée (Waiting, Progressing, Ready, Failed). Pour les ressources comme les Déploiements ou StatefulSets, il suit aussi l'état des Pods sous-jacents.
- Détection Heuristique pour les CRDs : Nelm tente de déterminer l'état "Ready" de nombreuses Custom Resources en analysant leurs champs
status
, ce qui fonctionne pour environ la moitié des CRDs sans configuration supplémentaire. - Affichage des Logs en Continu : Nelm récupère et affiche les logs des conteneurs des Pods créés ou mis à jour pendant le déploiement. Très utile pour déboguer rapidement les problèmes de démarrage.
- Affichage des Événements : En ajoutant l'annotation
werf.io/show-service-messages: "true"
à une ressource, Nelm affichera également les événements Kubernetes associés à cette ressource pendant le déploiement.
Des annotations permettent de personnaliser ce comportement (filtrer les logs par regex, skipper les logs pour certains conteneurs, ignorer les échecs pour des ressources non critiques, etc.). Voir la section Documentation du README pour la liste complète (werf.io/log-regex
, werf.io/skip-logs
, werf.io/fail-mode
, etc.).
5. Gestion Native des Secrets Chiffrés
Gérer les secrets (mots de passe, clés d'API) dans Git est toujours délicat. Nelm intègre une solution inspirée de helm-secrets
, mais nativement :
-
Fichiers de Valeurs Chiffrés : Vous pouvez créer des fichiers comme
secret-values.yaml
qui sont chiffrés sur disque mais déchiffrés en mémoire lors dunelm install
ounelm render
. Leurs valeurs sont accessibles via.Values
comme d'habitude. -
Fichiers Arbitraires Chiffrés : Vous pouvez chiffrer n'importe quel fichier (ex:
config.json
,cert.pem
) et le placer dans un répertoiresecret/
à la racine du Chart. Ces fichiers peuvent être injectés dans les templates via la fonction{{ werf_secret_file "monfichier.txt" }}
.
Le chiffrement utilise une clé AES-256-GCM générée via nelm chart secret key create
et fournie via la variable d'environnement NELM_SECRET_KEY
.
Exemple : Utiliser des identifiants de base de données chiffrés
- Générer une clé (à faire une seule fois et à stocker de manière sécurisée) :
export NELM_SECRET_KEY=$(nelm chart secret key create)
# Stocker cette clé quelque part (ex: variable CI/CD, gestionnaire de secrets)
echo $NELM_SECRET_KEY
- Créer/éditer un fichier de valeurs secret :
# Ouvre $EDITOR pour créer/modifier le fichier, le chiffre à la sauvegarde
nelm chart secret values-file edit my-webapp/secret-values.yaml
- Contenu de
secret-values.yaml
(dans l'éditeur) :
database:
username: dbuser
password: SecurePassword123!
Le fichier my-webapp/secret-values.yaml
sur disque contiendra des données chiffrées.
- Utiliser les valeurs dans un template (ex: pour créer un Secret Kubernetes) :
# templates/db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-db-credentials
type: Opaque
stringData:
username: {{ .Values.database.username }}
password: {{ .Values.database.password }}
- Déployer (Nelm utilisera
secret-values.yaml
automatiquement siNELM_SECRET_KEY
est définie) :
export NELM_SECRET_KEY=... # Fournir la clé
nelm release install -n web -r myapp ./my-webapp
Exemple : Utiliser un fichier de configuration API chiffré
- Créer/éditer un fichier secret dans le répertoire
secret/
:
# Assurez-vous que NELM_SECRET_KEY est définie
mkdir -p my-webapp/secret
nelm chart secret file edit my-webapp/secret/api-config.json
- Contenu de
api-config.json
(dans l'éditeur) :
{
"apiKey": "abcdef123456",
"endpoint": "https://api.example.com/v1"
}
Le fichier my-webapp/secret/api-config.json
sur disque sera chiffré.
- Injecter le contenu dans une ConfigMap :
# templates/api-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-api-config
data:
config.json: |
{{- werf_secret_file "api-config.json" | nindent 8 }}
- Déployer :
export NELM_SECRET_KEY=... # Fournir la clé
nelm release install -n web -r myapp ./my-webapp
La ConfigMap dans Kubernetes contiendra le JSON déchiffré.
Compatibilité avec Helm
Nelm se veut un remplacement "drop-in" pour de nombreux cas d'usage de Helm :
- Charts : Les Charts Helm 3 sont directement utilisables avec Nelm sans modification. Toutes les fonctionnalités de templating, y compris les fonctions
lookup
, sont supportées. - Releases : Nelm utilise le même format de stockage des releases (Secrets dans le namespace de la release) que Helm 3. Théoriquement, vous pouvez alterner entre
helm
etnelm
pour gérer la même release (bien que ce ne soit généralement pas recommandé en production). -
Commandes CLI : La structure des commandes est différente, mais les fonctionnalités sont largement équivalentes. Voici une correspondance rapide :
Helm Command Nelm Command helm upgrade --install --atomic --wait -n ns rel ./c
nelm release install --auto-rollback -n ns -r rel ./c
helm uninstall -n ns release
nelm release uninstall -n ns -r release
helm template ./chart
nelm chart render ./chart
helm lint ./chart
nelm chart lint ./chart
helm dependency build ./chart
nelm chart dependency download ./chart
helm get values -n ns release
nelm release get values -n ns -r release
(Plugin helm-diff) helm diff upgrade ...
(Natif) nelm release plan install ...
(Plugin helm-secrets) helm secrets ...
(Natif) nelm chart secret ...
-
Plugins Helm : Non supportés directement. Nelm privilégie l'intégration native des fonctionnalités utiles (comme
plan
etsecret
).
La migration consiste principalement à adapter vos scripts CI/CD pour utiliser les commandes Nelm équivalentes.
Conclusion : Plus de Contrôle et de Fiabilité pour vos Déploiements
Nelm se présente comme une alternative sérieuse et réfléchie à Helm 3 pour les équipes qui recherchent plus de prévisibilité, de contrôle et de robustesse dans leurs déploiements Kubernetes. En remplaçant le 3-Way Merge par Server-Side Apply, en offrant une planification détaillée des changements, un ordonnancement avancé des ressources, un suivi amélioré et une gestion native des secrets, Nelm répond à plusieurs points de douleur courants rencontrés avec Helm.
Sa compatibilité avec les Charts Helm existants facilite son adoption. Si vous utilisez déjà werf
, vous bénéficiez déjà de Nelm. Sinon, et si les fonctionnalités décrites ici vous semblent pertinentes pour vos défis de déploiement, Nelm mérite assurément d'être exploré.
Pour commencer, consultez les instructions d'installation et essayez-le sur un projet de test !
Découvrez les derniers articles d'alter way