L'automatisation de Helm avec CI/CD offre des déploiements Kubernetes rapides, reproductibles et réversibles. Bien faite, elle réduit aussi le travail répétitif en détectant les erreurs avant qu'elles n'atteignent le cluster et en fournissant des chemins de restauration propres lorsqu'un problème passe entre les mailles du filet.
Ce guide se concentre sur une approche sûre et observable que vous pouvez implémenter dès aujourd'hui :
- Établir un inventaire clair des versions et environnements pour que chaque étape s'exécute sur des cibles prévisibles.
- Adopter une approche de déploiement progressif avec des drapeaux Helm protégés.
- Utiliser de petites étapes CI composables (lint, rendu, validation, déploiement) et des fichiers de valeurs spécifiques à chaque environnement.
- Vérifier le succès avec des contrôles concrets et des artefacts.
- Préparer l'échec avec des commandes de restauration et de récupération testées.
À la fin, vous disposerez d'exemples pratiques pour GitHub Actions et GitLab CI/CD, d'un ensemble de commandes fonctionnel et d'une liste de contrôle reproductible que vous pourrez adapter aux services de votre équipe.
Inventaire des versions et environnements
Avant d'écrire le moindre job de pipeline, faites l'inventaire de votre environnement d'exécution. Des versions cohérentes sont essentielles pour des rendus reproductibles et des déploiements fiables.
Exemple d'inventaire d'environnement :
| Composant | Version | Notes |
|---|---|---|
| Helm CLI | v3.14.x | Cohérent entre le poste local et les runners CI |
| Kubernetes | v1.27.x | Stabilité de l'API supposée dans les manifestes |
| kubectl | v1.27.x | Correspondre à la version mineure du serveur |
| API du chart | apiVersion: v2 | Requis pour l'empaquetage Helm 3 |
| Disposition des namespaces | app-staging, app-prod | Un namespace par environnement |
Prérequis minimums :
- Vous avez un accès au cluster pour la préproduction et la production (contextes Kubernetes séparés ou clusters distincts).
- Vous pouvez créer des namespaces et du RBAC pour un compte de service CI avec des permissions limitées aux namespaces cibles.
- Vos charts Helm utilisent Chart.yaml apiVersion: v2 et incluent un values.schema.json lorsque c'est faisable pour valider les entrées.
Vérifications rapides des versions :
helm version
kubectl version --short
Si les versions divergent entre les machines de développement et la CI, épinglez-les dans vos jobs CI et dans la documentation d'intégration des développeurs.
Chemin de configuration sécurisé
L'objectif est une promotion prévisible et à faible risque, d'un changement prévalidé vers une version de production saine. Utilisez les choix d'implémentation suivants comme base de référence sûre.
Namespaces et noms de release
- Préproduction : namespace
app-staging, nom de releasemyapp-staging - Production : namespace
app-prod, nom de releasemyapp
Fichiers de valeurs
- Conservez des fichiers de valeurs spécifiques à l'environnement :
values/staging.yaml,values/production.yaml - Épinglez les tags d'image (pas de
latest) et incluez les nombres de répliques par environnement.
Mises à niveau protégées
Utilisez des mises à niveau atomiques, des délais explicites et la conservation de l'historique :
helm upgrade --install myapp-staging ./charts/myapp \
--namespace app-staging \
--create-namespace \
--values values/staging.yaml \
--atomic \
--timeout 5m \
--history-max 10
--atomic effectue une restauration en cas d'échec, évitant les états à moitié appliqués. Maintenez des délais serrés en préproduction pour faire émerger rapidement les déploiements lents, et légèrement plus élevés en production pour tenir compte de l'échelle.
Portes de santé et de disponibilité
- Assurez-vous que les Deployments/StatefulSets disposent de readinessProbes reflétant la disponibilité réelle.
- Ajoutez les annotations et labels Kubernetes que votre monitoring utilise pour suivre les SLO.
Hooks de test
Ajoutez un test Helm simple qui vérifie que l'application répond au trafic de base. Exemple de test dans templates/tests/test-connection.yaml :
apiVersion: v1
kind: Pod
metadata:
name: "{{ include \"myapp.fullname\" . }}-test-connection"
annotations:
"helm.sh/hook": test
spec:
restartPolicy: Never
containers:
- name: curl
image: curlimages/curl:8.7.1
command: ["sh", "-c"]
args:
- |
set -eu
echo "Ping du service..."
curl -fsS http://{{ include "myapp.fullname" . }}:{{ .Values.service.port }}/healthz
Validation de schéma
Incluez values.schema.json pour valider les valeurs fournies par l'utilisateur. Le lint et le dry-run échoueront tôt si une clé est absente ou de mauvais type.
Exemples pratiques d'automatisation
Le motif de base est le même sur toutes les plateformes :
- Prévol :
helm lintethelm template. - Déploiement en préproduction :
helm upgrade --installavec--atomicet un fichier de valeurs de préproduction. - Contrôles de santé :
kubectl rolloutethelm test. - Promotion en production avec le même chart et le tag d'image épinglé.
Voici deux exemples concis. Adaptez les versions et chemins à votre dépôt.
Exemple 1 : GitHub Actions
Ce workflow s'exécute sur les pushes vers main. Il fait le lint, le rendu, un dry-run, déploie en préproduction, vérifie, puis permet une promotion manuelle en production.
name: helm-cicd
on:
push:
branches: [ main ]
workflow_dispatch: {}
jobs:
preflight:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install Helm
run: |
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Lint chart
run: helm lint charts/myapp
- name: Render manifests (template)
run: helm template myapp ./charts/myapp -f values/staging.yaml > rendered.yaml
- name: Dry-run upgrade
run: helm upgrade --install myapp-staging ./charts/myapp -n app-staging -f values/staging.yaml --dry-run --debug
deploy-staging:
needs: preflight
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install Helm
run: |
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Configure kubeconfig
run: |
mkdir -p ~/.kube
echo "$KUBECONFIG_CONTENT" > ~/.kube/config
env:
KUBECONFIG_CONTENT: ${{ secrets.STAGING_KUBECONFIG }}
- name: Deploy to staging (atomic)
run: |
helm upgrade --install myapp-staging ./charts/myapp \
-n app-staging --create-namespace \
-f values/staging.yaml --atomic --timeout 5m --history-max 20
- name: Verify rollout
run: |
kubectl -n app-staging rollout status deploy/myapp --timeout=120s
helm -n app-staging test myapp-staging --logs
promote-production:
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: deploy-staging
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install Helm
run: |
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
- name: Configure kubeconfig
run: |
mkdir -p ~/.kube
echo "$KUBECONFIG_CONTENT" > ~/.kube/config
env:
KUBECONFIG_CONTENT: ${{ secrets.PROD_KUBECONFIG }}
- name: Deploy to production (atomic)
run: |
helm upgrade --install myapp ./charts/myapp \
-n app-prod --create-namespace \
-f values/production.yaml --atomic --timeout 10m --history-max 50
- name: Verify rollout
run: |
kubectl -n app-prod rollout status deploy/myapp --timeout=300s
helm -n app-prod test myapp --logs
Notes :
- Stockez les kubeconfigs ou l'authentification basée sur OIDC de manière sécurisée (l'exemple utilise des secrets chiffrés).
- Le job de production est protégé derrière un
workflow_dispatchmanuel. Remplacez par votre porte d'approbation préférée.
Exemple 2 : GitLab CI/CD
Un pipeline simple basé sur les étapes : prévol -> préproduction -> production.
stages:
- preflight
- staging
- production
variables:
HELM_HISTORY_MAX: "30"
.prep: &prep
before_script:
- apt-get update && apt-get install -y curl ca-certificates
- curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
preflight:
stage: preflight
image: debian:12-slim
<<: *prep
script:
- helm lint charts/myapp
- helm template myapp ./charts/myapp -f values/staging.yaml > rendered.yaml
- helm upgrade --install myapp-staging ./charts/myapp -n app-staging -f values/staging.yaml --dry-run --debug
artifacts:
paths:
- rendered.yaml
staging:
stage: staging
image: debian:12-slim
<<: *prep
script:
- kubectl config set-cluster staging --server=$KUBE_SERVER --certificate-authority=/ca.crt
- kubectl config set-credentials ci --token=$KUBE_TOKEN
- kubectl config set-context staging --cluster=staging --user=ci --namespace=app-staging
- kubectl config use-context staging
- helm upgrade --install myapp-staging ./charts/myapp -n app-staging -f values/staging.yaml --atomic --timeout 5m --history-max $HELM_HISTORY_MAX
- kubectl -n app-staging rollout status deploy/myapp --timeout=120s
- helm -n app-staging test myapp-staging --logs
dependencies:
- preflight
rules:
- if: $CI_PIPELINE_SOURCE == "push"
production:
stage: production
image: debian:12-slim
when: manual
allow_failure: false
<<: *prep
script:
- kubectl config set-cluster prod --server=$KUBE_SERVER --certificate-authority=/ca.crt
- kubectl config set-credentials ci --token=$KUBE_TOKEN
- kubectl config set-context prod --cluster=prod --user=ci --namespace=app-prod
- kubectl config use-context prod
- helm upgrade --install myapp ./charts/myapp -n app-prod -f values/production.yaml --atomic --timeout 10m --history-max $HELM_HISTORY_MAX
- kubectl -n app-prod rollout status deploy/myapp --timeout=300s
- helm -n app-prod test myapp --logs
dependencies:
- staging
Notes :
- Injectez les identifiants Kubernetes via des variables CI masquées ou utilisez un fournisseur d'identité.
- Les artefacts (
rendered.yaml) aident lors des revues et des post-mortems d'incidents.
Vérification et diagnostics
La vérification doit être observable et rapide. Ajoutez ces étapes aux manuels des développeurs et aux logs CI.
Lint, schéma et rendu
helm lint charts/myapp # détecte de nombreux problèmes de chart
helm template myapp charts/myapp -f values/staging.yaml | tee rendered.yaml
Résultat attendu : le lint passe ; rendered.yaml ne contient que des versions d'API supportées par votre cluster.
Dry-run de mise à niveau avec sortie de débogage
helm upgrade --install myapp-staging charts/myapp \
-n app-staging -f values/staging.yaml --dry-run --debug
Résultat attendu : code de sortie 0 ; manifestes affichés ; hooks montrant l'exécution planifiée.
Application et surveillance du déploiement
helm upgrade --install myapp-staging charts/myapp \
-n app-staging -f values/staging.yaml --atomic --timeout 5m
kubectl -n app-staging rollout status deploy/myapp --timeout=120s
Résultat attendu : message « Deployment successfully rolled out ».
Exécution des tests Helm
helm -n app-staging test myapp-staging --logs
Résultat attendu : le pod de test se termine avec la phase Succeeded et retourne la sortie attendue.
Inspection de l'état en direct si quelque chose semble anormal
kubectl -n app-staging get pods,svc,ingress
kubectl -n app-staging describe deploy/myapp
kubectl -n app-staging get events --sort-by=.lastTimestamp | tail -n 50
kubectl -n app-staging logs deploy/myapp --all-containers --tail=200
Confirmer ce qu'Helm a appliqué
helm -n app-staging get manifest myapp-staging | less
helm -n app-staging history myapp-staging
Ces commandes, combinées aux artefacts (rendered.yaml) et aux logs CI, forment votre boîte à outils de triage principale.
Modes de défaillance et récupération
Des échecs surviendront. L'essentiel est d'échouer vite en préproduction et de récupérer rapidement partout. Utilisez le tableau ci-dessous comme référence rapide.
| Symptôme | Cause probable | Action immédiate |
|---|---|---|
| Délai de mise à niveau dépassé | Sonde de disponibilité échouant ou pods non planifiables | kubectl describe pods ; revoir les sondes ; augmenter le délai seulement après correction |
| ImagePullBackOff | Mauvais tag ou identifiants de registre manquants | Vérifier le tag d'image dans les valeurs ; vérifier imagePullSecrets et l'accès au registre |
| Hook échoué | Erreur de test ou de hook pre-install | helm -n <ns> get hooks <release> ; corriger le template ou la commande du hook, relancer |
| Bloqué en PendingInstall | Hook bloqué ou problème CRD | kubectl get jobs/hooks ; inspecter les logs ; désinstaller la release et redéployer |
| Échec de mise à niveau CRD | Changement CRD incompatible | Appliquer les mises à jour CRD d'abord ; diviser le changement en deux releases |
Commandes de restauration et récupération
Restauration rapide vers la dernière révision valide :
helm -n app-prod history myapp
helm -n app-prod rollback myapp 12 --wait --atomic
- Choisissez la dernière révision réussie depuis l'historique.
--atomicassure que la restauration elle-même se restaure si elle échoue.
Nettoyage d'une installation ou mise à niveau échouée :
helm -n app-staging status myapp-staging
helm -n app-staging uninstall myapp-staging
# Confirmer le nettoyage
kubectl -n app-staging get all
Relancez la mise à niveau une fois les problèmes pertinents corrigés.
Gestion des CRDs
- Les CRDs ont souvent besoin d'être appliquées séparément des ressources d'application.
- Stratégie : appliquer d'abord le chart ou le manifeste CRD ; puis mettre à niveau le chart d'application. Si les CRDs ont changé de forme, effectuez un déploiement en deux étapes pour éviter de casser les CRs existants.
Problèmes de sonde de disponibilité
Si les déploiements dépassent régulièrement les délais, corrigez la sonde (chemin, port, initialDelaySeconds) pour qu'elle corresponde au comportement réel de démarrage. Évitez de simplement augmenter les délais comme première réponse.
Traces pour post-mortem
Conservez rendered.yaml, les sorties helm get manifest et kubectl events pour les exécutions échouées. Ces éléments accélèrent l'analyse des causes racines et préviennent les incidents répétés.
Liste de contrôle opérationnelle
Utilisez cette liste pour les opérations quotidiennes. Ajustez les noms et délais à votre environnement.
Prévol (par changement)
- Mettre à jour le fichier de valeurs avec un tag d'image épinglé et les réglages spécifiques à l'environnement.
helm lint charts/myapphelm template myapp charts/myapp -f values/staging.yaml > rendered.yaml- Révision par les pairs de
rendered.yamlpour les changements risqués (ingress, securityContext, limites de ressources).
Déploiement en préproduction
helm upgrade --install myapp-staging charts/myapp -n app-staging -f values/staging.yaml --atomic --timeout 5mkubectl -n app-staging rollout status deploy/myapp --timeout=120shelm -n app-staging test myapp-staging --logs- Observer les métriques et logs pour au moins une tranche de trafic si applicable.
Promotion en production
- S'assurer de la même version de chart et du même tag d'image.
helm upgrade --install myapp charts/myapp -n app-prod -f values/production.yaml --atomic --timeout 10mkubectl -n app-prod rollout status deploy/myapp --timeout=300shelm -n app-prod test myapp --logs
En cas d'échec
- Collecter les logs :
kubectl describe, events, ethelm get manifest. - Restaurer rapidement :
helm rollback ... --wait --atomic - Ouvrir un suivi pour corriger la cause racine avant la prochaine promotion.
Hygiène hebdomadaire
- Revoir la profondeur de
helm history; purger si nécessaire. - Valider que
values.schema.jsoncouvre les nouveaux champs. - Confirmer que les versions de cluster et Helm restent dans votre plage testée.
Conclusion
Une configuration CI/CD Helm fiable repose sur de petites étapes vérifiables. Maintenez des versions cohérentes et des environnements clairement délimités. Échouez vite avec le linting, les vérifications de schéma et le templating avant de toucher au cluster. Utilisez des mises à niveau atomiques, des délais explicites et des hooks de test pour garder les déploiements sûrs et observables. Prouvez le succès avec des contrôles concrets et conservez les artefacts pour un triage rapide. Pratiquez la restauration et la récupération pour que l'équipe puisse agir en confiance sous pression.
Prochaines étapes :
- Testez le workflow sur un service en préproduction avec un tag d'image épinglé et un périmètre étroit.
- Mesurez les critères de succès qui comptent pour vous (ex : temps de déploiement, taux d'échec des changements).
- Itérez sur la couverture de
values.schema.jsonet les tests. - Déployez le motif sur d'autres services une fois satisfait de la stabilité.