Aug 4, 2020

Managing your Helm deployments with Helmfile

As we’ve been using Kubernetes to build software delivery platforms for our clients, we’ve found Helm to be a reasonable solution to templating and managing deployments to Kubernetes. 

Although templating alternatives such as Kustomize have been gaining popularity, Helm still offers some advantages – notably, a large collection of publicly-available charts for common applications.

As you get started with Helm, often the tutorials have you working with imperative commands, e.g.:

$ helm install my-release ./my-chart

$ helm upgrade my-release ./my-chart

Notice the difficulties we would have here in developing a CD pipeline around this. First, the command differs from the first deployment, to the second deployment. Thankfully, Helm offers an easy way around this:

$ helm upgrade --install my-release ./my-chart

The --install flag will install the release if it has not already been installed.

What to do about values, however?

$ helm upgrade my-release ./my-chart set labelValue=something

helm upgrade … set passes a value into the Helm chart. That value is then persisted and used in future upgrades, even if you don’t use “set”. That wouldn’t work very well in a CI pipeline. Again, Helm has a solution for this:

$ helm upgrade --install my-release ./my-chart --values dev.yaml

When developing a CD pipeline around Kubernetes deployments, we found that every pipeline looked pretty much the same, just different names, and different values. Rather than require each repository to duplicate pipeline logic, we were looking for a declarative (configuration-driven) solution to define desired Helm releases, versions, and values. Enter Helmfile.

Helmfile is a simple wrapper around Helm. You simple add a simple helmfile.yaml file and run helmfile sync — Helmfile will determine whether an install or upgrade is necessary, compile the values, and run Helm.

# helmfile.yaml

releases:
- name: my-release
  chart: ./my-awesome-chart
  values:
  - dev.yaml


It’s a very straightforward tool, but it scratches an itch we had! It also supports a number of other features:

1. Hemfile supports Go templating in values files and helmfile.yaml, so you can look up values at deploy time (e.g., grab a value from a Terraform output or pull from environment)

# helmfile.yaml

{{ $environment := env "ENVIRONMENT" | default "dev" }}
releases:
- name: my-release
chart: ./my-awesome-chart
values:
- {{ $environment }}.yaml

2. You can make uninstalls declarative, in a sense with “installed: false”

# helmfile.yaml

releases:
- name: my-release
  chart: ./my-awesome-chart
  installed: false
  values:
  - {{ $environment }}.yaml


2. Many Helm flags can be specified via the config file, such as “—wait”, “–history-max”, etc.

# helmfile.yaml

helmDefaults:
  wait: true
  historyMax: 3

releases:
- name: my-release
  chart: ./my-awesome-chart
  values:
  - {{ $environment }}.yaml

3. You can specify multiple releases in a single Helmfile:

# helmfile.yaml

# oh yeah, and dynamically specify repositories!
repositories:
- name: bitnami
  url: https://charts.bitnami.com/bitnami

releases:
- name: my-release
  chart: ./my-awesome-chart
  values:
  - {{ $environment }}.yaml
- name: postgres
  chart: bitnami/postgresql
  values:
  - postgres-{{ $environment }}.yaml

4. You can preview the rendered chart output with “helmfile template”.

$ ENVIRONMENT=production helmfile template
Building dependency release=my-release, chart=my-awesome-chart
Templating release=my-release, chart=my-awesome-chart
---
# Source: my-awesome-chart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: me
  labels:
    foo: dev


There are so many more ways to use Helmfile! We’ve been using it successfully for a few years now and it has remained under active development. Need help making your Kubernetes platform production-ready? Reach out!

About the Author

David Norton profile.

David Norton

Director, Platform Engineering

Passionate about continuous delivery, cloud-native architecture, DevOps, and test-driven development.Passionate about continuous delivery, cloud-native architecture, DevOps, and test-driven development.

  • Experienced in cloud infrastructure technologies such as Terraform, Kubernetes, Docker, AWS, and GCP.
  • Background heavy in enterprise JVM technologies such as Groovy, Spring, Spock, Gradle, JPA, Jenkins.
  • Focus on platform transformation, continuous delivery, building agile teams and high-scale applications.
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Designing Kubernetes Controllers
There has been some excellent online discussion lately around Kubernetes controllers, highlighted by an excellent Speakerdeck presentation assembled by Tim Hockin. What I’d like to do in this post is explore some of the implications […]
React Server Components
The React Team recently announced new work they are doing on React Server Components, a new way of rendering React components. The goal is to create smaller bundle sizes, speed up render time, and prevent […]
Jolt custom java transform
Jolt is a JSON to JSON transformation library where the transform is defined in JSON. It’s really good at reorganizing the json data and massaging it into the output JSON you need. Sometimes, you just […]
Page Object Model for UI Testing