Aller au contenu principal
KubernetesHelmPackage Manager

Créer et publier son chart Helm

30 min de lecture Apprendre Kubernetes — Chapitre 12

Crée ton propre chart Helm, utilise Helmfile pour orchestrer tes releases et applique les best practices production.

Tu sais installer un chart Helm depuis un repo public. Bien. Mais en entreprise, tu ne te contentes pas de consommer des charts — tu en crées, tu les versionnes, tu les publies et tu les testes dans une CI. Ce chapitre t’emmène de l’autre côté : celui du mainteneur de chart. On va construire un chart de A à Z, le valider, le packager et le pousser dans un registry. C’est la compétence qui fait la différence entre “j’utilise Helm” et “je maîtrise Helm”.

Pourquoi créer ses propres charts

Quand ton équipe gère 15 microservices, tu ne vas pas écrire 15 fois les mêmes manifestes Deployment + Service + Ingress + HPA. Un chart maison te donne un template réutilisable : chaque service hérite de la même structure, des mêmes bonnes pratiques (probes, security context, resource limits), et seul le fichier values.yaml change d’un service à l’autre.

💡 Tip DevOps : Un chart interne bien conçu réduit le temps d’onboarding d’un nouveau microservice de plusieurs heures à quelques minutes. Tu crées un values.yaml, tu helm install, c’est en prod.

L’autre avantage, c’est la gouvernance. Avec un chart centralisé, tu imposes des standards : pas de container root, des limits obligatoires, des labels Kubernetes uniformes. Les développeurs ne peuvent pas “oublier” la sécurité — elle est dans le template.

Comprendre la structure d’un chart

Helm génère un squelette complet avec helm create. Chaque fichier a un rôle précis qu’il faut comprendre avant de modifier quoi que ce soit.

helm create payment-service
# Structure générée :
# payment-service/
# ├── Chart.yaml          # Métadonnées : nom, version, dépendances
# ├── values.yaml         # Valeurs par défaut (ce que l'utilisateur surcharge)
# ├── values.schema.json  # Validation JSON Schema des values
# ├── .helmignore         # Fichiers à exclure du package
# ├── templates/
# │   ├── NOTES.txt       # Message affiché après install
# │   ├── _helpers.tpl    # Fonctions Go réutilisables
# │   ├── deployment.yaml
# │   ├── service.yaml
# │   ├── ingress.yaml
# │   └── tests/
# │       └── test-connection.yaml
# └── charts/             # Dépendances (sous-charts)

Le fichier Chart.yaml porte deux versions distinctes : version (la version du chart lui-même) et appVersion (la version de l’application qu’il déploie). Ne les confonds pas — un fix dans un template sans changement applicatif incrémente version, pas appVersion.

⚠️ Attention : Le values.schema.json est optionnel mais fortement recommandé en production. Sans lui, une typo dans un values.yaml passe silencieusement et provoque un déploiement cassé que tu découvres au runtime.

🧠 À retenir : _helpers.tpl est le cœur de la réutilisabilité. C’est là que tu définis les labels standards, le fullname, les sélecteurs. Chaque template y fait référence — modifie-le en premier.

Commandes essentielles du workflow

Le cycle de vie d’un chart suit un workflow précis : lint → template → test → package → push. Voici les commandes que tu utiliseras quotidiennement.

Pour valider la syntaxe et les bonnes pratiques de ton chart avant même de l’installer :

# Lint strict — détecte les erreurs et les warnings
helm lint ./payment-service --strict

# Rendre les templates sans installer (debug)
helm template payment-service ./payment-service \
  -f values-prod.yaml --debug > rendered.yaml

# Dry-run côté serveur (valide aussi avec l'API Kubernetes)
helm install payment-service ./payment-service \
  --dry-run --debug -f values-prod.yaml

Pour voir ce qui va changer avant un upgrade, le plugin helm-diff est indispensable. Il affiche un diff coloré entre la release actuelle et ce que l’upgrade produirait :

# Installer le plugin une fois
helm plugin install https://github.com/databus23/helm-diff

# Diff avant upgrade — comme un 'terraform plan' pour Helm
helm diff upgrade payment-service ./payment-service \
  -f values-prod.yaml -n production

💡 Tip DevOps : Intègre helm diff dans ta CI comme étape de review. Avant chaque merge, le pipeline génère le diff et le poste en commentaire sur la PR. Zéro surprise en prod.

Pour packager et publier ton chart vers un registry OCI (le standard moderne) :

# Package le chart en .tgz
helm package ./payment-service
# → payment-service-1.2.0.tgz

# Push vers un registry OCI
helm push payment-service-1.2.0.tgz oci://registry.company.com/charts

# Installer depuis le registry OCI
helm install payment-service oci://registry.company.com/charts/payment-service \
  --version 1.2.0 -f values-prod.yaml -n production

Cas concret : chart unifié pour 12 microservices

🔥 Cas réel : Une fintech gère 12 microservices Node.js et Go. Avant Helm, chaque équipe maintenait ses propres manifestes YAML — avec des incohérences partout : certains services tournaient en root, d’autres n’avaient pas de probes, les labels étaient un chaos.

La solution : un chart générique company-service avec un values.schema.json strict. Chaque microservice a uniquement un fichier values.yaml et un Chart.yaml qui référence le chart parent comme dépendance.

Le schema impose les règles non négociables :

# values.yaml du service "payment-api"
replicaCount: 3
image:
  repository: registry.company.com/payment-api
  tag: "2.4.1"
resources:
  requests:
    cpu: "200m"
    memory: "256Mi"
  limits:
    cpu: "500m"
    memory: "512Mi"
probes:
  liveness:
    path: /healthz
  readiness:
    path: /ready
securityContext:
  runAsNonRoot: true
  readOnlyRootFilesystem: true

Le chart parent contient un test Helm qui vérifie que le service répond après déploiement :

# templates/tests/test-health.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "company-service.fullname" . }}-test"
  annotations:
    "helm.sh/hook": test
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
  containers:
    - name: curl
      image: curlimages/curl:8.5.0
      command: ['curl', '-sf', 'http://{{ include "company-service.fullname" . }}:{{ .Values.service.port }}{{ .Values.probes.readiness.path }}']
  restartPolicy: Never

Résultat : le temps de déploiement d’un nouveau microservice est passé de 2 jours à 30 minutes. Un values.yaml + une PR = en staging. Et les standards sécu sont impossibles à contourner — le schema rejette tout values.yaml sans securityContext.

La CI lint, template et teste chaque chart automatiquement. Un helm upgrade --atomic --wait --timeout 5m en prod garantit un rollback automatique si le déploiement échoue.

Pièges fréquents

Helm a des comportements surprenants qui peuvent ruiner ton déploiement si tu ne les connais pas.

helm upgrade sans --reuse-values efface tes values. C’est le piège #1. Si tu fais helm upgrade myapp ./chart sans passer de fichier values, toutes les valeurs custom sont réinitialisées aux defaults. Passe toujours -f values.yaml explicitement.

⚠️ Attention : Le nindent dans les templates est une source infinie de bugs. Un nindent 4 au lieu de nindent 8 produit un YAML invalide — et le message d’erreur de Helm ne pointe pas la bonne ligne. Utilise helm template systématiquement pour visualiser le rendu.

Les secrets en clair dans values.yaml finissent dans Git. Utilise SOPS + Age pour chiffrer les fichiers de values sensibles, ou mieux : External Secrets Operator qui tire les secrets depuis Vault ou AWS Secrets Manager au runtime.

Les hooks Helm s’exécutent dans un ordre précis (pre-install → install → post-install) et ne sont pas supprimés automatiquement. Sans hook-delete-policy, tes Jobs de migration s’accumulent dans le namespace.

🧠 À retenir : --atomic combine --wait + rollback automatique. C’est le flag à mettre partout en production. Si le déploiement échoue (probes qui ne passent pas, CrashLoopBackOff), Helm revient à la version précédente sans intervention.

Exercice : crée et teste ton chart

Mets en pratique tout ce qu’on a vu :

  1. Scaffolding — Lance helm create mon-api et explore la structure générée. Modifie values.yaml pour pointer vers une image nginx:1.27 avec un port 8080.

  2. Validation — Crée un values.schema.json qui rend image.repository et resources.requests obligatoires. Vérifie qu’un helm install --dry-run avec des values incomplètes échoue.

  3. Test — Ajoute un test dans templates/tests/ qui curl le endpoint / de ton service. Installe le chart puis lance helm test mon-api.

  4. Package & publish — Lance helm package ./mon-api, puis pousse le .tgz vers un registry OCI local (tu peux utiliser distribution/distribution en Docker pour un registry de test).

  5. Diff — Modifie le replicaCount dans tes values et utilise helm diff upgrade pour visualiser le changement avant de l’appliquer.

🔥 Cas réel : En entretien DevOps, on te demandera souvent de créer un chart from scratch sur un whiteboard. Cet exercice te prépare exactement à ça.

À retenir

  • helm create génère un squelette complet — comprends chaque fichier avant de modifier
  • values.schema.json est ton garde-fou contre les erreurs de configuration
  • Le workflow standard : lint → template → diff → install/upgrade —atomic
  • Un chart générique partagé entre services impose les standards et accélère les déploiements
  • helm diff avant chaque upgrade — jamais de surprise en prod
  • Les tests Helm (helm test) valident que le déploiement fonctionne réellement, pas juste que le YAML est valide
  • Secrets : SOPS + Age ou External Secrets Operator, jamais en clair dans Git
  • --atomic en prod, toujours — rollback automatique > intervention manuelle à 3h du matin

🖥️ Pratique sur ton propre serveur

Pour suivre Apprendre Kubernetes en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés