Implementing Template Flow Control
1. Using Conditional Statements
| Statement | Description | Example |
|---|---|---|
| has | Checks if a key exists in a map or list | {{- if has "key" .Values.configMap }}<br> Key exists<br>{{- end }} |
| eq | Checks equality between two values | {{- if eq .Values.env "production" }}<br> Production config<br>{{- end }} |
| ne | Checks inequality between two values | {{- if ne .Values.env "development" }}<br> Not development<br>{{- end }} |
| lt, le, gt, ge | Comparison operators for numbers | {{- if lt .Values.replicaCount 3 }}<br> Less than 3 replicas<br>{{- end }} |
| and | Logical AND operator | {{- if and (eq .Values.env "prod") (gt .Values.replicaCount 2) }}<br> Prod with more than 2 replicas<br>{{- end }} |
| or | Logical OR operator | {{- if or (eq .Values.env "dev") (eq .Values.env "staging") }}<br> Dev or staging<br>{{- end }} |
| not | Logical NOT operator | {{- if not (eq .Values.env "production") }}<br> Not production<br>{{- end }} |
Example: Conditional ConfigMap Creation
apiVersion: v1<br>kind: ConfigMap<br>metadata:<br> name: {{ include "myapp.fullname" . }}<br>{{- if .Values.configMap.enabled }}<br>data:<br> config.yaml: |<br> logLevel: {{ .Values.configMap.logLevel }}<br>{{- end }}
Example: Environment-Based Deployment
apiVersion: apps/v1<br>kind: Deployment<br>metadata:<br> name: {{ include "myapp.fullname" . }}<br>spec:<br> replicas: {{- if eq .Values.env "production" }}<br> 5<br> {{- else }}<br> 1<br> {{- end }}
Note: Conditional statements in Helm templates are evaluated during the template rendering phase, not at runtime.
2. Implementing Loops
| Directive | Description | Usage |
|---|---|---|
| .Values.loopItems | List of items to iterate over | loopItems: [ "item1", "item2" ] |
| .Values.loopItem | Current item in loop | name: {{ .Values.loopItem }} |
Example: Looping Over Items
loopItems:
- "app1"
- "app2"
{{- range .Values.loopItems }}
name: {{ . }}
{{- end }}
Example: Looping with Index
{{- range $index, $item := .Values.loopItems }}
{{ $index }}: {{ $item }}
{{- end }}
3. Using with Scope
| Property | Description | Values |
|---|---|---|
| .Values | Values passed to the chart from the user | {} |
| .Release | Information about the release | {name, namespace, revision, status} |
| .Chart | Metadata about the chart | {name, version, appVersion} |
| .Files | Access to files in the chart | {} |
| .Capabilities | Kubernetes version and features supported | {kubernetesVersion, apiVersions} |
| .Template | Information about the current template | {name, basepath} |
Note: The scope is automatically provided by Helm during template rendering and does not need to be explicitly passed.
4. Defining Variables
| Variable Type | Description | Usage Example | Notes |
|---|---|---|---|
| .Values | Root values passed to the chart | {{ .Values.database.host }} |
Accessed via dot notation |
| .Release | Release-specific information | {{ .Release.Name }} |
Includes name, namespace, and revision |
| .Chart | Chart metadata | {{ .Chart.Name }} |
Provides chart name and version |
| .Files | Access to chart files | {{ .Files.Get "config.yaml" }} |
Allows reading of files within the chart |
| .Capabilities | Kubernetes version and features | {{ .Capabilities.KubeVersion }} |
Used for feature detection |
Example: Setting and Using Variables in Values
# values.yaml
database:
host: "db.example.com"
port: 5432
username: "admin"
ingress:
enabled: true
hosts:
- host: "app.example.com"
paths:
- path: /
pathType: Prefix
Example: Using Variables in Templates
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
Note: Variables defined in
values.yaml can be overridden at release time using helm install --set key=value or by providing a custom values file.
5. Checking Value Existence
| Check Type | Description | Example |
|---|---|---|
| hasKey | Checks if a key exists in a map or object | |
| eq | Checks if two values are equal | |
| ne | Checks if two values are not equal | |
| gt | Checks if value is greater than another | |
| lt | Checks if value is less than another | |
| and | Checks if all conditions are true | |
| or | Checks if any condition is true | |
Example: Checking for a specific key in values
{{- if (hasKey .Values "ingress") }}
ingress:
enabled: {{ .Values.ingress.enabled }}
{{- end }}
Example: Using multiple conditions to check existence and value
{{- if (and (hasKey .Values "database") (eq .Values.database.enabled true)) }}
Database is enabled in values
{{- end }}
Note: The
hasKey function is particularly useful when checking for optional configuration sections in Helm charts.
6. Using Boolean Logic
| Operator | Description | Example | Notes |
|---|---|---|---|
| eq | Equal to | {{ eq .Values.image.tag "v1.0" }} |
Compares two values for equality |
| ne | Not equal to | {{ ne .Values.image.tag "v1.0" }} |
Checks if two values are not equal |
| and | Logical AND | {{ and (eq .Values.image.tag "v1.0") (gt .Values.replicaCount 1) }} |
Returns true if all values are truthy |
| or | Logical OR | {{ or (eq .Values.image.tag "v1.0") (eq .Values.image.tag "v2.0") }} |
Returns true if any value is truthy |
| not | Logical NOT | {{ not (eq .Values.image.tag "v1.0") }} |
Negates a boolean value |
| gt | Greater than | {{ gt .Values.replicaCount 3 }} |
Compares two numbers |
| lt | Less than | {{ lt .Values.replicaCount 5 }} |
Compares two numbers |
| ge | Greater than or equal to | {{ ge .Values.replicaCount 3 }} |
Compares two numbers |
| le | Less than or equal to | {{ le .Values.replicaCount 5 }} |
Compares two numbers |
| has | Checks if a key exists in a map | {{ has "image" .Values }} |
Useful for conditional rendering |
Example: Conditional rendering with boolean logic
{{- if (eq .Values.image.tag "v1.0") }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
{{- else if (eq .Values.image.tag "v2.0") }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
{{- else }}
image: {{ .Values.image.repository }}:latest
{{- end }}
Example: Combining conditions with and and or
{{- if (and (eq .Values.env "prod") (ge .Values.replicaCount 3)) }}
replicas: {{ .Values.replicaCount }}
{{- else if (or (eq .Values.env "staging") (eq .Values.env "dev")) }}
replicas: 1
{{- end }}
Note: Boolean logic in Helm templates is evaluated at template rendering time, not during chart installation.
7. Comparing Values
| Operator | Description | Example | Notes |
|---|---|---|---|
| eq | Equal to | {{ eq .Values.key1 .Values.key2 }} |
Compares two values for equality |
| ne | Not equal to | {{ ne .Values.key1 .Values.key2 }} |
Compares two values for inequality |
| lt | Less than | {{ lt .Values.number1 .Values.number2 }} |
Compares numeric values |
| le | Less than or equal to | {{ le .Values.number1 .Values.number2 }} |
Compares numeric values |
| gt | Greater than | {{ gt .Values.number1 .Values.number2 }} |
Compares numeric values |
| ge | Greater than or equal to | {{ ge .Values.number1 .Values.number2 }} |
Compares numeric values |
| and | Logical AND | {{ and (eq .Values.key1 "value") (ne .Values.key2 "other") }} |
Requires all conditions to be true |
| or | Logical OR | {{ or (eq .Values.key1 "value") (eq .Values.key2 "other") }} |
Requires at least one condition to be true |
| not | Logical NOT | {{ not (eq .Values.key1 "value") }} |
Negates a boolean expression |
Example: Using eq in a conditional
{{- if (eq .Values.service.type "LoadBalancer") }}
service:
type: LoadBalancer
port: {{ .Values.service.port }}
{{- else }}
service:
type: ClusterIP
port: {{ .Values.service.port }}
{{- end }}
Example: Using and and or
{{- if (and (eq .Values.env "prod") (gt .Values.replicaCount 3)) }}
replicas: {{ .Values.replicaCount }}
{{- else if (or (eq .Values.env "dev") (eq .Values.env "staging")) }}
replicas: 1
{{- end }}
8. Breaking Loop Iteration
| Directive | Description | Usage |
|---|---|---|
| break | Exits the loop immediately | break; |
Example: Breaking Loop Iteration
{{- range $index, $value := .Values.items }}
{{- if eq $value.name "stop" }}
{{- break }}
{{- end }}
Item: {{ $value.name }}
{{- end }}
9. Handling Empty Values
| Property | Description | Example |
|---|---|---|
| emptyVal | Value to use when a variable is empty or undefined | {{ .Values.emptyVal }} |
| defaultVal | Default value if variable is not set | {{ default "defaultValue" .Values.nullVal }} |
Example: Using default for empty values
{{- $val := default "default-value" .Values.nullVal -}}
{{ $val }}
Example: Conditional rendering with empty values
{{- if .Values.emptyVal -}}
<div>{{ .Values.emptyVal }}</div>
{{- else -}}
<div>No value provided</div>
{{- end -}}
10. Using Complex Conditionals
| Expression Type | Syntax | Description | Notes |
|---|---|---|---|
| .Values.myValue | eq .Values.myValue "production" |
Equality check | Can be used in if statements |
| .Values.env | ne .Values.env "staging" |
Inequality check | Checks if values are not equal |
| .Values.replicaCount | gt .Values.replicaCount 3 |
Greater than | Compares numeric values |
| .Values.memoryLimit | lt .Values.memoryLimit "512Mi" |
Less than | Compares numeric or string values |
| .Values.enabled | and .Values.enabled .Values.debug |
Logical AND | Both conditions must be true |
| .Values.debug | or .Values.debug .Values.verbose |
Logical OR | At least one condition must be true |
| .Values.env | not .Values.env |
Logical NOT | Negates a boolean value |
Example: Complex Conditional Logic
{{- if and (eq .Values.env "production") (gt .Values.replicaCount 3) }}
replicas: {{ .Values.replicaCount }}
{{- else if or (eq .Values.env "staging") (eq .Values.env "development") }}
replicas: 1
{{- else }}
replicas: 0
{{- end }}
Example: Nested Conditionals with Variables
{{- $isProd := eq .Values.env "production" }}
{{- $hasHighReplicas := gt .Values.replicaCount 5 }}
{{- if and $isProd $hasHighReplicas }}
resources:
limits:
cpu: "2"
memory: "4Gi"
{{- else if $isProd }}
resources:
limits:
cpu: "1"
memory: "2Gi"
{{- end }}
Note: Complex conditionals in Helm templates can become hard to read. Consider extracting logic into helper templates or using
include for better maintainability.
11. Implementing Dynamic Resource Creation
Dynamic resource creation in Helm charts allows you to conditionally create Kubernetes resources based on chart values or other runtime conditions. This is particularly useful for creating scalable and flexible deployments.
| Property | Description | Values | Notes |
|---|---|---|---|
| .Values.dynamicResources | Enables or disables dynamic resource creation | true / false |
Default: false |
| .Values.resourceTemplates | List of resource templates to render dynamically | Array of template names | Each template must exist in templates/ |
Example: Conditional Deployment Creation
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}-{{ .Values.dynamicResource.name }}
spec:
replicas: {{ .Values.dynamicResource.replicas }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- include "myapp.podLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
Example: Using Range to Create Multiple Resources
{{- range .Values.dynamicResources }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "myapp.fullname" $ }}-{{ .name }}
data:
config.yaml: |
key: {{ .value }}
{{- end }}
Note: When using dynamic resource creation, ensure that the templates you reference are properly validated to avoid runtime errors during chart installation.