I write Helm charts for my clients to help them deploy applications to Kubernetes easier. Often, they ask me if they can reference values in their values.yaml file to avoid duplicate strings. For example, instead of doing something like this:
image: myregistry.io/dev/myImage:1.0
env:
- name: ENVIRONMENT
value: dev
They’d rather do something like this to help organize their values better:
environment: dev
image: myregistry.io/{{ .Values.environment }}/myImage:1.0
env:
- name: ENVIRONMENT
value: “{{ .Values.environment }}”
The truth is that your users can reference values in their values file as shown above, but it requires you as the chart developer to write your charts to support this. You can do this by using the tpl function in your Helm chart templates.
The Tpl Function
To quote the Helm documentation, “The tpl function allows developers to evaluate strings as templates inside a template.” Imagine a Deployment resource template contains the following snippet:
spec:
containers:
- name: main
image: {{ .Values.image }}
env:
{{- toYaml .Values.env | nindent 12 }}
This snippet would not allow your users to reference other values in their values file. If they tried, the result of “helm install” or “helm template” would look like this:
spec:
containers:
- name: main
image: myregistry.io/{{ .Values.environment }}/myImage:1.0
env:
- name: ENVIRONMENT
value: '{{ .Values.environment }}'
As you can see, the template engine rendered the literal value {{ .Values.environment }} instead of the actual setting of that value.
Luckily, fixing this is easy with the tpl function. Here’s a rewritten version of the Deployment snippet using the tpl function:
spec:
containers:
- name: main
image: {{ tpl .Values.image . }}
env:
{{- tpl (toYaml .Values.env) . | nindent 12 }}
Now, when you run “helm install”, the template engine will be able to replace {{ .Values.environment }} with the setting from your values file:
spec:
containers:
- name: main
image: myregistry.io/dev/myImage:1.0
env:
- name: ENVIRONMENT
value: 'dev'
The tpl function uses a similar syntax as the include function, which I discuss in my post about Named Templates. The first argument is the string you want to render as a template, and the second argument is the scope, which will usually be . (dot), unless you are executing tpl inside a loop, in which case you will want to use $ instead.
On the values.yaml side, your users should remember to wrap values in quotes if the string starts with {{. Otherwise, the template engine will throw an error.
Tpl Security Considerations
Keep in mind that tpl is used to render any user input as a template, and can be used for use cases other than simply referencing other Helm values. Consider your user provides the following values file:
environment: dev
image: myregistry.io/{{ .Values.environment }}/myImage:1.0
env:
- name: PODS
value: '{{ lookup "v1" "Pod" "" "" }}'
Is this a malicious input? Maybe, maybe not. Regardless, this input would display all pods in your cluster if the user had permission to do so. Always use proper RBAC in your cluster to prevent users from reading or writing resources they shouldn’t be allowed to.
Thanks For Reading
In this post, you learned how to use the tpl function to allow users to reference values in values files. Are there other Helm topics or tricks you want me to cover? Feel free to leave a comment below!
Very useful. Thanks a lot 🙂