Aller au contenu
Conteneurs & Orchestration medium

Dépendances Helm : subcharts, umbrella charts et composition

60 min de lecture

logo helm

Réponse directe : helm dependency update télécharge les sous-charts déclarés dans Chart.yaml vers charts/ et génère un Chart.lock pour verrouiller les versions exactes. Le chart parent passe des values aux subcharts via des clés nommées (ex: backend.replicaCount), et global.* est automatiquement propagé à tous les sous-charts.

Ce guide vous montre comment composer des applications complexes en assemblant plusieurs charts Helm, subcharts locaux, dépendances externes, et umbrella charts, tout en maintenant une configuration cohérente et reproductible.

Avant de commencer, assurez-vous d'avoir :

  • Un cluster Kubernetes fonctionnel (kind, k3d, minikube ou distant)
  • kubectl configuré et un namespace de test
  • Helm v3.8+ installé
  • Connaissance des modules précédents : templates, values, fonctions
SectionConceptDurée
Déclarer des dépendancesChart.yaml dependencies, repositories10 min
Télécharger et verrouillerhelm dependency update/build, Chart.lock8 min
Subcharts et valuesClés nommées, global.*, import-values12 min
Conditions et tagsActiver/désactiver des sous-charts8 min
Umbrella chartArchitecture multi-tiers complète10 min
Pièges et maintenanceConflits de noms, mises à jour7 min

Un chart Helm peut dépendre d'autres charts, locaux ou distants. Ces dépendances sont déclarées dans le fichier Chart.yaml sous la clé dependencies.

L'exemple ci-dessous mélange volontairement les deux origines possibles, un sous-chart local et un chart public, parce que c'est la configuration réelle de la plupart des umbrella charts : votre code applicatif à côté de briques d'infrastructure que vous ne maintenez pas. Notez que l'ordre des entrées dans dependencies n'a aucune influence sur l'ordre de déploiement, Helm rend tous les manifestes puis les applique en une passe, triés par type de ressource.

Créez un chart umbrella avec des dépendances mixtes :

Chart.yaml
apiVersion: v2
name: mon-stack
description: Chart umbrella pour démo composition
type: application
version: 1.0.0
appVersion: "1.0.0"
dependencies:
# Dépendance locale (sous-chart dans charts/)
- name: backend
version: "0.1.0"
repository: "file://charts/backend"
# Dépendance externe (repository Helm)
- name: kube-state-metrics
version: "5.27.0"
repository: "https://prometheus-community.github.io/helm-charts"
condition: monitoring.enabled # Activation conditionnelle
alias: metrics # Renommer dans les templates

Le champ repository détermine d'où Helm va chercher le chart, et ce choix a des conséquences sur votre chaîne de livraison. file:// garde le sous-chart dans votre dépôt Git : il évolue au même rythme que le parent et ne demande aucune infrastructure. Les trois autres formes visent un artefact publié ailleurs, donc versionné indépendamment, ce qui suppose que ce dépôt distant reste accessible au moment du déploiement. Sur un cluster sans accès Internet, seule la forme file:// fonctionne sans miroir interne.

TypeSyntaxe repositoryUsage
Localfile://charts/nomSous-chart développé avec le parent
HTTPShttps://example.com/chartsRepository Helm classique
OCIoci://ghcr.io/org/chartsRegistry OCI (Helm 3.8+)
Alias@monrepoRéférence un repo ajouté via helm repo add

Trois champs sont obligatoires, les quatre autres servent à résoudre des problèmes précis que vous rencontrerez tôt ou tard. condition et tags répondent à la même question, activer ou non le sous-chart, mais avec des granularités différentes, détaillées plus bas. alias est indispensable dans un seul cas : inclure deux fois le même chart dans un umbrella, par exemple deux instances de PostgreSQL. Le champ version accepte les opérateurs SemVer, et c'est celui qui décide de la stabilité de vos déploiements : la section sur les pièges y revient.

ChampObligatoireDescription
nameNom du chart à inclure
versionVersion ou range SemVer (^1.2.0, ~1.2.0, >=1.0.0)
repositoryURL ou chemin du chart
conditionChemin values pour activer/désactiver (ex: db.enabled)
tagsListe de tags pour activation groupée
aliasRenommer le chart (utile si même chart plusieurs fois)
import-valuesImporter des values du sous-chart vers le parent

Helm propose deux commandes pour gérer les dépendances : update et build.

Cette commande résout les dépendances depuis Chart.yaml, télécharge les charts dans charts/, et génère un fichier Chart.lock :

Fenêtre de terminal
helm dependency update mon-stack/

Sortie typique :

Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "prometheus-community" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 2 charts
Downloading kube-state-metrics from repo https://prometheus-community.github.io/helm-charts
Deleting outdated charts

Ce qui se passe :

  1. Helm met à jour les indexes des repositories
  2. Résout les versions selon les contraintes (5.27.0, ^1.0.0, etc.)
  3. Télécharge les .tgz dans charts/
  4. Génère Chart.lock avec les versions exactes

Regarder le dossier charts/ après la commande apprend une chose qui surprend souvent : les deux types de dépendances n'y laissent pas la même trace. Le point à retenir pour votre .gitignore est que seuls les .tgz sont reconstructibles à partir du Chart.lock ; le dossier backend/ est du code source qui vous appartient et doit rester versionné.

Fenêtre de terminal
ls -la mon-stack/charts/
total 32
drwxrwxr-x 3 bob bob 4096 févr. 1 19:09 .
drwxrwxr-x 4 bob bob 4096 févr. 1 19:09 ..
drwxrwxr-x 3 bob bob 4096 févr. 1 19:08 backend
-rw-rw-r-- 1 bob bob 751 févr. 1 19:09 backend-0.1.0.tgz
-rw-r--r-- 1 bob bob 14235 févr. 1 19:09 kube-state-metrics-5.27.0.tgz

Les sous-charts locaux (file://) restent en dossiers ET sont packagés en .tgz. Les dépendances externes arrivent uniquement en .tgz.

Là où Chart.yaml exprime une intention (« une version 5.27.x me convient »), Chart.lock enregistre le résultat de la résolution à un instant donné. Deux champs font tout le travail : version, qui fige la version exacte retenue pour chaque dépendance, et digest, une empreinte de la liste des dépendances qui permet à Helm de détecter que Chart.yaml a été modifié depuis la dernière résolution. Le champ generated n'est qu'un horodatage informatif, ne vous en servez pas comme critère de fraîcheur.

Chart.lock (généré automatiquement)
dependencies:
- name: backend
repository: file://charts/backend
version: 0.1.0
- name: kube-state-metrics
repository: https://prometheus-community.github.io/helm-charts
version: 5.27.0
digest: sha256:c7be1e4c41ba5a5a166b995fbf57fd64ef0364100fb37c12a84553e64f4443c3
generated: "2026-02-01T19:09:58.573104083+01:00"

Ce fichier est essentiel : il garantit que toute l'équipe et la CI utilisent les mêmes versions exactes.

Contrairement à update, la commande build utilise Chart.lock au lieu de Chart.yaml pour télécharger les dépendances :

Fenêtre de terminal
# Supprimer les archives téléchargées
rm mon-stack/charts/*.tgz
# Reconstruire depuis le lock
helm dependency build mon-stack/

Sortie :

Saving 2 charts
Downloading kube-state-metrics from repo https://prometheus-community.github.io/helm-charts
Deleting outdated charts

La distinction est la même qu'entre npm install et npm ci : l'une peut faire évoluer les versions, l'autre reproduit à l'identique. build refuse d'ailleurs de travailler si les deux fichiers ont divergé, avec un message explicite, the lock file (Chart.lock) is out of sync with the dependencies file (Chart.yaml). C'est exactement le comportement que vous voulez en CI : un Chart.yaml modifié sans helm dependency update fait échouer le pipeline au lieu de résoudre silencieusement une version différente de celle testée.

CommandeUtiliseQuand l'utiliser
helm dependency updateChart.yamlDéveloppement, mise à jour vers nouvelles versions
helm dependency buildChart.lockCI/CD, builds reproductibles

C'est la commande de diagnostic à lancer avant de perdre du temps sur un rendu qui échoue. Elle ne télécharge rien et ne modifie rien, elle compare simplement ce que déclare Chart.yaml avec ce qui se trouve réellement dans charts/. La colonne STATUS répond à elle seule à la question « pourquoi mon helm template se plaint-il d'une dépendance ».

Fenêtre de terminal
helm dependency list mon-stack/
NAME VERSION REPOSITORY STATUS
backend 0.1.0 file://charts/backend ok
kube-state-metrics 5.27.0 https://prometheus-community.github.io/helm-charts ok

Les statuts possibles :

  • ok : Dépendance présente et à jour
  • missing : Non téléchargée (lancer update ou build)
  • unpacked : Dossier présent mais pas de .tgz
  • wrong version : Archive présente, mais sa version ne satisfait pas la contrainte de Chart.yaml
  • misnamed : Archive présente sous un nom de fichier qui ne correspond pas au chart qu'elle contient

La communication entre chart parent et subcharts se fait exclusivement via les values. Helm offre trois mécanismes.

Chaque sous-chart reçoit ses values sous une clé correspondant à son nom (ou alias) :

values.yaml du parent
# Configuration du sous-chart "backend"
backend:
replicaCount: 2
image:
tag: "6.7.1"
# Configuration du sous-chart avec alias "metrics" (kube-state-metrics)
metrics:
prometheusScrape: true
replicas: 1

Dans le sous-chart backend, ces values sont accessibles directement :

charts/backend/templates/deployment.yaml
spec:
replicas: {{ .Values.replicaCount }} # Reçoit 2
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" # tag = 6.7.1

Les values sous global.* sont automatiquement propagées à tous les sous-charts :

values.yaml du parent
global:
imageRegistry: "my-registry.io"
additionalLabels:
team: platform
cost-center: infra

Dans n'importe quel sous-chart :

Template d'un sous-chart
metadata:
labels:
{{- with .Values.global.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
containers:
- image: "{{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Résultat du template :

metadata:
labels:
team: platform
cost-center: infra
spec:
containers:
- image: "my-registry.io/ghcr.io/stefanprodan/podinfo:6.7.1"

Ce rendu montre au passage le défaut le plus courant du motif global.imageRegistry : le sous-chart concatène sans condition, si bien qu'une image.repository contenant déjà un registre produit une référence à deux registres et un ImagePullBackOff. Les charts publics sérieux protègent leur template avec {{- if .Values.global.imageRegistry }} ; sur vos propres sous-charts, faites de même et ne stockez que le chemin du dépôt dans image.repository.

Pour des cas avancés, vous pouvez importer des values d'un sous-chart vers le parent :

Chart.yaml
dependencies:
- name: database
version: "0.1.0"
repository: "file://charts/database"
import-values:
- child: exports.connection # Chemin dans le sous-chart
parent: dbConnection # Clé dans le parent
charts/database/values.yaml
exports:
connection:
host: postgres.default.svc
port: 5432
database: appdb

Dans un template du parent, vous accédez maintenant à :

data:
DB_HOST: {{ .Values.dbConnection.host | quote }} # "postgres.default.svc"
DB_PORT: {{ .Values.dbConnection.port | quote }} # "5432"

Vous pouvez activer ou désactiver des sous-charts dynamiquement sans les supprimer de Chart.yaml.

Une condition est un chemin values qui doit valoir true ou false :

Chart.yaml
dependencies:
- name: kube-state-metrics
version: "5.27.0"
repository: "https://prometheus-community.github.io/helm-charts"
condition: monitoring.enabled
alias: metrics
values.yaml
monitoring:
enabled: true # Le sous-chart est inclus

Tester la condition :

Fenêtre de terminal
# Avec monitoring activé
helm template mon-stack . --set monitoring.enabled=true 2>&1 | grep -E "^# Source:" | sort -u
mon-stack/charts/backend/templates/deployment.yaml
# Source: mon-stack/charts/backend/templates/service.yaml
# Source: mon-stack/charts/metrics/templates/clusterrolebinding.yaml
# Source: mon-stack/charts/metrics/templates/deployment.yaml
# Source: mon-stack/charts/metrics/templates/role.yaml
# Source: mon-stack/charts/metrics/templates/serviceaccount.yaml
# Source: mon-stack/charts/metrics/templates/service.yaml
Fenêtre de terminal
# Avec monitoring désactivé
helm template mon-stack . --set monitoring.enabled=false 2>&1 | grep -E "^# Source:" | sort -u
mon-stack/charts/backend/templates/deployment.yaml
# Source: mon-stack/charts/backend/templates/service.yaml

Le sous-chart metrics n'est plus rendu quand monitoring.enabled=false.

Les tags permettent de grouper plusieurs sous-charts et de les activer/désactiver ensemble :

Chart.yaml
dependencies:
- name: backend
version: "0.1.0"
repository: "file://charts/backend"
tags:
- backend
- api
- name: frontend
version: "0.1.0"
repository: "file://charts/frontend"
tags:
- frontend
- api
- name: kube-state-metrics
repository: "https://prometheus-community.github.io/helm-charts"
tags:
- monitoring
- observability
values.yaml
tags:
api: true # Active backend ET frontend
monitoring: false # Désactive kube-state-metrics

Quand un sous-chart a à la fois une condition et des tags, la condition a priorité :

conditiontagRésultat
truetrue✅ Inclus
truefalse✅ Inclus (condition prioritaire)
falsetrue❌ Exclu (condition prioritaire)
falsefalse❌ Exclu
non définietrue✅ Inclus
non définiefalse❌ Exclu

Un cas manque volontairement à ce tableau parce qu'il est la source d'erreur la plus fréquente : une condition déclarée dans Chart.yaml mais dont le chemin n'existe pas dans les values. Helm ne la considère alors pas comme fausse, il l'ignore purement et simplement, et le sous-chart est inclus. Autrement dit, oublier monitoring.enabled: false dans values.yaml ne désactive rien, cela déploie. Déclarez donc toujours explicitement la clé référencée par une condition dans le values.yaml du parent, avec la valeur par défaut que vous voulez réellement.


Un umbrella chart est un chart qui ne contient (presque) pas de templates propres, il orchestre uniquement des sous-charts pour déployer une stack complète.

Deux détails de cette arborescence méritent votre attention. D'abord le dossier templates/ du parent est quasi vide : un umbrella qui accumule ses propres manifestes n'en est plus un, il redevient un chart applicatif ordinaire et vous perdez le bénéfice de la composition. Ensuite, charts/ mélange volontairement des dossiers (sous-charts locaux, versionnés avec le parent) et des archives (dépendances externes, reconstruites par helm dependency build). Cette différence de nature est ce qui détermine ce que vous commitez.

  • Répertoiremon-stack/
    • Chart.yaml Dépendances déclarées ici
    • Chart.lock Versions verrouillées
    • values.yaml Configuration globale + overrides subcharts
    • Répertoiretemplates/
    • Répertoirecharts/
      • Répertoirebackend/ Sous-chart local
      • Répertoiredatabase/ Sous-chart local
      • kube-state-metrics-5.27.0.tgz Dépendance externe

Voici un umbrella chart pour une application web avec monitoring :

apiVersion: v2
name: mon-stack
description: Stack web complète avec backend, database et monitoring
type: application
version: 1.0.0
appVersion: "1.0.0"
dependencies:
- name: backend
version: "0.1.0"
repository: "file://charts/backend"
tags:
- backend
- name: database
version: "0.1.0"
repository: "file://charts/database"
import-values:
- child: exports.connection
parent: dbConnection
- name: kube-state-metrics
version: "5.27.0"
repository: "https://prometheus-community.github.io/helm-charts"
condition: monitoring.enabled
alias: metrics

helm show chart renvoie le Chart.yaml tel que Helm l'interprète, clés triées par ordre alphabétique et champs par défaut explicités. C'est utile pour deux vérifications : contrôler qu'un alias, une condition ou un import-values a bien été pris en compte, et inspecter un chart empaqueté que vous n'avez pas écrit, en passant un .tgz ou une référence de repository à la place du dossier.

Fenêtre de terminal
helm show chart mon-stack/
apiVersion: v2
appVersion: 1.0.0
dependencies:
- name: backend
repository: file://charts/backend
tags:
- backend
version: 0.1.0
- import-values:
- child: exports.connection
parent: dbConnection
name: database
repository: file://charts/database
version: 0.1.0
- alias: metrics
condition: monitoring.enabled
name: kube-state-metrics
repository: https://prometheus-community.github.io/helm-charts
version: 5.27.0
description: Stack web complète avec backend, database et monitoring
name: mon-stack
type: application
version: 1.0.0

Quand vous packagez un umbrella chart, toutes les dépendances sont incluses dans l'archive :

Fenêtre de terminal
helm package mon-stack/ -d ./dist/
Successfully packaged chart and saved it to: ./dist/mon-stack-1.0.0.tgz
Fenêtre de terminal
tar tzf ./dist/mon-stack-1.0.0.tgz | head -20
mon-stack/Chart.yaml
mon-stack/Chart.lock
mon-stack/values.yaml
mon-stack/templates/configmap.yaml
mon-stack/charts/backend/Chart.yaml
mon-stack/charts/backend/values.yaml
mon-stack/charts/backend/templates/deployment.yaml
mon-stack/charts/backend/templates/service.yaml
mon-stack/charts/kube-state-metrics/Chart.yaml
mon-stack/charts/kube-state-metrics/values.yaml
mon-stack/charts/kube-state-metrics/templates/...

Deux sous-charts peuvent générer des ressources avec le même nom, causant des conflits :

# backend génère : mon-stack-backend-config
# frontend génère aussi : mon-stack-frontend-config
# ✅ OK, noms différents
# Si les deux utilisent {{ .Release.Name }}-config :
# ❌ Conflit : mon-stack-config existe deux fois

Solution : Utilisez le pattern {{ include "chart.fullname" . }} qui inclut le nom du chart :

{{- define "backend.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}

Après modification de Chart.yaml, vous devez re-run helm dependency update :

Fenêtre de terminal
# ❌ Erreur si vous oubliez
helm template mon-stack .
# Error: an error occurred while checking for chart dependencies. You may need to run
# `helm dependency build` to fetch missing dependencies: found in Chart.yaml, but
# missing in charts/ directory: new-dependency
# ✅ Correct
helm dependency update mon-stack/
helm template mon-stack .

Une contrainte de version large ne pose problème que le jour où quelqu'un relance helm dependency update, et c'est précisément pour ça qu'elle passe inaperçue pendant des mois. Les quatre écritures ci-dessous se lisent de la plus dangereuse à la plus sûre. Retenez la différence entre les deux opérateurs SemVer : le tilde ~ autorise seulement les correctifs, le caret ^ autorise aussi les versions mineures. Si vous voulez la reproductibilité maximale, épinglez la version exacte et acceptez de la faire évoluer à la main : Chart.lock protège les autres membres de l'équipe, pas celui qui lance la mise à jour.

dependencies:
# ❌ Dangereux : peut sauter une major
- name: postgres
version: "*"
# ⚠️ Peut inclure des breaking changes mineurs
- name: postgres
version: ">=15.0.0"
# ✅ Recommandé : patch updates seulement
- name: postgres
version: "~15.5.0" # 15.5.x uniquement
# ✅ Recommandé : minor updates
- name: postgres
version: "^15.0.0" # 15.x.x uniquement

Si Chart.lock n'est pas dans le repo Git, chaque développeur peut avoir des versions différentes :

Fenêtre de terminal
# Fichiers à commiter
git add Chart.yaml Chart.lock values.yaml templates/
# Fichiers à ignorer (reconstruits via helm dependency build)
echo "charts/*.tgz" >> .gitignore

Sans condition, un sous-chart est toujours déployé même si non utilisé :

# ❌ Pas de condition : monitoring toujours déployé
- name: prometheus
version: "25.0.0"
repository: "https://prometheus-community.github.io/helm-charts"
# ✅ Avec condition : contrôle explicite
- name: prometheus
version: "25.0.0"
repository: "https://prometheus-community.github.io/helm-charts"
condition: prometheus.enabled

Ce lab enchaîne les cinq mécanismes du guide sur un chart minimal, sans rien déployer sur un cluster : helm template suffit à valider la composition, et le kubectl apply --dry-run=client de la dernière étape vérifie seulement que le YAML produit est accepté par l'API. Comptez une dizaine de minutes. Le point de contrôle le plus instructif est le quatrième critère de réussite : c'est celui qui prouve que la condition fonctionne, et c'est aussi celui qui échoue si vous avez oublié de déclarer monitoring.enabled dans values.yaml.

  1. Créer la structure :

    Fenêtre de terminal
    mkdir -p mon-umbrella/charts/api/templates
  2. Déclarer le sous-chart API (charts/api/Chart.yaml) :

    apiVersion: v2
    name: api
    version: 0.1.0
  3. Ajouter une dépendance externe (Chart.yaml du parent) :

    dependencies:
    - name: api
    version: "0.1.0"
    repository: "file://charts/api"
    - name: kube-state-metrics
    version: "5.27.0"
    repository: "https://prometheus-community.github.io/helm-charts"
    condition: monitoring.enabled
    alias: metrics
  4. Configurer les values avec global.* et overrides :

    global:
    environment: staging
    api:
    replicaCount: 3
    monitoring:
    enabled: true
  5. Télécharger et valider :

    Fenêtre de terminal
    helm dependency update mon-umbrella/
    helm template test mon-umbrella/ | kubectl apply --dry-run=client -f -

Critères de réussite :

  • helm dependency list affiche toutes les dépendances en status ok
  • Chart.lock est généré avec les versions exactes
  • Les values global.* sont accessibles dans les sous-charts
  • --set monitoring.enabled=false exclut kube-state-metrics du rendu
  • Le chart se package avec toutes les dépendances incluses

ConceptCommande / SyntaxeUsage
Déclarerdependencies: dans Chart.yamlLister les sous-charts
Téléchargerhelm dependency updateDéveloppement, nouvelles versions
Reconstruirehelm dependency buildCI/CD, reproductibilité
Listerhelm dependency listVérifier les statuts
Values nomméesbackend.replicaCount: 2Configurer un sous-chart
Global valuesglobal.imageRegistryPropager à tous les sous-charts
Conditioncondition: db.enabledActiver/désactiver un sous-chart
Aliasalias: metricsRenommer un sous-chart

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn