---
layout: docs
page_title: Kubernetes - Deploy with Helm
description: |-
  Waypoint can deploy your applications onto Kubernetes using Helm. Waypoint then tracks and shows you the health of all the resources that the Helm chart created.
---

# Deploying Applications with Helm

Waypoint can deploy your applications onto Kubernetes using [Helm](https://helm.sh/).
Waypoint then tracks and shows you the health of all the resources that
the Helm chart created.

If you're already using Helm, this lets you adopt Waypoint with very little
friction since you can reuse your existing Helm charts for your applications.
Another benefit of using Helm with Waypoint is that you can set chart values
more dynamically, such as setting different settings per environment,
referencing the most recently built artifacts, etc.

-> **Not a Helm user? No problem!** Waypoint supports many other mechanisms
for deploying to Kubernetes. You can use the
[`kubernetes`](/docs/kubernetes/deploy) plugin for highly opinionated, no YAML deployments. Or you can use
[`kubernetes-apply`](/docs/kubernetes/kubectl-deploy) with
a directory of YAML files.

## Why Helm?

The Helm deployment plugin for Waypoint is aimed primarily at people
who either already use Helm or need to use a tool that lets them specify
any custom Kubernetes resources. If you don't know Helm and are just trying
to deploy a typical web service, you can use the YAML-less
[`kubernetes`](/plugins/helm#values) plugin. And you can always switch
deployment plugins later, so you don't need to be worried about making a
"wrong" decision.

For people who are familiar with Helm or would prefer to use Helm,
you might still ask: but why would I use Helm with Waypoint? Why not use
Helm directly? There are many reasons:

1. **Dynamic Chart values.** Waypoint makes it easy to set chart values
   based on dynamic information such as metadata about the most recent
   artifact build, Git commit information, or just computed or templated
   information using [HCL functions](/docs/waypoint-hcl/functions/all).

2. **Environments.** Waypoint handles the higher level multi-environment
   abstraction for you, so you can deploy your chart to multiple environments
   but manage and see them all using the same tool and UI.

3. **Single Workflow Configuration.** While you still have to write Helm charts,
   you can invoke Helm using the same tool you're using to invoke builds,
   release management, etc.

4. **Other Waypoint features.** You can take advantage of other Waypoint features such as [remote operations](/docs/waypoint-hcl/functions/all),
   [logs](/docs/logs), [exec](/docs/exec), [input variables](/docs/waypoint-hcl/variables/input), and more.

## Using Helm with Waypoint

The example below shows a `waypoint.hcl` configuration that uses a
Helm chart in the "helm" directory. We set two Chart values `image.repository`
and `image.tag` to point to the artifact we just built (see
[here for more information on artifact variables](/docs/waypoint-hcl/variables/artifact)). Notice that with the
`set` Chart values, we could use any Waypoint variables, HCL functions, etc.
to dynamically set chart configuration.

```hcl
app "my-app" {
  build {
    use "docker" {}

    registry {
      use "docker" {
        image = "docker.io/myorg/myapp"
        tag   = gitrefpretty()
      }
    }
  }

  deploy {
    use "helm" {
      name  = "my-app"
      chart = "${path.app}/helm"

      set {
        name  = "image.repository"
        value = artifact.image
      }

      set {
        name  = "image.tag"
        value = artifact.tag
      }
    }
  }
}
```

With this set, you can run `waypoint deploy` (if you have an artifact
built already) and Waypoint will use Helm to deploy your application.

-> **Note:** The `set` syntax is the same as the `--set` flag used
with the `helm` CLI. This is documented on the Helm website [here](https://helm.sh/docs/intro/using_helm/#the-format-and-limitations-of---set). You can also specify
[values YAML files](/plugins/helm#values).

### Chart Repositories

The chart doesn't have to be local. You can also use a chart from a
Helm chart repository:

```hcl
deploy {
  use "helm" {
    chart      = "waypoint"
    repository = "https://helm.releases.hashicorp.com"
  }
}
```

## Entrypoint Variables

If you want to use the [Waypoint entrypoint](/docs/entrypoint) functionality,
you must manually inject the [entrypoint environment variables](/docs/entrypoint).
The [opinionated Kubernetes plugin](/docs/kubernetes/deploy) does this
automatically but since with Helm you're writing manual Kubernetes resources with
YAML, we can't automatically inject the environment variables.

A map of the environment variables to set are exposed in the `waypoint.hcl`
as [`entrypoint.env`](/docs/waypoint-hcl/variables/entrypoint). This can be
passed into your Helm chart either as values or templating your YAML templates.
The recommended approach is to use Helm values, to avoid templating a template.

A full example is available [in the `waypoint-examples` repository](https://github.com/hashicorp/waypoint-examples/tree/main/kubernetes/nodejs-helm),
but an incomplete example is shown below to briefly explain the process.

-> **Note:** This also requires that the entrypoint binary is already
injected into the image as part of the build process. This happens automatically
for `docker` or `pack` builders. If you're using an externally built image,
you must [inject the entrypoint manually](/docs/kubernetes/external-build#waypoint-entrypoint-with-external-image-builds).

```hcl
app "my-app" {
  // ...

  deploy {
    use "helm" {
      name  = "my-app"
      chart = "${path.app}/helm"

      // We use a values file so we can set the entrypoint environment
      // variables into a rich YAML structure. This is easier than --set
      values = [
        file(templatefile("${path.app}/values.yaml.tpl")),
      ]

      set {
        name  = "image.repository"
        value = artifact.image
      }

      set {
        name  = "image.tag"
        value = artifact.tag
      }
    }
  }
}
```

And `values.yaml.tpl`:

```yaml
env:
%{ for k,v in entrypoint.env ~}
- name: ${k}
  value: "${v}"
%{ endfor ~}
```

And your Deployment template in your Helm chart:

```yaml
...
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          {{- with .Values.env }}
          env:
          {{- toYaml . | nindent 12 }}
          {{- end }}
```

The key thing we do is setup a `values.yaml` override that templates our
`entrypoint.env` variables. This is then passed into the Helm installation
and used within the deployment template to set the proper environment
variables. This is equivalent to running `helm install` with the `-f` flag
to specify a values YAML file.

## Reference Documentation

To view a full list of the available options for the Helm plugin,
please see the [plugin reference documentation](/plugins/helm).
This documentation is more dense and has less examples, but is an
exhaustive list of the available options.
