helm-chart-scaffolding

Par wshobson · agents

Concevez, organisez et gérez des charts Helm pour le templating et le packaging d'applications Kubernetes avec des configurations réutilisables. À utiliser lors de la création de charts Helm, du packaging d'applications Kubernetes ou de la mise en œuvre de déploiements templatisés.

npx skills add https://github.com/wshobson/agents --skill helm-chart-scaffolding

Échafaudage de graphique Helm

Guide complet pour créer, organiser et gérer des graphiques Helm permettant de packager et déployer des applications Kubernetes.

Objectif

Cette skill fournit des instructions étape par étape pour construire des graphiques Helm prêts pour la production, incluant la structure des graphiques, les modèles de templating, la gestion des valeurs et les stratégies de validation.

Quand utiliser cette skill

Utilisez cette skill quand vous devez :

  • Créer de nouveaux graphiques Helm à partir de zéro
  • Packager des applications Kubernetes pour la distribution
  • Gérer des déploiements multi-environnements avec Helm
  • Implémenter le templating pour des manifestes Kubernetes réutilisables
  • Configurer des dépôts de graphiques Helm
  • Suivre les bonnes pratiques et conventions Helm

Présentation de Helm

Helm est le gestionnaire de paquets pour Kubernetes qui :

  • Template les manifestes Kubernetes pour la réutilisabilité
  • Gère les releases et rollbacks des applications
  • Gère les dépendances entre graphiques
  • Fournit le contrôle de version pour les déploiements
  • Simplifie la gestion de configuration à travers les environnements

Flux de travail étape par étape

1. Initialiser la structure du graphique

Créer un nouveau graphique :

helm create my-app

Structure standard du graphique :

my-app/
├── Chart.yaml           # Métadonnées du graphique
├── values.yaml          # Valeurs de configuration par défaut
├── charts/              # Dépendances de graphiques
├── templates/           # Templates de manifestes Kubernetes
│   ├── NOTES.txt       # Notes post-installation
│   ├── _helpers.tpl    # Helpers de template
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── serviceaccount.yaml
│   ├── hpa.yaml
│   └── tests/
│       └── test-connection.yaml
└── .helmignore         # Fichiers à ignorer

2. Configurer Chart.yaml

Les métadonnées du graphique définissent le paquet :

apiVersion: v2
name: my-app
description: A Helm chart for My Application
type: application
version: 1.0.0 # Version du graphique
appVersion: "2.1.0" # Version de l'application

# Mots-clés pour la découverte de graphiques
keywords:
  - web
  - api
  - backend

# Informations de maintenance
maintainers:
  - name: DevOps Team
    email: devops@example.com
    url: https://github.com/example/my-app

# Dépôt du code source
sources:
  - https://github.com/example/my-app

# Page d'accueil
home: https://example.com

# Icône du graphique
icon: https://example.com/icon.png

# Dépendances
dependencies:
  - name: postgresql
    version: "12.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
  - name: redis
    version: "17.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled

Référence : Voir assets/Chart.yaml.template pour un exemple complet

3. Concevoir la structure de values.yaml

Organisez les valeurs hiérarchiquement :

# Configuration de l'image
image:
  repository: myapp
  tag: "1.0.0"
  pullPolicy: IfNotPresent

# Nombre de réplicas
replicaCount: 3

# Configuration du service
service:
  type: ClusterIP
  port: 80
  targetPort: 8080

# Configuration Ingress
ingress:
  enabled: false
  className: nginx
  hosts:
    - host: app.example.com
      paths:
        - path: /
          pathType: Prefix

# Ressources
resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"

# Autoscaling
autoscaling:
  enabled: false
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

# Variables d'environnement
env:
  - name: LOG_LEVEL
    value: "info"

# Données ConfigMap
configMap:
  data:
    APP_MODE: production

# Dépendances
postgresql:
  enabled: true
  auth:
    database: myapp
    username: myapp

redis:
  enabled: false

Référence : Voir assets/values.yaml.template pour la structure complète

4. Créer des fichiers de template

Utiliser le templating Go avec les fonctions Helm :

templates/deployment.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels:
    {{- include "my-app.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-app.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - name: http
          containerPort: {{ .Values.service.targetPort }}
        resources:
          {{- toYaml .Values.resources | nindent 12 }}
        env:
          {{- toYaml .Values.env | nindent 12 }}

5. Créer des helpers de template

templates/_helpers.tpl :

{{/*
Expand the name of the chart.
*/}}
{{- define "my-app.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "my-app.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "my-app.labels" -}}
helm.sh/chart: {{ include "my-app.chart" . }}
{{ include "my-app.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "my-app.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

6. Gérer les dépendances

Ajouter les dépendances dans Chart.yaml :

dependencies:
  - name: postgresql
    version: "12.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

Mettre à jour les dépendances :

helm dependency update
helm dependency build

Surcharger les valeurs des dépendances :

# values.yaml
postgresql:
  enabled: true
  auth:
    database: myapp
    username: myapp
    password: changeme
  primary:
    persistence:
      enabled: true
      size: 10Gi

7. Tester et valider

Commandes de validation :

# Linter le graphique
helm lint my-app/

# Installation en dry-run
helm install my-app ./my-app --dry-run --debug

# Rendu des templates
helm template my-app ./my-app

# Rendu des templates avec valeurs
helm template my-app ./my-app -f values-prod.yaml

# Afficher les valeurs calculées
helm show values ./my-app

Script de validation :

#!/bin/bash
set -e

echo "Linting chart..."
helm lint .

echo "Testing template rendering..."
helm template test-release . --dry-run

echo "Checking for required values..."
helm template test-release . --validate

echo "All validations passed!"

Référence : Voir scripts/validate-chart.sh

8. Packager et distribuer

Packager le graphique :

helm package my-app/
# Crée : my-app-1.0.0.tgz

Créer un dépôt de graphiques :

# Créer l'index
helm repo index .

# Uploader vers le dépôt
# Exemple AWS S3
aws s3 sync . s3://my-helm-charts/ --exclude "*" --include "*.tgz" --include "index.yaml"

Utiliser le graphique :

helm repo add my-repo https://charts.example.com
helm repo update
helm install my-app my-repo/my-app

9. Configuration multi-environnements

Fichiers de valeurs spécifiques à l'environnement :

my-app/
├── values.yaml          # Défauts
├── values-dev.yaml      # Développement
├── values-staging.yaml  # Staging
└── values-prod.yaml     # Production

values-prod.yaml :

replicaCount: 5

image:
  tag: "2.1.0"

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 20

ingress:
  enabled: true
  hosts:
    - host: app.example.com
      paths:
        - path: /
          pathType: Prefix

postgresql:
  enabled: true
  primary:
    persistence:
      size: 100Gi

Installer avec environnement :

helm install my-app ./my-app -f values-prod.yaml --namespace production

10. Implémenter des hooks et des tests

Hook de pré-installation :

# templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-app.fullname" . }}-db-setup
  annotations:
    "helm.sh/hook": pre-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    spec:
      containers:
      - name: db-setup
        image: postgres:15
        command: ["psql", "-c", "CREATE DATABASE myapp"]
      restartPolicy: Never

Test de connexion :

# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "my-app.fullname" . }}-test-connection"
  annotations:
    "helm.sh/hook": test
spec:
  containers:
  - name: wget
    image: busybox
    command: ['wget']
    args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']
  restartPolicy: Never

Exécuter les tests :

helm test my-app

Motifs courants

Motif 1 : Ressources conditionnelles

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "my-app.fullname" . }}
spec:
  # ...
{{- end }}

Motif 2 : Itération sur les listes

env:
{{- range .Values.env }}
- name: {{ .name }}
  value: {{ .value | quote }}
{{- end }}

Motif 3 : Inclusion de fichiers

data:
  config.yaml: |
    {{- .Files.Get "config/application.yaml" | nindent 4 }}

Motif 4 : Valeurs globales

global:
  imageRegistry: docker.io
  imagePullSecrets:
    - name: regcred

# Utilisation dans les templates :
image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}

Bonnes pratiques

  1. Utilisez le versioning sémantique pour les versions du graphique et de l'application
  2. Documentez toutes les valeurs dans values.yaml avec des commentaires
  3. Utilisez des helpers de template pour la logique répétée
  4. Validez les graphiques avant de les packager
  5. Épinglez les versions des dépendances explicitement
  6. Utilisez des conditions pour les ressources optionnelles
  7. Suivez les conventions de nommage (minuscules, tirets)
  8. Incluez NOTES.txt avec les instructions d'utilisation
  9. Ajoutez des labels de manière cohérente en utilisant les helpers
  10. Testez les installations dans tous les environnements

Dépannage

Erreurs de rendu de template :

helm template my-app ./my-app --debug

Problèmes de dépendance :

helm dependency update
helm dependency list

Échecs d'installation :

helm install my-app ./my-app --dry-run --debug
kubectl get events --sort-by='.lastTimestamp'

Skills connexes

  • k8s-manifest-generator - Pour créer des manifestes Kubernetes de base
  • gitops-workflow - Pour les déploiements automatisés de graphiques Helm

Skills similaires