Introduction
Helm est le gestionnaire de paquets pour Kubernetes, mais pour l'exploiter en toute sécurité, vous devez comprendre son architecture, et pas seulement mémoriser des commandes. Cet article explique l'architecture Helm avec des exemples pratiques, en reliant les composants, le flux de données, la conception et les opérations à des commandes concrètes, des sorties attendues, des signaux d'échec et des décisions de récupération. Il s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui doivent diagnostiquer et résoudre les problèmes Helm dans des clusters réels.
L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter comment récupérer si l'état attendu n'est pas atteint.
Inventaire des versions et de l'environnement
Avant de toucher à quoi que ce soit, sachez exactement ce que vous exécutez. Le comportement de Helm change entre les versions majeures (v2 vs v3 est une source courante de confusion), et les versions du cluster Kubernetes ajoutent une autre couche. Commencez par ces commandes en lecture seule :
# Version du client Helm
helm version --short
# Exemple de sortie attendue : v3.12.0+g0a3158d
# Version du cluster Kubernetes (nécessite kubectl)
kubectl version --short
# Exemple de sortie attendue : Client Version: v1.27.1 / Server Version: v1.26.3
# Lister les releases Helm actuelles dans l'espace de noms par défaut
helm list --namespace default
# Exemple de sortie attendue :
# NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
# myapp default 1 2023-06-01 10:00:00.000000 +0000 UTC deployed myapp-0.1.0 1.16.0
Ces commandes sont sûres : elles ne modifient pas l'état du cluster. Enregistrez la sortie dans votre runbook ou votre journal de terminal avant toute intervention.
Identifiez la topologie de déploiement. Utilisez-vous Tiller (Helm v2) ou le modèle client/serveur pur (Helm v3) ? Helm v3 a supprimé Tiller ; si vous voyez un pod tiller dans kube-system, vous êtes en v2 et devez planifier une migration. Vérifiez avec :
kubectl get pods -n kube-system | grep tiller
# Aucune sortie signifie pas de Tiller (Helm v3 ou ultérieur), ou Tiller non installé.
Prérequis pour ce document : Helm v3.8+ installé, kubectl v1.24+ avec un kubeconfig valide, et un espace de noms de test où vous pouvez créer des ressources. Utilisez des espaces réservés explicites dans les exemples : <nom-release>, <nom-chart>, <espace-de-noms>. Ne placez jamais de véritables identifiants ou identifiants de production dans un article ou dans l'historique de votre terminal.
Architecture Helm : composants essentiels
Helm v3 se compose de deux parties principales : le client Helm et le serveur d'API Kubernetes. Contrairement à v2, il n'y a pas de composant serveur dans le cluster (Tiller) stockant les informations de release. Au lieu de cela, l'état de la release est stocké sous forme de Secrets Kubernetes (par défaut) ou de ConfigMaps dans le cluster lui-même.
Client Helm (helm) : L'outil en ligne de commande que vous exécutez localement ou en CI/CD. Il rend les modèles, interagit avec l'API Kubernetes et gère l'historique des releases.
Chart : Un paquet de ressources Kubernetes préconfigurées. Les charts sont des répertoires ou des archives contenant Chart.yaml (métadonnées), values.yaml (configuration par défaut) et des fichiers de modèles sous templates/.
Dépôt : Un serveur HTTP hébergeant des charts empaquetés (index.yaml + fichiers .tgz). Les dépôts publics courants incluent Bitnami, Prometheus Community et Artifact Hub (un méta-dépôt).
Release : Une instance spécifique d'un chart exécutée dans un cluster Kubernetes. Chaque release a un nom, un numéro de révision et des données de configuration et de manifeste stockées.
Secrets/ConfigMaps Kubernetes comme stockage : Lorsque vous installez une release, Helm stocke ses métadonnées et son manifeste rendu dans un Secret (par défaut) ou une ConfigMap dans l'espace de noms de la release. Vous pouvez l'inspecter :
# Lister les secrets créés par Helm pour une release (le préfixe du nom est le nom de la release)
kubectl get secrets -n <espace-de-noms> -l owner=helm
# Exemple de sortie :
# NAME TYPE DATA AGE
# myapp.v1 helm.sh/release.v1 1 3m
# Décoder les informations de la release (Helm v3 les encode en JSON gzippé dans la clé 'release')
kubectl get secret myapp.v1 -n <espace-de-noms> -o jsonpath='{.data.release}' | base64 -d | gzip -d | jq .
Comprendre ce stockage est crucial pour la sauvegarde, la migration et le débogage.
Flux de données Helm : du chart aux ressources en cours d'exécution
Lorsque vous exécutez helm install myapp ./mychart -n mynamespace, les étapes suivantes se produisent :
- Chargement du chart : Helm lit le répertoire du chart ou le télécharge depuis un dépôt. Il valide
Chart.yamlet charge les valeurs par défaut devalues.yaml. - Fusion des valeurs : Les valeurs fournies par l'utilisateur (
-ffichier ou--set) sont fusionnées par-dessus les valeurs par défaut du chart. Les valeurs fusionnées sont accessibles dans les modèles via l'objet.Values. - Rendu des modèles : Helm traite tous les fichiers sous
templates/en utilisant les modèles Go et la bibliothèque de fonctions Sprig. Il résout{{ .Values.key }}et les fonctions comme{{ include }},{{ toYaml }}, etc. Les modèles invalides provoquent une erreur immédiate avant de contacter le cluster. - Validation des ressources : Helm analyse le YAML rendu en objets Kubernetes et effectue une validation de schéma de base.
- Ordre des ressources : Helm trie les ressources par type (par exemple, Namespace, ServiceAccount, Secret, ConfigMap, Deployment, Service) pour les appliquer dans un ordre sensé. Un ordre personnalisé peut être défini avec les annotations
helm.sh/hook. - Appels API : Helm envoie des requêtes
POSTouPUTau serveur d'API Kubernetes pour créer ou mettre à jour chaque ressource. - Stockage de la release : En cas de succès, Helm stocke les métadonnées et le manifeste de la release en tant que Secret dans l'espace de noms de la release. Si l'installation échoue, Helm peut effectuer un rollback (si
--atomicest utilisé) ou laisser des ressources partielles (avec--waità false).
Exemple de modèle de déploiement simple :
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
labels:
app: {{ .Release.Name }}-nginx
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}-nginx
template:
metadata:
labels:
app: {{ .Release.Name }}-nginx
spec:
containers:
- name: nginx
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 80
Avec values.yaml :
replicaCount: 2
image:
repository: nginx
tag: "1.23"
Rendez le modèle pour prévisualiser :
helm template myapp ./mychart --namespace mynamespace
# La sortie affiche le YAML Kubernetes complet avec toutes les valeurs substituées.
Cet essai à blanc ne contacte pas le cluster et est inestimable pour déboguer les modèles.
Conception Helm : hooks, cycle de vie et gestion des releases
La conception de Helm est centrée sur la gestion du cycle de vie des releases. Concepts clés :
- Hooks : Permettent une intervention à certains moments du cycle de vie d'une release. Par exemple,
pre-install,post-install,pre-upgrade,post-upgrade,pre-rollback,post-rollback,pre-delete,post-delete. Les hooks sont des ressources Kubernetes annotées avechelm.sh/hook: <nom-du-hook>. Ils s'exécutent jusqu'à la fin avant ou après l'application des ressources principales. - Révisions de release : Chaque
helm install,helm upgradeouhelm rollbackincrémente le numéro de révision. Vous pouvez afficher l'historique :
helm history myapp -n mynamespace
# Sortie attendue :
# REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
# 1 Mon Jun 1 10:00:00 2023 deployed myapp-0.1.0 1.16.0 Install complete
- Rollback : Helm peut revenir à une révision précédente :
helm rollback myapp 1 -n mynamespace
# Sortie attendue : Rollback was a success! Happy Helming!
Le rollback n'est pas une garantie si l'environnement a changé ; vérifiez l'état résultant avec kubectl get.
- Drapeaux atomic et wait :
--atomiceffectue un rollback en cas d'échec ;--waitattend que les pods soient prêts. Utilisez--atomic --wait --timeout 5mpour les installations en production afin d'éviter les états partiels.
Exemple de job hook :
# templates/db-migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-db-migrate
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migration
image: "{{ .Values.migration.image }}"
command: ["./migrate.sh"]
Chemin de configuration sûr
Ne stockez jamais de secrets dans des fichiers de valeurs en clair validés dans Git. Helm prend en charge la gestion des secrets externes via des plugins comme helm-secrets (sops), ou en s'intégrant aux Secrets Kubernetes et en les référençant depuis les modèles.
Un chemin de configuration sûr implique :
- Utilisez
values.yamlpour les valeurs par défaut non sensibles, mais remplacez-les par des fichiers spécifiques à l'environnement. - Utilisez
--setpour des remplacements simples, mais évitez les chaînes--setcomplexes ; utilisez--set-fileou-favec un YAML structuré pour la lisibilité. - Pour les données sensibles, utilisez un magasin de secrets et injectez-les comme variables d'environnement ou fichiers montés.
Exemple avec un espace réservé :
# values.yaml
postgres:
host: mypostgres.default.svc.cluster.local
port: 5432
username: app_user
# le mot de passe ne doit pas être ici ; utilisez un secret existant
passwordSecretName: myapp-postgres-secret
passwordSecretKey: password
Modèle :
# templates/deployment.yaml
events:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.postgres.passwordSecretName }}
key: {{ .Values.postgres.passwordSecretKey }}
Créez le secret séparément :
kubectl create secret generic myapp-postgres-secret \
--from-literal=password='S3cureP@ssw0rd' -n mynamespace
Puis installez :
helm install myapp ./mychart -f values.yaml -n mynamespace
Vérification : vérifiez que la variable d'environnement du pod n'est pas journalisée et que le secret existe :
kubectl get secret myapp-postgres-secret -n mynamespace -o yaml
# La sortie affiche le mot de passe encodé en base64 ; ne le décodez que si nécessaire et via une méthode sécurisée.
Rayon d'impact : si le secret est compromis, faites une rotation avec kubectl create secret avec une nouvelle valeur et redémarrez les pods (kubectl rollout restart deployment myapp).
Vérification et diagnostics
Après toute opération Helm, vérifiez que l'état réel du cluster correspond à l'intention. Utilisez d'abord des commandes en lecture seule.
Vérifier l'état de la release :
helm status myapp -n mynamespace
# La sortie inclut la date du dernier déploiement, les ressources et les notes.
Vérifier l'état des pods :
kubectl get pods -n mynamespace -l app=myapp-nginx
# Attendu : tous les pods en Running et Ready
Vérifier les événements :
kubectl get events -n mynamespace --sort-by=.metadata.creationTimestamp
# Recherchez les avertissements : FailedScheduling, ImagePullBackOff, CrashLoopBackOff, etc.
Vérifier les journaux :
kubectl logs -n mynamespace deployment/myapp-nginx --tail=50
Déboguer les problèmes de templating :
Utilisez helm lint pour vérifier le chart :
helm lint ./mychart
# Exemple de sortie :
# ==> Linting ./mychart
# [INFO] Chart.yaml: icon is recommended
# 1 chart(s) linted, 0 chart(s) failed
Utilisez helm template --debug pour voir les modèles rendus et les valeurs :
helm template myapp ./mychart -n mynamespace --debug
Vérifier les métadonnées de la release :
helm get values myapp -n mynamespace
# Affiche les valeurs fournies par l'utilisateur
helm get manifest myapp -n mynamespace
# Affiche le manifeste qui a été appliqué
Modes d'échec et récupération
Échecs Helm courants et comment récupérer :
1. Erreurs d'extraction d'image
Symptôme : Pod bloqué en ImagePullBackOff ou ErrImagePull.
Diagnostic :
kubectl describe pod myapp-nginx-<hash> -n mynamespace
# Regardez les événements : Failed to pull image "nginx:1.23": rpc error: code = NotFound desc = failed to pull and unpack image...
Cause : Balise d'image incorrecte, identifiants de dépôt manquants, ou registre inaccessible.
Récupération : Corrigez la balise d'image dans values.yaml ou créez un secret d'extraction d'image. Puis mettez à niveau :
helm upgrade myapp ./mychart -f values.yaml -n mynamespace
Vérifiez que le pod extrait et s'exécute.
2. Échecs de mise à niveau avec ressources partielles
Symptôme : helm upgrade échoue, laissant certains nouveaux pods et anciens pods en cours d'exécution, ou un mélange.
Cause : Nouveau modèle invalide, valeur requise manquante, ou conflit de ressources.
Récupération : Utilisez --atomic pour un rollback automatique en cas d'échec :
helm upgrade myapp ./mychart -f new-values.yaml -n mynamespace --atomic --wait --timeout 5m
Si déjà dans un mauvais état, effectuez un rollback manuel :
helm rollback myapp <révision-précédente> -n mynamespace
Puis corrigez le chart et réessayez.
3. Échecs de hook
Symptôme : La mise à niveau se bloque, et helm status montre un job de hook en échec.
Diagnostic :
kubectl get jobs -n mynamespace
# Recherchez le job de hook en état d'échec.
kubectl describe job myapp-db-migrate -n mynamespace
Récupération : Corrigez le script du hook ou les permissions, puis supprimez le job en échec et relancez la mise à niveau :
kubectl delete job myapp-db-migrate -n mynamespace
helm upgrade myapp ./mychart -f values.yaml -n mynamespace
4. Espace de noms introuvable
Symptôme : helm install échoue avec Error: namespaces "mynewnamespace" not found.
Cause : Helm ne crée pas les espaces de noms par défaut (sauf si --create-namespace est utilisé).
Récupération : Soit créer l'espace de noms d'abord :
kubectl create namespace mynewnamespace
helm install myapp ./mychart -n mynewnamespace
Ou utilisez le drapeau --create-namespace :
helm install myapp ./mychart -n mynewnamespace --create-namespace
5. Corruption des métadonnées de release
Symptôme : helm list montre la release en état unknown, ou les commandes échouent avec Error: release: not found.
Cause : Secret de release supprimé, ou modifications manuelles ont endommagé le stockage.
Récupération : Si le secret existe mais est corrompu, vous devrez peut-être reconstruire à partir de l'historique ou utiliser helm upgrade --force pour recréer les ressources. Si le secret est manquant, réinstallez en tant que nouvelle release si possible. Prévention : sauvegardez toujours les secrets de release ou utilisez helm get values et helm get manifest avant des opérations risquées.
Liste de contrôle des opérations
Utilisez cette liste de contrôle avant toute opération Helm en production.
- Capturer l'état actuel (lecture seule) :
helm list -n <espace-de-noms>
helm history <release> -n <espace-de-noms>
helm get values <release> -n <espace-de-noms> > values-backup.yaml
helm get manifest <release> -n <espace-de-noms> > manifest-backup.yaml
- Vérifier le chart et les valeurs avec
helm lintethelm template --debug.
- Vérifier la connectivité du cluster et les RBAC :
kubectl auth can-i create deployments -n <espace-de-noms>
# Attendu : yes
- Essai à blanc de la mise à niveau (le cas échéant) :
helm upgrade --dry-run --debug <release> ./chart -f new-values.yaml -n <espace-de-noms>
- Appliquer le changement avec atomic et wait pour la production :
helm upgrade <release> ./chart -f new-values.yaml -n <espace-de-noms> --atomic --wait --timeout 5m
- Vérifier le déploiement (pods, services, endpoints, ingress) :
kubectl get pods,svc,ingress -n <espace-de-noms>
kubectl rollout status deployment/<nom-du-déploiement> -n <espace-de-noms>
- Vérifier les journaux et les événements pour les avertissements.
- Documenter le changement dans votre système de gestion des changements avec le numéro de révision, l'horodatage et l'opérateur.
- Tester le chemin de récupération dans un environnement non productif régulièrement.
Exemple de flux de travail pour la mise à niveau d'une application web :
# Sauvegarde
helm get values webapp -n prod > webapp-values-backup-20230601.yaml
helm get manifest webapp -n prod > webapp-manifest-backup-20230601.yaml
# Essai à blanc
helm upgrade --dry-run --debug webapp ./webapp -f new-values.yaml -n prod
# Appliquer
helm upgrade webapp ./webapp -f new-values.yaml -n prod --atomic --wait --timeout 5m
# Vérifier
kubectl rollout status deployment/webapp -n prod
kubectl get pods -n prod -l app=webapp
Vérification attendue : deployment "webapp" successfully rolled out et tous les pods 1/1 Running.
Conclusion
L'architecture Helm expliquée avec des exemples pratiques n'est utile que si chaque recommandation est versionnée, observable et réversible dans la mesure où la technologie le permet. Copier une commande sans vérifier les prérequis et la sortie attendue n'est pas une procédure opérationnelle.
Vous avez maintenant une base : inventorier l'environnement, comprendre les composants et le flux de données, gérer une configuration sûre, vérifier les changements, diagnostiquer les échecs et suivre une liste de contrôle opérationnelle. Comme prochaine étape, choisissez une vérification à faible risque de cet article, enregistrez l'état actuel, exécutez la vérification documentée, comparez le résultat avec le signal attendu et passez en revue les dépendances telles que la version de Kubernetes et votre configuration CI/CD.
Un flux de travail technique fiable rend l'échec visible, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision.