Helm

Running instance of a chart with a specific config is called a release.

Helm tracks an installed chart in the Kubernetes cluster using releases. This allows us to install a single chart multiple times with different releases in a cluster. Releases are stored as Secrets by default in the namespace of the release directly.

We can share charts as archives through repositories. It is basically a location where packages charts can be stored and shared. There is a distributed community chart repository by the name Artifact Hub where we can collaborate. We can also create our own private chart repositories. We can add any number of chart repositories to work with.

Example

The resulting structure will be

Template language

πŸ”— Official reference

How to run below experiment: in generated chart by command helm create remove all files from templates folder and add only below content to file templates/configmap.yaml

{{ .Release.Name }} The values that are passed into a template can be thought of as namespaced objects, where a dot (.) separates each namespaced element. The leading dot before Release indicates that we start with the top-most namespace for this scope. So we could read .Release.Name as "start at the top namespace, find the Release object, then look inside of it for an object called Name".

Chart local render

If rendering fails try to use following command

There are a few commands that can help you debug.

  • helm lint is your go-to tool for verifying that your chart follows best practices

  • helm template --debug will test rendering chart templates locally.

  • helm install --dry-run --debug will also render your chart locally without installing it, but will also check if conflicting resources are already running on the cluster. Setting --dry-run=server will additionally execute any lookup in your chart towards the server.

  • helm get manifest: This is a good way to see what templates are installed on the server.

Built-in objects

πŸ”—More details. This can be references as e.g. {{ .Release.Name }}

  • Release

  • Values. Empty by default, comes from values.yaml file and from user-supplied files

  • Chart: The contents of the Chart.yaml file

  • Subcharts

  • Files

  • Capabilities: This provides information about what capabilities the Kubernetes cluster supports.

  • Template: Contains information about the current template that is being executed

The built-in values always begin with a capital letter.

Values files

This object provides access to values passed into the chart. Its contents come from multiple sources (in order of precedence)

  • The values.yaml file in the chart

  • If this is a subchart, the values.yaml file of a parent chart

  • A values file is passed into helm install or helm upgrade with the -f flag (helm install -f myvals.yaml ./mychart)

  • Individual parameters are passed with --set (such as helm install --set foo=bar ./mychart)

Assuming values.yaml has following content

We can use it inside of the template

If you need to delete a key from the default values, you may override the value of the key to be null

Template Functions and Pipelines

Template functions follow the syntax functionName arg1 arg2...

Helm has over 60 available functions. Some of them are defined by the Go template language itself. Most of the others are part of the Sprig template library.

Pipelines

Like in Unix

Results in

There is a useful command default

the default command is perfect for computed values, which cannot be declared inside values.yaml. For example:

Flow Control

Helm's template language provides the following control structures:

  • if/else for creating conditional blocks

  • with to specify a scope

  • range, which provides a "for each"-style loop

In addition to these, it provides a few actions for declaring and using named template segments:

  • define declares a new named template inside of your template

  • template imports a named template

  • block declares a special kind of fillable template area

if else

Controlling Whitespace

When the template engine runs, it removes the contents inside of {{ and }}, but it leaves the remaining whitespace exactly as is.

The curly brace syntax of template declarations can be modified with special characters to tell the template engine to chomp whitespace. {{- (with the dash and space added) indicates that whitespace should be chomped left, while -}} means whitespace to the right should be consumed. Be careful! Newlines are whitespace!

Lets substitute an * for each whitespace that will be deleted following this rule. An * at the end of the line indicates a newline character that would be removed

The result will be

Sometimes it's easier to tell the template system how to indent for you instead of trying to master the spacing of template directives. For that reason, you may sometimes find it useful to use the indent function ({{ indent 2 "mug:true" }}).

with

Scopes can be changed. with can allow you to set the current scope (.) to a particular object. For example, we've been working with .Values.favorite. Let's rewrite our ConfigMap to alter the . scope to point to .Values.favorite:

The block after with only executes if the value of PIPELINE is not empty.

range

Assuming values.yaml

range changes the scope, thats why we access the value by . in - {{ . | title | quote }} Note. title (title case function)

The result will be

toppings: |- line is declaring a multi-line string. So our list of toppings is actually not a YAML list. It's a big string. Why would we do this? Because the data in ConfigMaps data is composed of key/value pairs, where both the key and the value are simple strings

Variables

Variable values does not respect the present scope, so we can use .Release.Name inside of scope .Values.favorite

Variables are particularly useful in range loops. They can be used on list-like objects to capture both the index and the value:

Note that range comes first, then the variables, then the assignment operator, then the list. This will assign the integer index (starting from zero) to $index and the value to $topping. Running it will produce:

For data structures that have both a key and a value, we can use range to get both. For example, we can loop through .Values.favorite like this:

Now on the first iteration, $key will be drink and $val will be coffee, and on the second, $key will be food and $val will be pizza. Running the above will generate this:

There is one variable that will always point to the root context: - $ -. This can be very useful when you are looping in a range and you need to know the chart's release name.

An example illustrating this:

Named templates

Files whose name begins with an underscore (_) are assumed to not have a k8smanifest inside. These files are not rendered to Kubernetes object definitions, but are available everywhere within other chart templates for use.

Define and template

The define action allows us to create a named template inside of a template file. Its syntax goes like this:

For example, we can define a template to encapsulate a Kubernetes block of labels:

Now we can embed this template inside of our existing ConfigMap, and then include it with the template action:

Conventionally, Helm charts put these templates inside of a partials file, usually _helpers.tpl. Let's move this function there:

By convention, define functions should have a simple documentation block ({{/* ... */}}) describing what they do.

Scopes in template

When a named template (created with define) is rendered, it will receive the scope passed in by the template call. In our example, we included the template like this:

No scope was passed in, so within the template we cannot access anything in .. This is easy enough to fix, though. We simply pass a scope to the template:

include function

Because template is an action, and not a function, there is no way to pass the output of a template call to other functions; the data is simply inserted inline.

Last updated

Was this helpful?