Chart Development Tips and Tricks

This guide covers some of the tips and tricks Helm chart developers have learnedwhile building production-quality charts.

Know Your Template Functions

Helm uses Go templates for templating yourresource files. While Go ships several built-in functions, we have added manyothers.

First, we added all of the functions in the Spriglibrary.

We also added two special template functions: include and required. Theinclude function allows you to bring in another template, and then pass theresults to other template functions.

For example, this template snippet includes a template called mytpl, thenlowercases the result, then wraps that in double quotes.

  1. value: {{ include "mytpl" . | lower | quote }}

The required function allows you to declare a particular values entry asrequired for template rendering. If the value is empty, the template renderingwill fail with a user submitted error message.

The following example of the required function declares an entry for.Values.who is required, and will print an error message when that entry ismissing:

  1. value: {{ required "A valid .Values.who entry required!" .Values.who }}

Quote Strings, Don’t Quote Integers

When you are working with string data, you are always safer quoting the stringsthan leaving them as bare words:

  1. name: {{ .Values.MyName | quote }}

But when working with integers do not quote the values. That can, in manycases, cause parsing errors inside of Kubernetes.

  1. port: {{ .Values.Port }}

This remark does not apply to env variables values which are expected to bestring, even if they represent integers:

  1. env:
  2. - name: HOST
  3. value: "http://host"
  4. - name: PORT
  5. value: "1234"

Using the ‘include’ Function

Go provides a way of including one template in another using a built-intemplate directive. However, the built-in function cannot be used in Gotemplate pipelines.

To make it possible to include a template, and then perform an operation on thattemplate’s output, Helm has a special include function:

  1. {{ include "toYaml" $value | indent 2 }}

The above includes a template called toYaml, passes it $value, and thenpasses the output of that template to the indent function.

Because YAML ascribes significance to indentation levels and whitespace, this isone great way to include snippets of code, but handle indentation in a relevantcontext.

Using the ‘required’ function

Go provides a way for setting template options to control behavior when a map isindexed with a key that’s not present in the map. This is typically set withtemplate.Options("missingkey=option"), where option can be default, zero, orerror. While setting this option to error will stop execution with an error,this would apply to every missing key in the map. There may be situations wherea chart developer wants to enforce this behavior for select values in thevalues.yaml file.

The required function gives developers the ability to declare a value entry asrequired for template rendering. If the entry is empty in values.yaml, thetemplate will not render and will return an error message supplied by thedeveloper.

For example:

  1. {{ required "A valid foo is required!" .Values.foo }}

The above will render the template when .Values.foo is defined, but will fail torender and exit when .Values.foo is undefined.

Creating Image Pull Secrets

Image pull secrets are essentially a combination of registry, username, andpassword. You may need them in an application you are deploying, but tocreate them requires running base64 a couple of times. We can write a helpertemplate to compose the Docker configuration file for use as the Secret’spayload. Here is an example:

First, assume that the credentials are defined in the values.yaml file likeso:

  1. imageCredentials:
  2. registry: quay.io
  3. username: someone
  4. password: sillyness

We then define our helper template as follows:

  1. {{- define "imagePullSecret" }}
  2. {{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }}
  3. {{- end }}

Finally, we use the helper template in a larger template to create the Secretmanifest:

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: myregistrykey
  5. type: kubernetes.io/dockerconfigjson
  6. data:
  7. .dockerconfigjson: {{ template "imagePullSecret" . }}

Automatically Roll Deployments

Often times ConfigMaps or Secrets are injected as configuration files incontainers or there are other external dependencies changes that require rollingpods. Depending on the application a restart may be required should those beupdated with a subsequent helm upgrade, but if the deployment spec itselfdidn’t change the application keeps running with the old configuration resultingin an inconsistent deployment.

The sha256sum function can be used to ensure a deployment’s annotation sectionis updated if another file changes:

  1. kind: Deployment
  2. spec:
  3. template:
  4. metadata:
  5. annotations:
  6. checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
  7. [...]

In the event you always want to roll your deployment, you can use a similarannotation step as above, instead replacing with a random string so it alwayschanges and causes the deployment to roll:

  1. kind: Deployment
  2. spec:
  3. template:
  4. metadata:
  5. annotations:
  6. rollme: {{ randAlphaNum 5 | quote }}
  7. [...]

Both of these methods allow your Deployment to leverage the built in updatestrategy logic to avoid taking downtime.

NOTE: In the past we recommended using the —recreate-pods flag as anotheroption. This flag has been marked as deprecated in Helm 3 in favor of the moredeclarative method above.

Tell Helm Not To Uninstall a Resource

Sometimes there are resources that should not be uninstalled when Helm runs ahelm uninstall. Chart developers can add an annotation to a resource toprevent it from being uninstalled.

  1. kind: Secret
  2. metadata:
  3. annotations:
  4. "helm.sh/resource-policy": keep
  5. [...]

(Quotation marks are required)

The annotation "helm.sh/resource-policy": keep instructs Helm to skip thisresource during a helm uninstall operation. However, this resource becomesorphaned. Helm will no longer manage it in any way. This can lead to problems ifusing helm install —replace on a release that has already been uninstalled,but has kept resources.

Using “Partials” and Template Includes

Sometimes you want to create some reusable parts in your chart, whether they’reblocks or template partials. And often, it’s cleaner to keep these in their ownfiles.

In the templates/ directory, any file that begins with an underscore(_) isnot expected to output a Kubernetes manifest file. So by convention, helpertemplates and partials are placed in a _helpers.tpl file.

Complex Charts with Many Dependencies

Many of the charts in the official chartsrepository are “building blocks” for creatingmore advanced applications. But charts may be used to create instances oflarge-scale applications. In such cases, a single umbrella chart may havemultiple subcharts, each of which functions as a piece of the whole.

The current best practice for composing a complex application from discreteparts is to create a top-level umbrella chart that exposes the globalconfigurations, and then use the charts/ subdirectory to embed each of thecomponents.

YAML is a Superset of JSON

According to the YAML specification, YAML is a superset of JSON. That means thatany valid JSON structure ought to be valid in YAML.

This has an advantage: Sometimes template developers may find it easier toexpress a datastructure with a JSON-like syntax rather than deal with YAML’swhitespace sensitivity.

As a best practice, templates should follow a YAML-like syntax unless the JSONsyntax substantially reduces the risk of a formatting issue.

Be Careful with Generating Random Values

There are functions in Helm that allow you to generate random data,cryptographic keys, and so on. These are fine to use. But be aware that duringupgrades, templates are re-executed. When a template run generates data thatdiffers from the last run, that will trigger an update of that resource.

Install or Upgrade a Release with One Command

Helm provides a way to perform an install-or-upgrade as a single command. Usehelm upgrade with the —install command. This will cause Helm to see if therelease is already installed. If not, it will run an install. If it is, then theexisting release will be upgraded.

  1. $ helm upgrade --install <release name> --values <values file> <chart directory>