What is Helm in Kubernetes?


Helm is an open-source graduated CNCF project originally created by DeisLabs as a third-party utility, now known as the package manager for Kubernetes, focused on automating the Kubernetes applications lifecycle in a simple and consistent way.

The objective of Helm as package manager is to make an easy and automated management (install, update, or uninstall) of packages for Kubernetes applications, and deploy them with just a few commands.

If you ever wonder how Helm works, how it can be used, or start working with the Helm charts, you can dig more into this article to answer your questions.

What is Helm?

What you'll learn

  • What Helm is and why it's useful

  • How Helm works and how to use it

  • How to create a Helm chart

Why use Helm?

Deploying your applications manually seems complex without using Helm. You will have to define every single YAML configuration, from configuring your workloads to how (and what) you want them to be deployed.

And it’s not only that. After defining and debugging the YAML, think about what will happen after updating the application? You will have to manually remove all created resources and re-deploy them for the new version, which can be slightly mitigated if you create additional files for automation, but that costs additional effort.

Helm is the simplification of this. With Helm, you can simply download your preferred Helm chart, deploy it in the cluster, and update or delete it with low effort. Helm means several benefits for your application:

  • Offers Helm charts and repositories where you get everything necessary for deployment and its configurations.
  • Official Helm charts are up to date and maintained with new releases.
  • Allows you to jump between your preferred versions of the Helm chart.
  • Everything with just a single CLI command.

How does Helm work?

With Helm, you can facilitate the package management, but how are these packages made? And how does Helm communicate with Kubernetes to manage and install these packages?

What is a Helm chart?

We have mentioned Helm charts before, but what are they? Kubernetes applications packages are structured in the Helm packaging format called charts.

A Helm chart is a set of YAML manifests and templates that describes Kubernetes resources (Deployments, Secrets, CRDs, etc.) and defined configurations needed for the Kubernetes application, and is also easy to deploy in a Kubernetes cluster or in a single node with just one command.

The chart keeps its files in a main directory. This directory is what defines the name of the chart and defines the version of the chart package. The chart directory has a specific structure that must be respected, and can also created with helm create command:

  chart.yaml: contains the chart information.
  LICENSE: optional, contains the chart license.
  README.md: optional.
  values.yaml: optional, contains the char values default configuration.
  values.schema.json: optional, defines the structure of values.yaml.
  charts/: contains every chart dependency of the current one.
  crds/: custom resources definitions.
  templates/: templates that combined with values will generate the valid Kubernetes manifests.
   NOTES.txt: optional, intended for usage notes. Code language: JavaScript (javascript)

The chart.yaml is the file that contains all the metadata about the chart, including dependent helm charts:

  • This YAML describes the official Falco chart. Falco is a Cloud Native Runtime Security tool for detecting anomalous activity in your application.
  • The chart.yaml can have two versions, the version tag describes the version of the chart itself and the appVersion indicates the version of the contained application.
  • The dependencies is a list of charts needed for the current one that Helm will download at the moment of installing the chart. Falco has a dependency with falcosidekick, a daemon for connecting Falco to your ecosystem, taking its events and forwarding them to different outputs in a fan-out way.
apiVersion: v2
name: falco
version: 2.0.17
appVersion: 0.32.2
description: Falco #optional
keywords: #optional
  - monitoring
  - security
  - alerting
  - metric
  - troubleshooting
  - run-time
home: https://falco.org  #optional
icon:  #optional https://raw.githubusercontent.com/cncf/artwork/master/projects/falco/horizontal/color/falco-horizontal-color.svg
sources:  #optional
  - https://github.com/falcosecurity/falco
maintainers:  #optional
  - name: The Falco Authors
    email: [email protected]
dependencies:  #optional
  - name: falcosidekick
    version: "0.5.4"
    condition: falcosidekick.enabled
    repository: https://falcosecurity.github.io/chartsCode language: PHP (php)

Helm chart releases

Did you know that your cluster can run different instances of the same chart? Now you do, and those are called Helm chart releases. A release is an instance of your selected chart running on your Kubernetes Cluster.

That means every time that you install a Helm chart there, it creates a new release or instance that coexists with other releases without conflict.

However, the coexistence relation between releases will depend on the Helm chart. For example, with some charts, there can’t be more than one release (e.g., Falco).

What is a Helm chart repository?

Helm charts are the applications for your Kubernetes cluster, but Helm has to get those from somewhere. The Helm chart repository is this “somewhere,” a remote location that contains and offers these chart packages.

The ArtifactHub CNCF sandbox project is the Helm’s official repository (previously known as the official Helm repository on Github, deprecated and discontinued since Nov. 13, 2020). Helm also allows the use of your own hosted repositories, such as the Falco chart repository or the Sysdig Helm Charts repository.

To learn more about what repositories are and how to create and host them, dig into the official Helm guide.

Helm architecture

Helm, internally, is just an executable that you install in your environment to interact with your Kubernetes cluster. There are officially two components in Helm v3:

  • The Helm Client: The CLI for end users. The component in charge of:
    • Local chart development.
    • Managing repositories and releases.
    • Helm Library interaction to execute the users demands (sending charts to be installed or requesting upgrading or uninstalling existing releases).
  • The Helm Library: The logic for Helm operations execution:
    • The component that communicates with the Kubernetes API through the Kubernetes client library.
    • It doesn’t need its own database. Instead, it stores the information in Kubernetes secrets.
    • Combines charts and configurations to build a release.
    • Installs, upgrades, or uninstall charts (and its correspondent resources) to your Kubernetes cluster.
    • Encapsulates the helm logic, which allows portability between different systems.

The Tiller server (deprecated)

Up until the last version of Helm 2 (Helm v2.16.7), an in-cluster server component, called Tiller server, was needed to be installed in the cluster to establish the interaction between the client and the Kubernetes API. This requirement has been removed in Helm 3, fixing some security issues and avoiding unnecessary resource usage.

How to use Helm

Helm commands

The Helm CLI is the component that allows the user to interact with Helm and Kubernetes (through Helm). Here is a list of the most common Helm commands:

Add a Helm Repository

> helm repo add <repository-name> <url>Code language: HTML, XML (xml)

Remove a Helm repository

> helm repo remove <repository-name>Code language: HTML, XML (xml)

Update repositories

> helm repo update

List repositories

> helm repo {list|index}Code language: PHP (php)
  • list: Lists all chart repositories in local.
  • index: Gives an index with the charts of the current directory.

Install a Helm chart

> helm install <application-name> <chart> [--namespace <namespace>] 
[--values <yaml-file|url>] [--dry-run --debug] [--set <field>=<value>]Code language: HTML, XML (xml)
  • [--namespace <namespace>]: Install the app in a specific namespace.
  • [--values <yaml-file|url>]: Overrides the default values file with a given one.
  • [--dry-run --debug]: Runs a test installation to verify the chart.
  • [--set <field>=<value>]: Sets given value to the specified field in values.yaml.

Uninstall a Helm chart release

> helm uninstall <release-name>Code language: HTML, XML (xml)

Upgrade a Helm chart

> helm upgrade <release-name> <chart-name> [--atomic] [--install] [--version <version-number>]Code language: HTML, XML (xml)
  • [--atomic]: Indicates that if the upgrade goes wrong, rollback to the previous version.
  • [--install]: Indicates that if the chart isn’t installed, install it and upgrade it.
  • [--version <version-number>]: Specifies which version the chart will be updated.

List Helm releases

> helm list [--all-namespaces | --namespace <namespace>] [--output <format>] [--filter '<expression>']Code language: CSS (css)
  • --all-namespaces: List releases across all namespaces.
  • --namespace <namespace>: List releases in the specified namespace.
  • [--output <format>]: Prints output in the specified format, <format>: { table | json | yaml }.
  • [--filter '<expression>']: List releases that match with the regex.

Get release history

> helm history <release>Code language: HTML, XML (xml)

Download release information

> helm get {all|hooks|manifest|notes|values} <release>Code language: JavaScript (javascript)
  • all: Downloads all information of the given release.
  • hooks: Downloads the hooks of the given release.
  • manifest: Downloads the manifest of the given release.
  • notes: Downloads the notes of the given release.
  • values: Download the values file of the given release.

You can dig more into Helm commands in the official Helm documentation.

A Helm use case

Continuing with the Falco example, now we will go further and explain how to work with Helm using custom values for it:

$ helm repo add falcosecurity https://falcosecurity.github.io/chartsCode language: JavaScript (javascript)
  • Refresh the local repositories metadata to get the latest version of the carts:
$ helm repo update
$ helm show values falcosecurity/falco
# Driver settings (scenario requirement)
  enabled: true
# -- Tell Falco which driver to use. Available options: module (kernel driver) and ebpf (eBPF probe).
  kind: module
…Code language: PHP (php)
  • Install the Falco chart. Instead of using the Kernel module, we will use the eBPF instrumentation. You can set new values with the --set flag:
$ helm install falco falcosecurity/falco \
    --namespace falco \
    --create-namespace \
    --set driver.kind=ebpfCode language: JavaScript (javascript)
  • If you verify the values.yaml again, you will see that the default driver has changed:
$ helm show values falcosecurity/falco
# Driver settings (scenario requirement)
  enabled: true
# -- Tell Falco which driver to use. Available options: module (kernel driver) and ebpf (eBPF probe).
  kind: ebpf
…Code language: PHP (php)

You can get deeper information about how to install Falco with Helm by checking this out!

Verifying a Helm chart

You can also run the templating engine locally without interacting with the Kubernetes API by using the Helm template command. This is used for debugging and verifying that the chart is defined correctly all without creating anything in Kubernetes:

$ helm template falco falcosecurity/falco --namespace falco --create-namespace --set driver.kind=ebpf
# Source: falco/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
# Source: falco/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
# Source: falco/templates/clusterrole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
# Source: falco/templates/clusterrolebinding.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
# Source: falco/templates/daemonset.yaml
apiVersion: apps/v1
kind: DaemonSetCode language: JavaScript (javascript)

How to create a Helm chart

Let’s create a simple Helm chart to deploy a basic web server that serves a ‘Hello user‘ website. To make it more exciting, we will allow the message, the image name, and the image tag to be customizable via Helm parameters (using {{ .Values.<variable> }} notation).

  • Create the a folder to store the Helm chart and the templates:
$ mkdir -p hello-world/templates/
  • Create a chart.yaml to store the basic information required:
$ cat << EOF > hello-world/Chart.yaml
    apiVersion: v2
    name: hello-world
    description: A Helm chart for Kubernetes
    type: application
    version: 0.0.1
    appVersion: "0.0.1"
    EOFCode language: JavaScript (javascript)
  • Create a ConfigMap where the index.html file is stored:
$ cat << EOF > hello-world/templates/configmap-index.yaml
    apiVersion: v1
      index.html: {{ .Values.message }}
    kind: ConfigMap
      name: {{ .Values.name }}-configmap
  • Create a nginx deployment. The /usr/share/nginx/html/ folder is using the configmap content we previously created:
$ cat << EOF > hello-world/templates/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
      name: {{ .Values.name }}
      namespace: {{ default .Release.Namespace .Values.namespace }}
          app: {{ .Values.name }}
      replicas: {{ .Values.replicaCount }}
            app: {{ .Values.name }}
          - name: {{ .Values.image.repository }}
            image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
            - containerPort: 80
            - mountPath: /usr/share/nginx/html/
              name: index
            - configMap:
                defaultMode: 420
                name: {{ .Values.name }}-configmap
              name: index
    EOFCode language: JavaScript (javascript)
  • Create a values file with some predefined values:
$ cat << EOF > hello-world/values.yaml
    name: "hello-world"
    namespace: ""
    replicaCount: 1
      repository: nginx
      tag: "1.14.2"
    message: "hello world!"
    EOFCode language: JavaScript (javascript)
  • With all of that set, let’s deploy our application with a custom message:
$ helm install hello-world --namespace hello-world --create-namespace --set message="Hola mundo" hello-worldCode language: JavaScript (javascript)
  • Let’s see if it worked:
$ kubectl port-forward -n hello-world $(kubectl get pods -n hello-world -l app=hello-world -o name) 8000:80 &
$ curl localhost:8000
Hola mundoCode language: JavaScript (javascript)


It’s simple and easy. The facilities for creating your own charts and repositories, and the available documentation, are the points that make Helm an excellent package manager for Kubernetes. It is the tool that is a must for every developer that works and develops applications for and with Kubernetes.