Helm v4 apporte des changements importants qui peuvent casser vos pipelines CI/CD si vous ne les anticipez pas. Ce guide liste tout ce qui change, avec les commandes exactes pour adapter vos scripts. Vous apprendrez à identifier les incompatibilités, tester votre migration en staging, et basculer sans incident en production.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Identifier les flags renommés et les corriger (
--atomic→--rollback-on-failure) - Migrer vos post-renderers vers le système de plugins
- Comprendre le nouveau comportement de
--dry-runet--wait - Activer Server-Side Apply (SSA) et gérer les conflits
- Adapter l'authentification OCI et utiliser les digests
- Planifier votre migration avec une checklist CI/CD
Ce qui casse en migration (checklist rapide)
Section intitulée « Ce qui casse en migration (checklist rapide) »Avant de lire le détail, voici une checklist des breaking changes à vérifier dans vos scripts :
| Ce qui change | v3 | v4 | Impact |
|---|---|---|---|
| Rollback automatique | --atomic | --rollback-on-failure | Scripts CI/CD |
| Forcer remplacement | --force | --force-replace | Scripts upgrade |
| Post-renderer | --post-renderer ./script | --post-renderer plugin-name | Pipelines avec kustomize |
| Dry-run | --dry-run (booléen) | --dry-run=client|server | Tests avant déploiement |
| Wait | --wait (booléen) | --wait=watcher|legacy | Attente pods ready |
| Server-Side Apply | Opt-in | Activé par défaut | Conflits ownership |
| OCI login | URL complète acceptée | Domaine uniquement | Auth registries |
Changements CLI majeurs
Section intitulée « Changements CLI majeurs »Les ruptures les plus visibles portent sur la ligne de commande, et elles se manifestent de deux façons très différentes. Un flag supprimé provoque une erreur immédiate (unknown flag), donc un pipeline en échec franc. Un flag dont le comportement change, comme --dry-run ou --wait, passe au contraire inaperçu et modifie silencieusement ce que fait votre déploiement. Les seconds méritent plus d'attention que les premiers.
Flags renommés
Section intitulée « Flags renommés »Trois flags de helm upgrade sont concernés. Le premier reste accepté mais déprécié, le deuxième a changé de nom, le troisième est nouveau et lié à Server-Side Apply.
--atomic → --rollback-on-failure
Section intitulée « --atomic → --rollback-on-failure »Le flag --atomic existe toujours mais est déprécié. Utilisez --rollback-on-failure :
helm upgrade --install myapp ./chart \ --atomic \ --wait \ --timeout 5mhelm upgrade --install myapp ./chart \ --rollback-on-failure \ --wait \ --timeout 5mComportement : Si le déploiement échoue (pods non Ready dans le timeout), Helm effectue automatiquement un rollback vers la révision précédente.
--force → --force-replace
Section intitulée « --force → --force-replace »Le flag pour forcer le remplacement des ressources a été renommé :
helm upgrade myapp ./chart --forcehelm upgrade myapp ./chart --force-replaceQuand l'utiliser : Forcer le remplacement complet d'une ressource au lieu d'un patch. Utile quand un champ immutable a changé.
Nouveau flag --force-conflicts
Section intitulée « Nouveau flag --force-conflicts »En v4, un nouveau flag gère les conflits Server-Side Apply :
helm upgrade myapp ./chart --force-conflictsCe flag force l'application même si un autre controller (ArgoCD, Flux, kubectl) a modifié la ressource.
Post-renderer : migration vers plugins
Section intitulée « Post-renderer : migration vers plugins »Un post-renderer est un programme qui reçoit les manifestes générés par Helm et les transforme avant leur envoi au cluster ; c'est le point d'accroche habituel de kustomize. C'est le changement de la v4 qui casse le plus de pipelines, parce qu'il ne se contourne pas : le passage par le système de plugins est obligatoire, et il faut donc empaqueter le script existant avant de migrer.
Ce qui change
Section intitulée « Ce qui change »En Helm v3, vous pouviez passer un binaire externe :
# v3 : binaire direct (NE FONCTIONNE PLUS en v4)helm template myapp ./chart --post-renderer ./kustomize-overlay.shEn Helm v4, les post-renderers passent obligatoirement par le système de plugins :
# v4 : plugin installéhelm template myapp ./chart --post-renderer kustomizeMigrer un post-renderer existant
Section intitulée « Migrer un post-renderer existant »La conversion ne touche pas au script lui-même : il continue de lire les manifestes sur l'entrée standard et d'écrire le résultat sur la sortie standard. Ce qui change, c'est son emballage : un répertoire dans le dossier des plugins et un fichier plugin.yaml qui le déclare avec postRenderer: true.
-
Convertir votre script en plugin Helm
Créez la structure de plugin :
Fenêtre de terminal mkdir -p ~/.local/share/helm/plugins/my-postrendererCréez
plugin.yaml:~/.local/share/helm/plugins/my-postrenderer/plugin.yaml name: "my-postrenderer"version: "1.0.0"usage: "Post-render manifests with custom logic"command: "$HELM_PLUGIN_DIR/render.sh"postRenderer: true -
Déplacer votre script
Copiez votre script existant :
Fenêtre de terminal cp ./kustomize-overlay.sh ~/.local/share/helm/plugins/my-postrenderer/render.shchmod +x ~/.local/share/helm/plugins/my-postrenderer/render.sh -
Vérifier l'installation
Fenêtre de terminal helm plugin listSortie attendue :
NAME VERSION DESCRIPTIONmy-postrenderer 1.0.0 Post-render manifests with custom logic -
Utiliser le plugin
Fenêtre de terminal helm template myapp ./chart --post-renderer my-postrenderer
Passer des arguments au post-renderer
Section intitulée « Passer des arguments au post-renderer »Utilisez --post-renderer-args :
helm upgrade --install myapp ./chart \ --post-renderer kustomize \ --post-renderer-args "--enable-helm" \ --post-renderer-args "--load-restrictor=LoadRestrictionsNone"Dry-run et validation
Section intitulée « Dry-run et validation »--dry-run est le flag le plus dangereux de cette migration, car il ne provoque aucune erreur : la commande continue de fonctionner, mais pas forcément comme avant. En v3 c'était un booléen ; en v4 il accepte une valeur qui détermine si Helm contacte ou non le cluster. Un pipeline de validation qui croyait tester contre le serveur peut se retrouver à ne valider que localement.
Nouveau comportement de --dry-run
Section intitulée « Nouveau comportement de --dry-run »En v3, --dry-run était un booléen. En v4, c'est une option à valeurs :
| Valeur | Comportement | Connexion cluster |
|---|---|---|
--dry-run=none | Exécution normale (défaut si omis) | Oui |
--dry-run=client | Simulation côté client uniquement | Non |
--dry-run=server | Simulation côté serveur | Oui |
--dry-run (sans valeur) | Équivalent à --dry-run=client | Non |
Recommandation : Utilisez toujours la forme explicite pour éviter les ambiguïtés.
# Validation sans cluster (rapide, offline)helm upgrade --install myapp ./chart --dry-run=client
# Validation avec le cluster (vérifie schémas, RBAC, quotas)helm upgrade --install myapp ./chart --dry-run=serverMasquer les secrets en dry-run
Section intitulée « Masquer les secrets en dry-run »Le flag --hide-secret masque les valeurs des Secrets dans la sortie :
helm template myapp ./chart --dry-run=client --hide-secretServer-Side Apply (SSA)
Section intitulée « Server-Side Apply (SSA) »Le Server-Side Apply est un mécanisme de Kubernetes où c'est l'API server, et non le client, qui fusionne la ressource souhaitée avec celle déjà en place. Chaque champ garde la trace du propriétaire qui l'a défini, ce qui permet au cluster de refuser une modification venant d'un autre gestionnaire. Ce changement est celui qui produit les erreurs les plus déroutantes en migration, surtout si un outil GitOps gère déjà les mêmes ressources.
Ce qui change
Section intitulée « Ce qui change »En v3 : Client-Side Apply (kubectl apply côté client)
En v4 : Server-Side Apply activé par défaut (--server-side=true)
SSA délègue la logique de merge au serveur Kubernetes, ce qui apporte :
- Meilleure gestion des conflits : détection si un autre controller a modifié la ressource
- Ownership tracking : Kubernetes sait qui a créé chaque champ
- Dry-run serveur : validation plus précise
Gérer les conflits
Section intitulée « Gérer les conflits »Si un autre outil (ArgoCD, kubectl, opérateur) a modifié une ressource, vous verrez :
Error: UPGRADE FAILED: cannot patch "myapp" with kind Deployment:Apply failed with 1 conflict: conflict with "argocd-application-controller"Solutions :
-
Forcer l'ownership (si Helm doit prendre le contrôle) :
Fenêtre de terminal helm upgrade myapp ./chart --force-conflicts -
Désactiver SSA (temporairement, pour debug) :
Fenêtre de terminal helm upgrade myapp ./chart --server-side=false
Vérifier le mode actuel
Section intitulée « Vérifier le mode actuel »Une simulation côté serveur suffit à savoir comment Helm applique vos ressources, sans rien modifier dans le cluster.
helm upgrade myapp ./chart --dry-run=server 2>&1 | grep -i "server-side"Wait avec kstatus (watcher)
Section intitulée « Wait avec kstatus (watcher) »--wait décide si helm upgrade rend la main immédiatement ou attend que les ressources soient réellement prêtes. En v4, ce n'est plus un interrupteur mais un choix de stratégie de surveillance, et la valeur par défaut n'attend que les hooks. Un pipeline qui comptait sur --wait pour bloquer jusqu'au démarrage effectif des pods doit donc être adapté, sous peine de déclarer un déploiement réussi avant qu'il ne le soit.
Nouveau comportement de --wait
Section intitulée « Nouveau comportement de --wait »En v3, --wait attendait que les ressources soient "Ready" selon une logique interne. En v4, vous choisissez la stratégie :
| Valeur | Comportement |
|---|---|
--wait=hookOnly | Attend seulement les hooks (défaut) |
--wait=watcher | Utilise kstatus pour surveiller l'état réel |
--wait=legacy | Comportement v3 (rétrocompatibilité) |
Pourquoi préférer watcher ?
Section intitulée « Pourquoi préférer watcher ? »Le mode watcher utilise kstatus qui comprend mieux l'état des ressources Kubernetes :
- Détecte les CRDs avec des conditions personnalisées
- Comprend les états intermédiaires (Progressing, Degraded)
- Gère les ressources non-standard (Argo Rollouts, Knative, etc.)
helm upgrade --install myapp ./chart \ --wait=watcher \ --timeout 5mAttendre les Jobs
Section intitulée « Attendre les Jobs »Le flag --wait-for-jobs reste disponible :
helm upgrade --install myapp ./chart \ --wait=watcher \ --wait-for-jobs \ --timeout 10mOCI : authentification et digests
Section intitulée « OCI : authentification et digests »Helm publie et récupère les charts depuis des registries OCI, les mêmes que celles qui hébergent vos images de conteneurs. Deux points changent en v4 : la commande de connexion devient plus stricte sur ce qu'elle accepte, et l'installation peut désormais viser un digest plutôt qu'un tag. Le premier casse les scripts existants, le second améliore la reproductibilité des déploiements.
Changement d'authentification
Section intitulée « Changement d'authentification »En v4, helm registry login attend uniquement le domaine, pas une URL complète :
# Fonctionnait en v3helm registry login oci://ghcr.io/myorg/charts# v4 : domaine uniquementhelm registry login ghcr.ioPattern CI/CD recommandé :
echo "$REGISTRY_TOKEN" | helm registry login ghcr.io -u "$REGISTRY_USER" --password-stdinInstallation par digest
Section intitulée « Installation par digest »Helm v4 supporte l'installation par digest SHA256 pour des déploiements reproductibles :
# Par tag (peut changer si le tag est réécrit)helm install myapp oci://ghcr.io/myorg/charts/myapp --version 1.2.3
# Par digest (immuable, recommandé pour prod)helm install myapp oci://ghcr.io/myorg/charts/myapp@sha256:abc123...Obtenir le digest d'un chart :
helm pull oci://ghcr.io/myorg/charts/myapp --version 1.2.3 2>&1 | grep DigestPlan de migration recommandé
Section intitulée « Plan de migration recommandé »La migration se fait sans désinstaller Helm v3 : les deux binaires cohabitent sous des noms différents, ce qui permet de comparer les manifestes générés avant de basculer quoi que ce soit. L'ordre des étapes compte, car l'audit des scripts détermine l'ampleur du travail restant, notamment la présence ou non d'un post-renderer à convertir.
-
Auditer vos scripts
Cherchez les patterns à mettre à jour :
Fenêtre de terminal # Dans vos repos CI/CDgrep -rn --include="*.yml" --include="*.yaml" --include="*.sh" \-E "(--atomic|--force[^-]|--post-renderer [^-]|--dry-run[^=])" . -
Installer Helm v4 en parallèle
Testez sans remplacer v3. Téléchargez l'archive et le fichier de sommes officiel publié à côté d'elle, vérifiez l'empreinte, et n'extrayez qu'ensuite :
Fenêtre de terminal HELM_VERSION="4.1.0"curl -fsSLO "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz"curl -fsSLO "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz.sha256sum"sha256sum --check "helm-v${HELM_VERSION}-linux-amd64.tar.gz.sha256sum"# helm-v4.1.0-linux-amd64.tar.gz: OKTant que la vérification ne répond pas
OK, n'installez rien. Une archive dépliée directement depuis le réseau ne laisse aucune chance de détecter une substitution :Fenêtre de terminal tar -xzf "helm-v${HELM_VERSION}-linux-amd64.tar.gz"sudo install -m 0755 linux-amd64/helm /usr/local/bin/helm4# Testerhelm4 version -
Tester en environnement de dev
Fenêtre de terminal # Comparer les manifests généréshelm3 template myapp ./chart -f values.yaml > v3-manifests.yamlhelm4 template myapp ./chart -f values.yaml > v4-manifests.yamldiff v3-manifests.yaml v4-manifests.yaml -
Migrer les post-renderers
Si vous utilisez
--post-renderer, convertissez en plugin (voir section dédiée). -
Adapter les flags dans CI/CD
Mettez à jour vos pipelines :
.gitlab-ci.yml deploy:script:# Avant (v3)# - helm upgrade --install myapp ./chart --atomic --wait# Après (v4)- helm upgrade --install myapp ./chart --rollback-on-failure --wait=watcher -
Déployer en staging
Testez le cycle complet :
- Install → Upgrade → Rollback → Uninstall
-
Basculer en production
Une fois validé en staging, mettez à jour Helm et les scripts en production.
Dépannage v4
Section intitulée « Dépannage v4 »Les messages ci-dessous se répartissent en deux familles. Les erreurs unknown flag sont bénignes : le pipeline s'arrête net, la correction est mécanique. Les conflits Server-Side Apply et les problèmes de détection d'état demandent une décision, car ils révèlent qu'un autre acteur gère les mêmes ressources ou que l'attente ne portait pas sur ce que vous croyiez.
| Symptôme | Cause | Solution |
|---|---|---|
unknown flag: --atomic | Helm v4 avec ancien flag | Remplacer par --rollback-on-failure |
unknown flag: --force | Helm v4 avec ancien flag | Remplacer par --force-replace |
Apply failed with conflict | SSA détecte une modification externe | Utiliser --force-conflicts ou coordonner l'ownership |
post-renderer plugin not found | Post-renderer non migré | Convertir en plugin Helm |
Error: login requires exactly one argument | URL au lieu du domaine | Utiliser seulement le domaine (ghcr.io) |
--dry-run flag needs an argument | Syntaxe v3 | Utiliser --dry-run=client ou --dry-run=server |
| Pods non détectés comme Ready | Mode wait legacy | Utiliser --wait=watcher |
Vérifier la version de Helm
Section intitulée « Vérifier la version de Helm »Premier réflexe avant tout diagnostic : la sortie indique aussi la version du client Kubernetes embarquée, qui conditionne la compatibilité avec votre cluster.
helm versionSortie attendue (v4) :
version.BuildInfo{Version:"v4.1.0", GitCommit:"...", GoVersion:"go1.25.6", KubeClientVersion:"v1.35"}Forcer le comportement v3 (temporaire)
Section intitulée « Forcer le comportement v3 (temporaire) »Si vous devez rester compatible temporairement :
helm upgrade --install myapp ./chart \ --server-side=false \ --wait=legacyÀ retenir
Section intitulée « À retenir »| Changement | Action requise |
|---|---|
--atomic → --rollback-on-failure | Rechercher/remplacer dans tous les scripts |
--force → --force-replace | Rechercher/remplacer |
| Post-renderer binaire → plugin | Créer un plugin Helm |
--dry-run → --dry-run=client|server | Spécifier explicitement la valeur |
| SSA activé par défaut | Gérer les conflits ownership |
--wait → --wait=watcher | Utiliser pour meilleure détection Ready |
| OCI login : domaine seul | Adapter les scripts de login |