Advanced Features

Import Configuration Parameters into Helmfile

Helmfile integrates vals to import configuration parameters from following backends:

  • AWS SSM Parameter Store
  • AWS SecretsManager
  • Vault
  • SOPS

See Vals “Suported Backends” for the full list of available backends.

This feature was implemented in https://github.com/roboll/helmfile/pull/906.
If you’re curious how it’s designed and how it works, please consult the pull request.

Deploy Kustomizations with Helmfile

You can deploy kustomize “kustomization”s with Helmfile.

Most of Kustomize operations that is usually done with kustomize edit can be done declaratively via Helm values.yaml files.

Under the hood, Helmfile transforms the kustomization into a local chart in a temporary directory so that it can be helm upgrade --installed.

The transformation is done by generating (1)a temporary kustomization from various options and (2)temporary chart from the temporary kustomization.

An example pseudo code for the transformation logic can be written as:

$ TMPCHART=/tmp/sometmpdir
$ mkdir -p ${TMPCHART}/templates
$ somehow_generate_chart_yaml ${TMPCHART}/Chart.yaml

$ TMPKUSTOMIZATION=/tmp/sometmpdir2
$ somehow_generate_temp_kustomization_yaml ${TMPKUSTOMIZATION}/kustomization.yaml
$ kustomize build ${TMPKUSTOMIZATION}/kustomization.yaml > ${TMPCHART}/templates/all.yaml

Let’s say you have a helmfile.yaml that looks like the below:

releases:
- name: myapp
  chart: mykustomization
  values:
  - values.yaml

Helmfile firstly generates a temporary kustomization.yaml that looks like:

bases:
- $(ABS_PATH_TO_HELMFILE_YAML}/mykustomization

Followed by the below steps:

  • Running kustomize edit set image $IMAGE for every $IMAGE generated from your values.yaml
  • Running kustomize edit set nameprefix $NAMEPREFIX with the nameprefix specified in your values.yaml
  • Running kustomize edit set namesuffix $NAMESUFFIX with the namesuffix specified in your values.yaml
  • Running kustomize edit set namespace $NS with the namespace specified in your values.yaml

A values.yaml file for kustomization would look like the below:

images:
# kustomize edit set image mysql=eu.gcr.io/my-project/mysql@canary
- name: mysql
  newName: eu.gcr.io/my-project/mysql
  newTag: canary
# kustomize edit set image myapp=my-registry/my-app@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
- name: myapp
  digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
  newName: my-registry/my-app

# kustomize edit set nameprefix foo-
namePrefix: foo-

# kustomize edit set namesuffix -bar
nameSuffix: -bar

# kustomize edit set namespace myapp
namespace: myapp

At this point, Helmfile can generate a complete kustomization from the base kustomization you specified in releases[].chart of your helmfile.yaml and values.yaml,
which can be included in the temporary chart.

After all, Helmfile just installs the temporary chart like standard charts, which allows you to manage everything with Helmfile regardless of each app is declared using a Helm chart or a kustomization.

Please also see test/advanced/helmfile.yaml for an example of kustomization support and more.

Adhoc Kustomization of Helm charts

With Helmfile’s integration with Kustomize, not only deploying Kustomization as a Helm chart, you can kustomize charts before installation.

.. Hint:: The following fields can also specify files, in the same manner as
the values field.

Currently, Helmfile allows you to set the following fields for kustomizing the chart:

strategicMergePatches

You can add/update any Kubernetes resource field rendered from a Helm chart by specifying releases[].strategicMergePatches:

repositories:
- name: incubator
  url: https://charts.helm.sh/incubator

releases:
- name: raw1
  chart: incubator/raw
  values:
  - resources:
    - apiVersion: v1
      kind: ConfigMap
      metadata:
        name: raw1
        namespace: default
      data:
        foo: FOO
  strategicMergePatches:
    - apiVersion: v1
      kind: ConfigMap
      metadata:
        name: raw1
        namespace: default
      data:
        bar: BAR

Running helmfile template on the above example results in a ConfigMap called raw whose data is:

foo: FOO
bar: BAR

Please note that the second data field bar is coming from the strategic-merge patch defined in the above helmfile.yaml.

There’s also releases[].jsonPatches that works similarly to strategicMergePatches but has additional capability to remove fields.

Please also see test/advanced/helmfile.yaml for an example of patching support and more.

transformers

You can set transformers to apply Kustomize’s transformers.

Each item can be a path to a YAML or Go template file, or an embedded transformer declaration as a YAML hash.

It’s often used to add common labels and annotations to your resources.

In the below example, we add common annotations and labels every resource rendered from the aws-load-balancer-controller chart:

releases:
- name: "aws-load-balancer-controller"
  namespace: "kube-system"
  forceNamespace: "kube-system"
  chart: "center/aws/aws-load-balancer-controller"
  transformers:
  - apiVersion: builtin
    kind: AnnotationsTransformer
    metadata:
      name: notImportantHere
    annotations:
      area: 51
      greeting: take me to your leader
    fieldSpecs:
    - path: metadata/annotations
      create: true
  - apiVersion: builtin
    kind: LabelTransformer
    metadata:
      name: notImportantHere
    labels:
      foo: bar
    fieldSpecs:
    - path: metadata/labels
      create: true

As explained earlier, transformers can be not only a list of embedded transformers, but also YAML or Go template files, or a mix of those three kinds.

transformers:
# Embedded transformer
- apiVersion: builtin
  kind: AnnotationsTransformer
  metadata:
    name: notImportantHere
  annotations:
    area: 51
    greeting: take me to your leader
  fieldSpecs:
  - path: metadata/annotations
    create: true
# YAML file
- path/to/transformer.yaml
# Go template
# The same set of template parameters as release values files templates is available.
- path/to/transformer.yaml.gotmpl

Please see https://github.com/kubernetes-sigs/kustomize/blob/master/examples/configureBuiltinPlugin.md#configuring-the-builtin-plugins-instead for more information on how to declare transformers.

Adding dependencies without forking the chart

With Helmfile, you can add chart dependencies to a Helm chart without forking it.

An example helmfile.yaml that adds a stable/envoy dependency to the release foo looks like the below:

repositories:
- name: stable
  url: https://charts.helm.sh/stable

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: stable/envoy
    version: 1.5

When Helmfile encounters releases[].dependencies, it creates another temporary chart from ./path/to/foo and adds the following dependencies to the Chart.yaml, so that you don’t need to fork the chart.

dependencies:
- name: envoy
  repo: https://charts.helm.sh/stable
  condition: envoy.enabled

A Helm chart can have two or more dependencies for the same chart with different aliases. To give your dependency an alias, define it like you would do in a standard Chart.yaml:

repositories:
- name: stable
  url: https://charts.helm.sh/stable

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: stable/envoy
    version: 1.5
    alias: bar
  - chart: stable/envoy
    version: 1.5
    alias: baz

which will tweaks the temporary chart’s Chart.yaml to have:

dependencies:
- alias: bar
  name: envoy
  repo: https://charts.helm.sh/stable
  condition: bar.enabled
- alias: baz
  name: envoy
  repo: https://charts.helm.sh/stable
  condition: baz.enabled

Please see #649 for more context around this feature.

After the support for adhoc dependency to local chart (#1765),
you can even write local file paths relative to helmfile.yaml in chart:

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: ./path/to/bar

Internally, Helmfile creates another temporary chart from the local chart ./path/to/foo, and modifies the chart’s Chart.yaml dependencies to look like:

dependencies:
- alias: bar
  name: bar
  repo: file:///abs/path/to/bar
  condition: bar.enabled

Please read https://github.com/roboll/helmfile/issues/1762#issuecomment-816341251 for more details.

OCI chart dependencies

With Helmfile version v0.146.0 or later, you can add OCI chart to chart dependencies.

An example helmfile.yaml that adds a OCI chart dependency to the release foo looks like the below:

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: oci://my-oci-registry/helm-repo/envoy
    version: 1.5

Lockfile per environment

In some cases it can be handy for CI/CD pipelines to be able to roll out updates gradually for environments, such as staging and production while using the same
set of charts. This can be achieved by using lockFilePath in combination with environments, such as:

environments:
  staging:
  production

---
lockFilePath: .helmfile.{{ .Environment.Name}}.lock

releases:
- name: myapp
  chart: charts/myapp