Skip to main content

Templates and Values


1 - Introduction to templates

Helm templates use the Go template engine with Helm-specific extensions.

Basic syntax

# Délimiteurs
{{ }} # Action template
{{- }} # Supprime les espaces avant
{{ -}} # Supprime les espaces après
{{- -}} # Supprime les espaces des deux côtés

# Commentaires
{{/* Ceci est un commentaire */}}

2 - Built-in Objects

2.1 Available objects

ObjectDescription
.ValuesValues from values.yaml and overrides
.ReleaseInformation about the release
.ChartContents of Chart.yaml
.FilesAccess to the chart's files
.CapabilitiesInformation about the cluster
.TemplateInformation about the current template

2.2 .Values

# values.yaml
replicaCount: 3
image:
repository: nginx
tag: "1.25"

# Dans le template
apiVersion: apps/v1
kind: Deployment
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: nginx
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

2.3 .Release

# Propriétés disponibles
{{ .Release.Name }} # Nom de la release
{{ .Release.Namespace }} # Namespace de déploiement
{{ .Release.IsUpgrade }} # true si upgrade
{{ .Release.IsInstall }} # true si installation
{{ .Release.Revision }} # Numéro de révision
{{ .Release.Service }} # Toujours "Helm"

# Exemple
metadata:
name: {{ .Release.Name }}-config
namespace: {{ .Release.Namespace }}
labels:
release: {{ .Release.Name }}

2.4 .Chart

# Propriétés du Chart.yaml
{{ .Chart.Name }} # Nom du chart
{{ .Chart.Version }} # Version du chart
{{ .Chart.AppVersion }} # Version de l'application
{{ .Chart.Description }} # Description
{{ .Chart.Type }} # Type (application/library)

# Exemple
labels:
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}

2.5 .Capabilities

# Informations sur le cluster
{{ .Capabilities.KubeVersion }} # Version K8s complète
{{ .Capabilities.KubeVersion.Major }} # Version majeure
{{ .Capabilities.KubeVersion.Minor }} # Version mineure
{{ .Capabilities.APIVersions.Has "apps/v1" }} # API disponible?

# Exemple conditionnel basé sur la version
{{- if semverCompare ">=1.21" .Capabilities.KubeVersion.Version }}
apiVersion: networking.k8s.io/v1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}
kind: Ingress

2.6 .Files

# Accéder aux fichiers du chart
{{ .Files.Get "config/app.conf" }} # Contenu d'un fichier
{{ .Files.GetBytes "binary/data.bin" }} # Contenu binaire
{{ .Files.Glob "configs/*.yaml" }} # Glob de fichiers

# Exemple: ConfigMap depuis fichier
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
data:
app.conf: |-
{{ .Files.Get "config/app.conf" | indent 4 }}

# Ou plusieurs fichiers
{{- range $path, $content := .Files.Glob "configs/*.yaml" }}
{{ base $path }}: |-
{{ $content | indent 4 }}
{{- end }}

3 - Functions and Pipelines

3.1 Pipelines

Pipelines let you chain functions together:

# Syntaxe pipeline
{{ valeur | fonction1 | fonction2 | fonction3 }}

# Équivalent à
{{ fonction3 (fonction2 (fonction1 valeur)) }}

# Exemples
{{ .Values.name | upper }} # Majuscules
{{ .Values.name | lower | quote }} # Minuscules puis guillemets
{{ .Values.data | toYaml | indent 4 }} # YAML indenté

3.2 String functions

# Manipulation de chaînes
{{ upper "hello" }} # HELLO
{{ lower "HELLO" }} # hello
{{ title "hello world" }} # Hello World
{{ trim " hello " }} # hello
{{ trimSuffix "-" "hello-" }} # hello
{{ trimPrefix "v" "v1.0.0" }} # 1.0.0
{{ quote "hello" }} # "hello"
{{ squote "hello" }} # 'hello'
{{ nospace "hello world" }} # helloworld
{{ trunc 5 "hello world" }} # hello
{{ substr 0 5 "hello world" }} # hello
{{ replace "old" "new" "old text" }} # new text
{{ contains "lo" "hello" }} # true
{{ hasPrefix "he" "hello" }} # true
{{ hasSuffix "lo" "hello" }} # true

# Génération
{{ randAlphaNum 10 }} # Chaîne aléatoire
{{ randNumeric 5 }} # Nombre aléatoire
{{ now | date "2006-01-02" }} # Date formatée
{{ uuidv4 }} # UUID v4

3.3 Conversion functions

# Types
{{ int "123" }} # 123 (int)
{{ int64 "123" }} # 123 (int64)
{{ float64 "1.23" }} # 1.23 (float64)
{{ toString 123 }} # "123"
{{ toJson .Values.config }} # JSON
{{ toYaml .Values.config }} # YAML
{{ toPrettyJson .Values }} # JSON formaté
{{ fromYaml "key: value" }} # Parse YAML
{{ fromJson "{\"k\":\"v\"}" }} # Parse JSON

# Encodage
{{ b64enc "hello" }} # Base64 encode
{{ b64dec "aGVsbG8=" }} # Base64 decode
{{ sha256sum "hello" }} # Hash SHA256

3.4 List functions

# values.yaml
hosts:
- host1.example.com
- host2.example.com
- host3.example.com

# Opérations
{{ first .Values.hosts }} # host1.example.com
{{ last .Values.hosts }} # host3.example.com
{{ rest .Values.hosts }} # [host2, host3]
{{ initial .Values.hosts }} # [host1, host2]
{{ len .Values.hosts }} # 3
{{ has "host1.example.com" .Values.hosts }} # true
{{ without .Values.hosts "host1.example.com" }} # [host2, host3]
{{ concat .Values.hosts (list "host4.com") }} # Fusion

# Création de listes
{{ list "a" "b" "c" }} # [a, b, c]
{{ tuple 1 2 3 }} # (1, 2, 3)

3.5 Dictionary functions

# Opérations sur maps
{{ dict "key1" "val1" "key2" "val2" }} # Créer un dict
{{ get .Values.config "key" }} # Récupérer une clé
{{ set .Values.config "key" "value" }} # Définir une clé
{{ unset .Values.config "key" }} # Supprimer une clé
{{ hasKey .Values.config "key" }} # Vérifier une clé
{{ keys .Values.config }} # Liste des clés
{{ values .Values.config }} # Liste des valeurs
{{ pluck "key" .Values.dict1 .Values.dict2 }} # Extraire de plusieurs dicts
{{ merge .Values.dict1 .Values.dict2 }} # Fusionner

# Exemple pratique
{{- $labels := dict
"app" .Chart.Name
"version" .Chart.Version
"release" .Release.Name
-}}
labels:
{{- toYaml $labels | nindent 2 }}

3.6 Logical functions

# Comparaisons
{{ eq "a" "a" }} # true (égal)
{{ ne "a" "b" }} # true (différent)
{{ lt 1 2 }} # true (inférieur)
{{ le 1 1 }} # true (inférieur ou égal)
{{ gt 2 1 }} # true (supérieur)
{{ ge 2 2 }} # true (supérieur ou égal)

# Logique
{{ and true true }} # true
{{ or false true }} # true
{{ not true }} # false

# Conditions
{{ default "valeur_defaut" .Values.optionnel }}
{{ coalesce .Values.a .Values.b "default" }} # Premier non-vide
{{ empty .Values.maybe }} # true si vide
{{ ternary "oui" "non" true }} # oui (condition ternaire)

4 - Control structures

4.1 if/else conditions

# Syntaxe de base
{{- if condition }}
# contenu
{{- else if autreCondition }}
# autre contenu
{{- else }}
# sinon
{{- end }}

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

# Conditions combinées
{{- if and .Values.postgresql.enabled .Values.redis.enabled }}
# Les deux sont activés
{{- end }}

{{- if or .Values.dev .Values.staging }}
# Environnement non-production
{{- end }}

# Vérifier si une valeur existe
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 2 }}
{{- end }}

4.2 range loops

# Itérer sur une liste
{{- range .Values.hosts }}
- host: {{ . }}
{{- end }}

# Avec index
{{- range $index, $value := .Values.hosts }}
- index: {{ $index }}
host: {{ $value }}
{{- end }}

# Itérer sur un dictionnaire
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}

# Exemple complet
env:
{{- range $key, $value := .Values.environment }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range .Values.envFromSecrets }}
- name: {{ .name }}
valueFrom:
secretKeyRef:
name: {{ .secretName }}
key: {{ .secretKey }}
{{- end }}

4.3 with - Change the scope

# Changer le contexte (.)
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 2 }}
{{- end }}

# Attention: à l'intérieur de with, . change de contexte
{{- with .Values.ingress }}
host: {{ .host }}
# Pour accéder au contexte parent, utilisez $
release: {{ $.Release.Name }}
{{- end }}

4.4 Variables

# Définir une variable
{{- $name := .Values.name -}}
{{- $fullname := include "app.fullname" . -}}

# Utiliser la variable
metadata:
name: {{ $name }}
labels:
app: {{ $fullname }}

# Variable dans une boucle
{{- range $idx, $host := .Values.hosts }}
- name: HOST_{{ $idx }}
value: {{ $host }}
{{- end }}

5 - Define and use named templates

5.1 define and template

{{/* _helpers.tpl */}}

{{/*
Définir un template nommé
*/}}
{{- define "app.labels" -}}
app.kubernetes.io/name: {{ include "app.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Template avec paramètres via dict
*/}}
{{- define "app.servicePort" -}}
{{- $svc := .svc -}}
{{- $port := .port -}}
- port: {{ $port }}
targetPort: {{ $svc.targetPort | default $port }}
protocol: {{ $svc.protocol | default "TCP" }}
name: {{ $svc.name | default "http" }}
{{- end }}
{{/* deployment.yaml */}}
metadata:
labels:
# Utiliser template
{{- template "app.labels" . }}

# Ou include (recommandé car peut être pipeliné)
{{- include "app.labels" . | nindent 4 }}

# Appeler avec des paramètres
ports:
{{- include "app.servicePort" (dict "svc" .Values.service "port" 80) | nindent 2 }}

5.2 Difference between template and include

# template - Ne peut pas être pipeliné
{{- template "app.labels" . }}

# include - Peut être pipeliné (RECOMMANDÉ)
{{- include "app.labels" . | nindent 4 }}
{{- include "app.labels" . | indent 2 }}

6 - Common patterns

6.1 Conditional resource generation

{{/* ingress.yaml */}}
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "app.fullname" . }}
{{- 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 "app.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}

6.2 Checksum for automatic restart

# Redémarrer les pods quand ConfigMap/Secret change
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}

6.3 Resources with defaults

{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 2 }}
{{- else }}
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
{{- end }}

7 - Debugging templates

7.1 Useful commands

# Voir le rendu complet
helm template my-release ./my-chart

# Avec des values spécifiques
helm template my-release ./my-chart -f values-prod.yaml

# Debug verbose
helm template my-release ./my-chart --debug

# Voir un seul template
helm template my-release ./my-chart -s templates/deployment.yaml

# Dry-run contre le cluster
helm install my-release ./my-chart --dry-run --debug

7.2 Debug function

# Afficher une valeur pour debug
{{- $debug := toYaml .Values.config -}}
{{- printf "DEBUG: %s" $debug | fail -}}

# Ou avec un commentaire
# DEBUG: {{ .Values.someValue | toJson }}

Summary

In this chapter, we mastered:

  • The built-in objects (Values, Release, Chart, etc.)
  • Functions and pipelines
  • Control structures (if, range, with)
  • Named templates with define/include
  • Common templating patterns
  • Debugging templates

Next step

In the next chapter, we will explore Helm Repositories.

→ Next chapter: Helm Repositories


← Back to the table of contents