Helm

helm is a package manager for Kubernetes that helps you manage Kubernetes applications. Skaffold natively supports iterative development for projects configured to use helm.

Configuring your Helm Project with Skaffold

Skaffold supports projects set up to deploy with Helm, but certain aspects of the project need to be configured correctly in order for Skaffold to work properly. This guide should demystify some of the nuance around using Skaffold with Helm to help you get started quickly.

Image Configuration

The normal Helm convention for defining image references is through the values.yaml file. Often, image information is configured through an image stanza in the values file, which might look something like this:

project_root/values.yaml

image:
  repository: gcr.io/my-project/my-image
  tag: v1.2.0
  pullPolicy: IfNotPresent

This image would then be referenced in a templated resource file, maybe like this:

project_root/templates/deployment.yaml:

spec:
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: {{ .Values.image.repository }}:{{ .Values.image.tag}}
          imagePullPolicy: {{ .Values.image.pullPolicy }}

IMPORTANT: To get Skaffold to work with Helm, the image key must be configured in the skaffold.yaml.

Associating the Helm image key allows Skaffold to track the image being built, and then configure Helm to substitute it in the proper resource definitions to be deployed to your cluster. In practice, this looks something like this:

build:
  artifacts:
    - image: gcr.io/my-project/my-image # must match in artifactOverrides
deploy:
  helm:
    releases:
    - name: my-release
      artifactOverrides:
        image: gcr.io/my-project/my-image # no tag present!
      imageStrategy:
        helm: {}

The artifactOverrides binds a Helm value key to a build artifact. The imageStrategy configures the image reference strategy for informing Helm of the image reference to a newly built artifact.

Multiple image overrides

To override multiple images (ie a Pod with a side car) you can simply add additional variables. For example, the following helm template:

spec:
  containers:
    - name: firstContainer
      image: "{{.Values.firstContainerImage}}"
      ....
    - name: secondContainer
      image: "{{.Values.secondContainerImage}}"
      ...

can be overriden with:

deploy:
  helm:
    releases:
    - name: my-release
      artifactOverrides:
        firstContainerImage: gcr.io/my-project/first-image # no tag present!
        secondContainerImage: gcr.io/my-project/second-image # no tag present!
      imageStrategy:
        helm: {}

Image reference strategies

Skaffold supports three image reference strategies for Helm:

  1. fqn: provides a fully-qualified image reference (default);
  2. helm: provides separate repository and tag portions (shown above);
  3. helm+explicitRegistry: provides separate registry, repository, and tag portions.

fqn strategy: single fully-qualified name (default)

With the fully-qualified name strategy, Skaffold configures Helm by setting a key to the fully-tagged image reference.

The skaffold.yaml setup:

build:
  artifacts:
    - image: gcr.io/my-project/my-image
deploy:
  helm:
    releases:
      - name: my-chart
        chartPath: helm
        artifactOverrides:
          image: gcr.io/my-project/my-image
        imageStrategy:
          fqn: {}

Note that the fqn strategy is the default and the imageStrategy can be omitted.

The values.yaml (note that Skaffold overrides this value):

image: gcr.io/other-project/other-image:latest

The chart template:

spec:
  containers:
    - name: {{ .Chart.Name }}
      image: "{{.Values.image}}"

Skaffold will invoke

helm install <chart> <chart-path> --set-string image=gcr.io/my-project/my-image:generatedTag@sha256:digest

helm strategy: split repository and tag

Skaffold can be configured to provide Helm with a separate repository and tag. The key used in the artifactOverrides is used as base portion producing two keys {key}.repository and {key}.tag.

The skaffold.yaml setup:

build:
  artifacts:
    - image: gcr.io/my-project/my-image
deploy:
  helm:
    releases:
      - name: my-chart
        chartPath: helm
        artifactOverrides:
          image: gcr.io/my-project/my-image
        imageStrategy:
          helm: {}

The values.yaml (note that Skaffold overrides these values):

image:
  repository: gcr.io/other-project/other-image
  tag: latest

The chart template:

spec:
  containers:
    - name: {{ .Chart.Name }}
      image: "{{.Values.image.repository}}:{{.Values.image.tag}}"

Skaffold will invoke

helm install <chart> <chart-path> --set-string image.repository=gcr.io/my-project/my-image,image.tag=generatedTag@sha256:digest

helm+explicitRegistry strategy: split registry, repository, and tag

Skaffold can also be configured to provide Helm with a separate repository and tag. The key used in the artifactOverrides is used as base portion producing three keys: {key}.registry, {key}.repository, and {key}.tag.

The skaffold.yaml setup:

build:
  artifacts:
    - image: gcr.io/my-project/my-image
deploy:
  helm:
    releases:
      - name: my-chart
        chartPath: helm
        artifactOverrides:
          image: gcr.io/my-project/my-image
        imageStrategy:
          helm:
            explicitRegistry: true

The values.yaml (note that Skaffold overrides these values):

image:
  registry: gcr.io
  repository: other-project/other-image
  tag: latest

The chart template:

spec:
  containers:
    - name: {{ .Chart.Name }}
      image: "{{.Values.image.registry}}/{{.Values.image.repository}}:{{.Values.image.tag}}"

Skaffold will invoke

helm install <chart> <chart-path> --set-string image.registry=gcr.io,image.repository=my-project/my-image,image.tag=generatedTag@sha256:digest

Helm Build Dependencies

The skipBuildDependencies flag toggles whether dependencies of the Helm chart are built with the helm dep build command. This command manipulates files inside the charts subfolder of the specified Helm chart.

If skipBuildDependencies is false then skaffold dev does not watch the charts subfolder of the Helm chart, in order to prevent a build loop - the actions of helm dep build always trigger another build.

If skipBuildDependencies is true then skaffold dev watches all files inside the Helm chart.

skaffold.yaml Configuration

The helm type offers the following options:

Option Description
releases Required a list of Helm releases.
flags additional option flags that are passed on the command line to helm.
hooks describes a set of lifecycle hooks that are executed before and after every deploy.

Each release includes the following fields:

Option Description Default
name Required name of the Helm release. It accepts environment variables via the go template syntax.
chartPath local path to a packaged Helm chart or an unpacked Helm chart directory.
remoteChart refers to a remote Helm chart reference or URL.
valuesFiles paths to the Helm values files. []
artifactOverrides key value pairs where the key represents the parameter used in the --set-string Helm CLI flag to define a container image and the value corresponds to artifact i.e. ImageName defined in Build.Artifacts section. The resulting command-line is controlled by ImageStrategy.
namespace Kubernetes namespace.
version version of the chart.
setValues key-value pairs. If present, Skaffold will send --set flag to Helm CLI and append all pairs after the flag.
setValueTemplates key-value pairs. If present, Skaffold will try to parse the value part of each key-value pair using environment variables in the system, then send --set flag to Helm CLI and append all parsed pairs after the flag.
setFiles key-value pairs. If present, Skaffold will send --set-file flag to Helm CLI and append all pairs after the flag. {}
createNamespace if true, Skaffold will send --create-namespace flag to Helm CLI. --create-namespace flag is available in Helm since version 3.2. Defaults is false.
wait if true, Skaffold will send --wait flag to Helm CLI. false
recreatePods if true, Skaffold will send --recreate-pods flag to Helm CLI when upgrading a new version of a chart in subsequent dev loop deploy. false
skipBuildDependencies should build dependencies be skipped. Ignored for remoteChart. false
useHelmSecrets instructs skaffold to use secrets plugin on deployment. false
repo specifies the helm repository for remote charts. If present, Skaffold will send --repo Helm CLI flag or flags.
upgradeOnChange specifies whether to upgrade helm chart on code changes. Default is true when helm chart is local (has chartPath). Default is false when helm chart is remote (has remoteChart).
overrides key-value pairs. If present, Skaffold will build a Helm values file that overrides the original and use it to call Helm CLI (--f flag).
packaged parameters for packaging helm chart (helm package).
imageStrategy controls how an ArtifactOverrides entry is turned into --set-string Helm CLI flag or flags.