Ce guide présente les 10 patterns essentiels pour transformer un chart Helm basique en chart production-ready. Vous apprendrez à ajouter les health probes, les limites de ressources, la sécurité des conteneurs, l’autoscaling, l’Ingress avec TLS, et les hooks. À la fin, votre chart respectera les standards Kubernetes pour la production.
Prérequis
Section intitulée « Prérequis »- Avoir créé un chart basique (voir module H2-01)
- Connaître les concepts Kubernetes : Deployment, Service, ConfigMap
- Comprendre les values et le templating Helm
Vue d’ensemble des patterns
Section intitulée « Vue d’ensemble des patterns »Voici les 10 patterns que tout chart production-ready doit implémenter :
| # | Pattern | Problème résolu | Impact production |
|---|---|---|---|
| 1 | Health Probes | Détection des conteneurs défaillants | Haute dispo, auto-healing |
| 2 | Resources | Conteneurs gourmands, éviction | Stabilité, QoS |
| 3 | SecurityContext | Conteneurs root, failles | Sécurité, compliance |
| 4 | ServiceAccount | Permissions excessives | Principe moindre privilège |
| 5 | ConfigMap | Config en dur dans l’image | Flexibilité, 12-factor |
| 6 | Ingress | Exposition HTTP sans TLS | Accès sécurisé |
| 7 | Autoscaling (HPA) | Charge variable | Élasticité, coûts |
| 8 | Scheduling | Répartition non optimale | HA, performance |
| 9 | PodAnnotations | Intégrations manquantes | Observabilité |
| 10 | Hooks | Migrations, initialisations | Orchestration |
Pattern 1 — Health Probes configurables
Section intitulée « Pattern 1 — Health Probes configurables »Pourquoi des probes ?
Section intitulée « Pourquoi des probes ? »Les probes (sondes) permettent à Kubernetes de vérifier l’état de vos conteneurs :
| Probe | Question posée | Conséquence si échec |
|---|---|---|
livenessProbe | ”Le conteneur est-il vivant ?” | Kubernetes le redémarre |
readinessProbe | ”Le conteneur est-il prêt à recevoir du trafic ?” | Retiré du Service (plus de trafic) |
startupProbe | ”Le conteneur a-t-il fini de démarrer ?” | Les autres probes attendent |
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »livenessProbe: enabled: true httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3
readinessProbe: enabled: true httpGet: path: /readyz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3
startupProbe: enabled: false httpGet: path: /healthz port: http initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 30Décryptage des paramètres :
| Paramètre | Signification | Valeur typique |
|---|---|---|
initialDelaySeconds | Attente avant première vérification | 5-30s selon l’app |
periodSeconds | Intervalle entre vérifications | 10s |
timeoutSeconds | Timeout de la requête | 3s |
failureThreshold | Échecs consécutifs avant action | 3 |
Template avec flag enabled
Section intitulée « Template avec flag enabled »{{- if .Values.livenessProbe.enabled }}livenessProbe: httpGet: path: {{ .Values.livenessProbe.httpGet.path }} port: {{ .Values.livenessProbe.httpGet.port }} initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} failureThreshold: {{ .Values.livenessProbe.failureThreshold }}{{- end }}Rendu obtenu
Section intitulée « Rendu obtenu »helm template test-release mon-api --show-only templates/deployment.yamlExtrait du résultat :
livenessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3readinessProbe: httpGet: path: /readyz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3Pattern 2 — Resources (CPU/Memory)
Section intitulée « Pattern 2 — Resources (CPU/Memory) »Pourquoi définir les resources ?
Section intitulée « Pourquoi définir les resources ? »Sans limites, un conteneur peut consommer toutes les ressources du nœud et impacter les autres applications. Kubernetes utilise les resources pour :
- Requests : réserver des ressources minimales (scheduling)
- Limits : plafonner la consommation (protection)
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »resources: limits: cpu: 200m memory: 256Mi requests: cpu: 100m memory: 128MiNotation des ressources :
| Notation | Signification |
|---|---|
100m | 100 millicores = 0.1 CPU |
1 | 1 CPU complet |
128Mi | 128 Mébioctets |
1Gi | 1 Gibioctet |
Template avec pattern “with”
Section intitulée « Template avec pattern “with” »{{- with .Values.resources }}resources: {{- toYaml . | nindent 2 }}{{- end }}Pourquoi ce pattern ?
- Si
resources: {}(vide), le bloc n’est pas rendu toYamlconvertit l’objet YAML proprementnindent 2ajoute une nouvelle ligne + 2 espaces d’indentation
Rendu obtenu
Section intitulée « Rendu obtenu »resources: limits: cpu: 200m memory: 256Mi requests: cpu: 100m memory: 128MiPattern 3 — SecurityContext
Section intitulée « Pattern 3 — SecurityContext »Pourquoi sécuriser les conteneurs ?
Section intitulée « Pourquoi sécuriser les conteneurs ? »Par défaut, un conteneur peut s’exécuter en root et avoir des privilèges excessifs. Le securityContext applique le principe du moindre privilège.
Deux niveaux de sécurité
Section intitulée « Deux niveaux de sécurité »| Niveau | Scope | Exemple d’usage |
|---|---|---|
podSecurityContext | Tous les conteneurs du pod | fsGroup, runAsNonRoot |
securityContext | Un conteneur spécifique | capabilities, readOnlyRootFilesystem |
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »podSecurityContext: fsGroup: 65534 runAsNonRoot: true
securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 65534 runAsGroup: 65534Décryptage :
| Paramètre | Signification |
|---|---|
runAsNonRoot: true | Refuse de démarrer si le conteneur tente de tourner en root |
runAsUser: 65534 | UID nobody (utilisateur sans privilèges) |
allowPrivilegeEscalation: false | Empêche d’obtenir plus de droits qu’au départ |
capabilities.drop: [ALL] | Supprime toutes les capabilities Linux |
readOnlyRootFilesystem: true | Système de fichiers en lecture seule |
Template
Section intitulée « Template »spec: {{- with .Values.podSecurityContext }} securityContext: {{- toYaml . | nindent 4 }} {{- end }} containers: - name: {{ .Chart.Name }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 8 }} {{- end }}Rendu obtenu
Section intitulée « Rendu obtenu »spec: securityContext: fsGroup: 65534 runAsNonRoot: true containers: - name: mon-api securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65534 runAsNonRoot: true runAsUser: 65534Pattern 4 — ServiceAccount conditionnel
Section intitulée « Pattern 4 — ServiceAccount conditionnel »Pourquoi un ServiceAccount dédié ?
Section intitulée « Pourquoi un ServiceAccount dédié ? »Chaque pod Kubernetes a un ServiceAccount qui définit ses permissions d’accès à l’API Kubernetes. Le compte default est partagé par tous les pods sans SA explicite.
Problème : si vous montez un token dans un pod compromis, l’attaquant hérite des permissions du SA.
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »serviceAccount: create: true automount: false annotations: {} name: ""| Paramètre | Signification |
|---|---|
create | Créer un SA dédié (vs utiliser default) |
automount | Monter automatiquement le token ? (false recommandé) |
annotations | Pour IAM (AWS IRSA, GCP Workload Identity) |
name | Nom personnalisé (sinon généré automatiquement) |
Helper serviceAccountName
Section intitulée « Helper serviceAccountName »{{/*Nom du ServiceAccount à utiliser*/}}{{- define "mon-api.serviceAccountName" -}}{{- if .Values.serviceAccount.create }}{{- default (include "mon-api.fullname" .) .Values.serviceAccount.name }}{{- else }}{{- default "default" .Values.serviceAccount.name }}{{- end }}{{- end }}Logique :
- Si
create: true→ utilise le nom personnalisé ou génère un nom - Si
create: false→ utilise le nom fourni oudefault
Template serviceaccount.yaml
Section intitulée « Template serviceaccount.yaml »{{- if .Values.serviceAccount.create -}}apiVersion: v1kind: ServiceAccountmetadata: name: {{ include "mon-api.serviceAccountName" . }} labels: {{- include "mon-api.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }}automountServiceAccountToken: {{ .Values.serviceAccount.automount }}{{- end }}Rendu obtenu
Section intitulée « Rendu obtenu »Avec serviceAccount.create: true :
apiVersion: v1kind: ServiceAccountmetadata: name: test-release-mon-api labels: helm.sh/chart: mon-api-0.2.0 app.kubernetes.io/name: mon-api app.kubernetes.io/instance: test-release app.kubernetes.io/version: "1.0.0" app.kubernetes.io/managed-by: HelmautomountServiceAccountToken: falseAvec serviceAccount.create: false :
helm template test-release mon-api --set serviceAccount.create=false \ --show-only templates/deployment.yaml | grep serviceAccountName serviceAccountName: defaultPattern 5 — ConfigMap dynamique
Section intitulée « Pattern 5 — ConfigMap dynamique »Pourquoi externaliser la configuration ?
Section intitulée « Pourquoi externaliser la configuration ? »Le 12-factor app recommande de stocker la configuration dans l’environnement, pas dans le code. Les ConfigMaps permettent de modifier la config sans rebuilder l’image.
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »config: enabled: true data: LOG_LEVEL: "info" APP_ENV: "production" API_TIMEOUT: "30"Template configmap.yaml
Section intitulée « Template configmap.yaml »{{- if .Values.config.enabled }}apiVersion: v1kind: ConfigMapmetadata: name: {{ include "mon-api.fullname" . }}-config labels: {{- include "mon-api.labels" . | nindent 4 }}data: {{- range $key, $value := .Values.config.data }} {{ $key }}: {{ $value | quote }} {{- end }}{{- end }}Le pattern range expliqué :
range $key, $value := .Values.config.dataparcourt chaque paire clé-valeur{{ $key }}et{{ $value }}sont des variables locales| quotemet la valeur entre guillemets (sécurité YAML)
Injection dans le Deployment
Section intitulée « Injection dans le Deployment »{{- if .Values.config.enabled }}envFrom: - configMapRef: name: {{ include "mon-api.fullname" . }}-config{{- end }}Rendu obtenu
Section intitulée « Rendu obtenu »apiVersion: v1kind: ConfigMapmetadata: name: test-release-mon-api-config labels: helm.sh/chart: mon-api-0.2.0 app.kubernetes.io/name: mon-api app.kubernetes.io/instance: test-release app.kubernetes.io/version: "1.0.0" app.kubernetes.io/managed-by: Helmdata: APP_ENV: "production" LOG_LEVEL: "info"Pattern 6 — Ingress avec TLS optionnel
Section intitulée « Pattern 6 — Ingress avec TLS optionnel »Pourquoi un Ingress ?
Section intitulée « Pourquoi un Ingress ? »L’Ingress expose vos Services HTTP/HTTPS à l’extérieur du cluster avec :
- Routage basé sur le hostname ou le path
- Terminaison TLS
- Annotations pour le controller (rate limiting, auth, etc.)
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »ingress: enabled: false className: nginx annotations: {} hosts: - host: api.example.local paths: - path: / pathType: Prefix tls: []Template ingress.yaml
Section intitulée « Template ingress.yaml »{{- if .Values.ingress.enabled -}}apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: {{ include "mon-api.fullname" . }} labels: {{- include "mon-api.labels" . | nindent 4 }} {{- with .Values.ingress.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }}spec: {{- if .Values.ingress.className }} ingressClassName: {{ .Values.ingress.className }} {{- end }} {{- if .Values.ingress.tls }} tls: {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - {{ . | quote }} {{- end }} secretName: {{ .secretName }} {{- end }} {{- end }} rules: {{- range .Values.ingress.hosts }} - host: {{ .host | quote }} http: paths: {{- range .paths }} - path: {{ .path }} pathType: {{ .pathType }} backend: service: name: {{ include "mon-api.fullname" $ }} port: number: {{ $.Values.service.port }} {{- end }} {{- end }}{{- end }}Points clés du template :
{{- if .Values.ingress.enabled -}}: tout le fichier est conditionnel$pour accéder au contexte global dans les boucles imbriquées- Double
range: une boucle pour les hosts, une pour les paths
Rendu avec TLS
Section intitulée « Rendu avec TLS »helm template test-release mon-api \ --set ingress.enabled=true \ --set 'ingress.annotations.nginx\.ingress\.kubernetes\.io/rewrite-target=/' \ --set 'ingress.tls[0].secretName=api-tls' \ --set 'ingress.tls[0].hosts[0]=api.example.local'Résultat :
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: test-release-mon-api labels: helm.sh/chart: mon-api-0.2.0 app.kubernetes.io/name: mon-api app.kubernetes.io/instance: test-release app.kubernetes.io/version: "1.0.0" app.kubernetes.io/managed-by: Helm annotations: nginx.ingress.kubernetes.io/rewrite-target: /spec: ingressClassName: nginx tls: - hosts: - "api.example.local" secretName: api-tls rules: - host: "api.example.local" http: paths: - path: / pathType: Prefix backend: service: name: test-release-mon-api port: number: 9898Pattern 7 — Autoscaling (HPA)
Section intitulée « Pattern 7 — Autoscaling (HPA) »Pourquoi l’autoscaling ?
Section intitulée « Pourquoi l’autoscaling ? »L’HPA (Horizontal Pod Autoscaler) ajuste automatiquement le nombre de réplicas selon la charge. Avantages :
- Absorber les pics de trafic
- Réduire les coûts en période creuse
- Maintenir la performance
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »autoscaling: enabled: false minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: 80Interaction avec le Deployment
Section intitulée « Interaction avec le Deployment »Quand l’HPA est actif, c’est lui qui gère le nombre de réplicas. Le Deployment ne doit pas définir replicas :
spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }}Template hpa.yaml
Section intitulée « Template hpa.yaml »{{- if .Values.autoscaling.enabled }}apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: {{ include "mon-api.fullname" . }} labels: {{- include "mon-api.labels" . | nindent 4 }}spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: {{ include "mon-api.fullname" . }} minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - type: Resource resource: name: cpu target: type: Utilization averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} {{- end }} {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory target: type: Utilization averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} {{- end }}{{- end }}Rendu obtenu
Section intitulée « Rendu obtenu »helm template test-release mon-api --set autoscaling.enabled=trueExtrait deployment.yaml (sans replicas) :
spec: selector: matchLabels: app.kubernetes.io/name: mon-apihpa.yaml :
apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: test-release-mon-apispec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: test-release-mon-api minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80Pattern 8 — Scheduling (affinity, tolerations, nodeSelector)
Section intitulée « Pattern 8 — Scheduling (affinity, tolerations, nodeSelector) »Pourquoi contrôler le scheduling ?
Section intitulée « Pourquoi contrôler le scheduling ? »Par défaut, Kubernetes place les pods sur n’importe quel nœud disponible. En production, vous voulez :
| Besoin | Solution |
|---|---|
| Pods sur des nœuds spécifiques (SSD, GPU) | nodeSelector |
| Pods sur des nœuds taintés | tolerations |
| Pods répartis sur plusieurs zones | podAntiAffinity |
| Pods co-localisés avec d’autres | podAffinity |
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »nodeSelector: {}
tolerations: []
affinity: {}Template (dans le Deployment)
Section intitulée « Template (dans le Deployment) »{{- with .Values.nodeSelector }}nodeSelector: {{- toYaml . | nindent 8 }}{{- end }}{{- with .Values.affinity }}affinity: {{- toYaml . | nindent 8 }}{{- end }}{{- with .Values.tolerations }}tolerations: {{- toYaml . | nindent 8 }}{{- end }}Exemple : haute disponibilité avec podAntiAffinity
Section intitulée « Exemple : haute disponibilité avec podAntiAffinity »Créez un fichier values-ha.yaml :
replicaCount: 3
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: mon-api topologyKey: kubernetes.io/hostnameRendu :
helm template test-release mon-api -f values-ha.yaml --show-only templates/deployment.yaml | tail -15 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: mon-api topologyKey: kubernetes.io/hostname weight: 100Exemple : nœuds dédiés avec tolerations
Section intitulée « Exemple : nœuds dédiés avec tolerations »helm template test-release mon-api \ --set 'nodeSelector.disktype=ssd' \ --set 'tolerations[0].key=dedicated' \ --set 'tolerations[0].operator=Equal' \ --set 'tolerations[0].value=api' \ --set 'tolerations[0].effect=NoSchedule' nodeSelector: disktype: ssd tolerations: - effect: NoSchedule key: dedicated operator: Equal value: apiPattern 9 — PodAnnotations et PodLabels
Section intitulée « Pattern 9 — PodAnnotations et PodLabels »Pourquoi des annotations sur les pods ?
Section intitulée « Pourquoi des annotations sur les pods ? »Les annotations permettent d’intégrer vos pods avec d’autres outils :
| Outil | Annotation | Usage |
|---|---|---|
| Prometheus | prometheus.io/scrape: "true" | Découverte des métriques |
| Vault | vault.hashicorp.com/agent-inject: "true" | Injection de secrets |
| Istio | sidecar.istio.io/inject: "true" | Service mesh |
| Datadog | ad.datadoghq.com/... | APM et logs |
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »podAnnotations: {}podLabels: {}Template
Section intitulée « Template »template: metadata: {{- with .Values.podAnnotations }} annotations: {{- toYaml . | nindent 8 }} {{- end }} labels: {{- include "mon-api.selectorLabels" . | nindent 8 }} {{- with .Values.podLabels }} {{- toYaml . | nindent 8 }} {{- end }}Exemple : scraping Prometheus
Section intitulée « Exemple : scraping Prometheus »helm template test-release mon-api \ --set 'podAnnotations.prometheus\.io/scrape=true' \ --set 'podAnnotations.prometheus\.io/port=9898' \ --set 'podAnnotations.prometheus\.io/path=/metrics' metadata: annotations: prometheus.io/path: /metrics prometheus.io/port: "9898" prometheus.io/scrape: "true"Pattern 10 — Hooks Helm
Section intitulée « Pattern 10 — Hooks Helm »Quand utiliser les hooks ?
Section intitulée « Quand utiliser les hooks ? »Les hooks exécutent des Jobs à des moments précis du cycle de vie :
| Hook | Moment d’exécution | Cas d’usage |
|---|---|---|
pre-install | Avant l’installation | Vérifications préalables |
post-install | Après l’installation | Seed de données, notifications |
pre-upgrade | Avant la mise à jour | Migrations de BDD |
post-upgrade | Après la mise à jour | Tests de smoke |
pre-delete | Avant la suppression | Backup, nettoyage |
post-delete | Après la suppression | Notification |
Configuration dans values.yaml
Section intitulée « Configuration dans values.yaml »hooks: preInstall: enabled: false image: busybox:1.36 command: "echo 'Running pre-install hook'"Template hook-pre-install.yaml
Section intitulée « Template hook-pre-install.yaml »{{- if .Values.hooks.preInstall.enabled }}apiVersion: batch/v1kind: Jobmetadata: name: {{ include "mon-api.fullname" . }}-pre-install labels: {{- include "mon-api.labels" . | nindent 4 }} annotations: "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-weight": "-5" "helm.sh/hook-delete-policy": hook-succeededspec: template: spec: restartPolicy: Never containers: - name: pre-install image: {{ .Values.hooks.preInstall.image | default "busybox:1.36" }} command: ["sh", "-c", {{ .Values.hooks.preInstall.command | quote }}]{{- end }}Annotations expliquées :
| Annotation | Signification |
|---|---|
helm.sh/hook | Quand exécuter le Job |
helm.sh/hook-weight | Ordre d’exécution (négatif = plus tôt) |
helm.sh/hook-delete-policy | Quand supprimer le Job (hook-succeeded, before-hook-creation, hook-failed) |
Rendu obtenu
Section intitulée « Rendu obtenu »helm template test-release mon-api \ --set hooks.preInstall.enabled=true \ --set 'hooks.preInstall.command=echo "Running migrations"'apiVersion: batch/v1kind: Jobmetadata: name: test-release-mon-api-pre-install annotations: "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-weight": "-5" "helm.sh/hook-delete-policy": hook-succeededspec: template: spec: restartPolicy: Never containers: - name: pre-install image: busybox:1.36 command: ["sh", "-c", "echo \"Running migrations\""]Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
Pod en CrashLoopBackOff | Probe échoue, app pas prête | Augmenter initialDelaySeconds |
Pod OOMKilled | Limite memory dépassée | Augmenter limits.memory |
| Pod ne démarre pas (security) | Image incompatible securityContext | Vérifier UID de l’image |
HPA <unknown> | metrics-server absent | Installer metrics-server |
| Ingress sans effet | IngressController absent | Installer nginx-ingress ou traefik |
| Hook ne s’exécute pas | Mauvaise annotation | Vérifier helm.sh/hook |
Lab B2 — Rendre un chart production-ready
Section intitulée « Lab B2 — Rendre un chart production-ready »-
Partir du chart du Lab B1
Fenêtre de terminal cd /tmp && cp -r mon-api mon-api-prodcd mon-api-prod -
Mettre à jour values.yaml avec les patterns
Ajoutez les sections : probes, resources, securityContext, serviceAccount, autoscaling.
-
Valider avec helm lint
Fenêtre de terminal helm lint . --strict -
Prévisualiser le rendu complet
Fenêtre de terminal helm template my-release . > rendered.yamlcat rendered.yaml -
Tester avec autoscaling activé
Fenêtre de terminal helm template my-release . --set autoscaling.enabled=true | grep -A5 "kind: HorizontalPodAutoscaler" -
Tester avec Ingress et TLS
Fenêtre de terminal helm template my-release . \--set ingress.enabled=true \--set 'ingress.tls[0].secretName=my-tls' \--set 'ingress.tls[0].hosts[0]=api.example.local' -
Installer et vérifier sur le cluster
Fenêtre de terminal kubectl create namespace lab-b2helm install my-api . -n lab-b2kubectl get all,sa,cm -n lab-b2 -
Vérifier le securityContext du pod
Fenêtre de terminal kubectl get pod -n lab-b2 -o jsonpath='{.items[0].spec.containers[0].securityContext}' | jq -
Nettoyer
Fenêtre de terminal helm uninstall my-api -n lab-b2kubectl delete namespace lab-b2
Critères de réussite :
- Probes configurées et activées
- Resources limits/requests présents
- SecurityContext appliqué (runAsNonRoot, drop ALL capabilities)
- ServiceAccount créé avec automount: false
- HPA généré quand autoscaling.enabled=true
- Ingress avec TLS quand activé
- Pod Running avec securityContext vérifié
À retenir
Section intitulée « À retenir »- Les probes garantissent que Kubernetes détecte les conteneurs défaillants
- Les resources protègent le cluster contre les conteneurs gourmands
- Le securityContext applique le principe du moindre privilège
- L’Ingress expose vos services avec TLS et routage intelligent
- Le HPA adapte automatiquement le nombre de réplicas à la charge
- Les hooks permettent d’orchestrer des actions au bon moment
- Le pattern
{{- with .Values.xxx }}évite de rendre des blocs vides - Utilisez
$pour accéder au contexte global dans les bouclesrange