Helm
Structure
mychart/
Chart.yaml
values.yaml
charts/
templates/
...
Useful commands
helm install full-coral ./mychart
helm install RELEASE_NAME PATH_TO_CHART
helm get manifest full-coral
helm uninstall full-coral
helm install --debug --dry-run full-coral ./mychart
helm dependencies build; helm template ./ -f values.yaml
you can not create template of particular yaml file, only all
Built-in objects
Release
{{ .Release.Name }}
Values
Chart
Files
Capabilities
Template
Values files
The
values.yaml
file in the chartIf this is a subchart, the
values.yaml
file of a parent chartA values file if passed into
helm install
orhelm upgrade
with the-f
flag (helm install -f myvals.yaml ./mychart
)Individual parameters passed with
--set
(such ashelm install --set foo=bar ./mychart
)
Function
functionName arg1 arg2...
For example
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ quote .Values.favorite.drink }}
food: {{ quote .Values.favorite.food }}
Pipeline
Passing a value through 1..N functions (.Values.favorite.food | upper | quote)
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | quote }}
food: {{ .Values.favorite.food | upper | quote }}
Useful function default
default
drink: {{ .Values.favorite.drink | default "tea" | quote }}
the
default
command is perfect for computed values, which cannot be declared insidevalues.yaml
drink: {{ .Values.favorite.drink | default (printf "%s-tea" (include "fullname" .)) }}
Useful function lookup
The lookup
function can be used to look up resources in a running cluster. The synopsis of the lookup function is lookup apiVersion, kind, namespace, name -> resource or resource list
.
kubectl get pod mypod -n mynamespace
lookup "v1" "Pod" "mynamespace" "mypod"
kubectl get pods -n mynamespace
lookup "v1" "Pod" "mynamespace" ""
kubectl get pods --all-namespaces
lookup "v1" "Pod" "" ""
kubectl get namespace mynamespace
lookup "v1" "Namespace" "" "mynamespace"
kubectl get namespaces
lookup "v1" "Namespace" "" ""
Flow control
Helm's template language provides the following control structures:
if
/else
for creating conditional blocks
if
/else
for creating conditional blocks{{ if PIPELINE }}
# Do something
{{ else if OTHER PIPELINE }}
# Do something else
{{ else }}
# Default case
{{ end }}
A pipeline is evaluated as false if the value is:
a boolean false
a numeric zero
an empty string
a
nil
(empty or null)an empty collection (
map
,slice
,tuple
,dict
,array
)
Whitespaces may be tricky while rendering a temple
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{- if eq .Values.favorite.drink "coffee" }}
mug: "true"
{{- end }}
you may sometimes find it useful to use the indent
function ({{ indent 2 "mug:true" }}
)
with
to specify a scope
with
to specify a scopeapiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
Notice that now we can reference .drink
and .food
without qualifying them. That is because the with
statement sets .
to point to .Values.favorite
. The .
is reset to its previous scope after {{ end }}
.
But here's a note of caution! Inside of the restricted scope, you will not be able to access the other objects from the parent scope using .
. This, for example, will fail:
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ .Release.Name }}
{{- end }}
range
, which provides a "for each"-style loop
Named templates
An important detail to keep in mind when naming templates: template names are global. If you declare two templates with the same name, whichever one is loaded last will be the one used. Because templates in subcharts are compiled together with top-level templates, you should be careful to name your templates with chart-specific names.
These files are used to store partials and helpers. In fact, when we first created mychart
, we saw a file called _helpers.tpl
. That file is the default location for template partials.
define
declares a new named template inside of your templatetemplate
imports a named template
{{- define "mychart.labels" }} // declare using "define"
labels:
generator: helm
date: {{ now | htmlDate }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "mychart.labels" }} // use with a "template"
data:
myvalue: "Hello World"
result looks like
apiVersion: v1
kind: ConfigMap
metadata:
name: running-panda-configmap
labels:
generator: helm
date: 2016-11-02
data:
myvalue: "Hello World"
Conventionally, Helm charts put these templates inside of a partials file, usually _helpers.tpl
. Let's move this function there:
{{/* Generate basic labels */}}
{{- define "mychart.labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}
{{- end }}
block
declares a special kind of fillable template area
Variables
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- $relname := .Release.Name -}}
release: {{ $relname }}
Debugging Templates
Debugging templates can be tricky because the rendered templates are sent to the Kubernetes API server, which may reject the YAML files for reasons other than formatting.
There are a few commands that can help you debug.
helm lint
is your go-to tool for verifying that your chart follows best practiceshelm template --debug
will test rendering chart templates locally.helm install --dry-run --debug
: We've seen this trick already. It's a great way to have the server render your templates, then return the resulting manifest file.helm get manifest
: This is a good way to see what templates are installed on the server.
When your YAML is failing to parse, but you want to see what is generated, one easy way to retrieve the YAML is to comment out the problem section in the template, and then re-run helm install --dry-run --debug
:
apiVersion: v2
# some: problem section
# {{ .Values.foo | quote }}
The above will be rendered and returned with the comments intact:
apiVersion: v2
# some: problem section
# "bar"
This provides a quick way of viewing the generated content without YAML parse errors blocking.
Last updated
Was this helpful?