The CNCF Annual Survey published in January 2026 showed that Helm is the second most used CNCF project, second only to Kubernetes itself. The reason is simple: once you start working with Kubernetes, YAML files accumulate fast and managing them keeps getting harder. A single microservice can require a Deployment, a Service, a ConfigMap, and a Secret, and that's before accounting for the different sets you’ll need for your development, staging, and production environments. Helm fixes this by packaging all of your manifests into a single, versioned unit that can be installed, upgraded, and rolled back easily.
In this guide, we'll cover what Helm is, some key concepts, and the main Helm commands you need to know to deploy and manage manifests using it. You’ll walk away with a complete understanding of how to use Helm so you can simplify the YAML mess you might be in.
Prerequisite: Basic familiarity with Kubernetes
What is Helm in Kubernetes?
Helm is a package manager for Kubernetes. Just as apt manages software packages on Linux or brew does on macOS, Helm manages Kubernetes applications and lets you install, upgrade, and roll them back as versioned, reusable units called charts.
The way Helm solves the YAML management problem is easiest to understand through a programming analogy. Bare Kubernetes manifests work fine for a single, static deployment. But the moment you need multiple similar deployments (dev, staging, prod, which may differ only by a few values), you're essentially copy-pasting. Helm solves this the same way classes solve it in object-oriented programming: you define the boilerplate once in a chart, which can include things like the Deployment template, the Service definition, the ConfigMap structure, and then each Helm chart deployment only specifies what's different: the image, the environment variables, the command being run in the pods. Someone installing your chart can also supply their own values file and get a correctly configured deployment for their use case without touching the original templates.
Like Kubernetes, Helm is declarative. You describe which chart to install and what values to pass in and Helm figures out how to get the cluster there and keeps it in that state.
Helm is built around three core concepts: Charts, Releases, and Repositories. We'll look at each of these next.
Key Concepts
Charts
A chart is a self-contained package of Kubernetes resource manifests. It defines everything needed to deploy an application (the Deployment, the Service, the ConfigMap, etc.) along with default values for any configurable settings. When you install a chart, Helm uses those templates and values to generate the actual Kubernetes manifests and applies them to your cluster.
Charts can also declare dependencies on other charts, called subcharts. This makes it possible to build composable application definitions, for example, a chart for a web application might pull in a chart for PostgreSQL and another for Redis rather than having manifests for those dependencies within it.
Releases
Each time you install a chart, Helm creates a release which is a named instance of that chart running in your cluster. If you install the same chart three times under different names, you get three independent releases, each with its own configuration, its own Kubernetes resources, and its own revision history.
It's important to understand that releases are what Helm actually manages. Helm doesn't think in terms of individual deployments or Helm charts when it comes to a Kubernetes cluster. Instead, it tracks releases and uses them to know what's deployed, what version it's at, and how to upgrade or roll back.
Repositories
A repository is a collection of charts hosted at an accessible URL. You add repositories to your local Helm installation and then install charts from them by name. The most widely used public index is Artifact Hub, which aggregates charts from many sources. Most projects that run on Kubernetes publish an official Helm chart there, so in practice you'll rarely need to write a chart from scratch to deploy well-known software like nginx, PostgreSQL, or Prometheus. For example, we also publish a chart for the mirrord Kubernetes operator, which you can find on Artifact Hub here.
What's Inside a Helm Chart
When you clone or create a Helm chart (using helm create chart-name), you get a directory with a specific structure. Here's what a typical chart looks like:
my-chart/
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
├── deployment.yaml
├── service.yaml
├── ...
└── NOTES.txt
Chart.yaml is the chart's metadata file. It declares the chart's name, version, and description, and optionally lists dependencies on other charts.
apiVersion: v2
name: my-chart
description: A Helm chart for my application
version: 0.1.0
appVersion: "1.0.0"
apiVersion here refers to the Helm chart API version, not the Kubernetes API. v2 means the chart requires at least Helm 3 (don’t ask me why they couldn’t have made it simple by just having v3 for Helm 3). If you come across a chart with v1, it was written for Helm 2, which had a different chart format but Helm 3 and later versions still support v1 for backward compatibility.
version is the version of the chart itself. This follows semantic versioning and should be bumped whenever you change the chart by doing things like adding a new template, changing a default value, or updating dependencies. It's independent of what the chart deploys.
appVersion is the version of the application the chart deploys. This is purely for documentation and nothing else since Helm doesn't use it to pull images or make any decisions. You'd typically set it to the container image tag your chart defaults to, so users can tell at a glance what version of the application they're getting. You can update appVersion without changing version, and vice versa.
A good way to think about it is that appVersion tracks the version of the application being deployed, while version tracks releases of the chart itself. If your application is upgraded from 1.0.0 to 1.1.0, you'd update appVersion to reflect that change. If the chart's default image tag is also updated, you'd typically bump the chart version as well, since the chart itself has changed. But if you only modify the chart (for example by adding a new template, changing default values, or updating dependencies) while continuing to deploy the same application version, you'd bump version and leave appVersion unchanged.
values.yaml contains the default configuration for the chart. These are the values users can override at install time. For example:
image:
repository: nginx
tag: "1.25"
replicaCount: 1
templates/ is where the Kubernetes manifests live. Unlike regular YAML, these files use Go template syntax, which lets Helm inject values into them at render time. A template referencing the values above would look like this:
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: app
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
When someone installs this chart and passes --set image.tag=1.26, Helm substitutes that value before applying the manifest to the cluster. This is the mechanism that makes a single chart work across environments without touching the templates themselves.
charts/ is where subchart dependencies are bundled. If your chart depends on PostgreSQL, for example, the PostgreSQL chart will live in this folder.
NOTES.txt is a template file that Helm renders and prints to the terminal after a successful install. Charts typically use it to show how to connect to or use what was just deployed. This is what a simple NOTES.txt could look like:
Thanks for installing {{ .Chart.Name }}.
To get more info, try:
$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
Creating Your Own Chart
Running helm create my-chart scaffolds the directory structure we just walked through, with sensible defaults already filled in. The generated values.yaml comes pre-populated with common settings like replicaCount, image.repository, and image.tag, and templates/ includes a Deployment, Service, Ingress, and a few other Kubernetes resources you might need.
The first thing to do after generating the chart is update values.yaml to reflect your application. Change the image.repository to point to your container image, set a default tag, and remove any values that don't apply. The generated defaults are based on a generic nginx deployment, so most of them will need adjusting.
The templates themselves often need less work. The generated Deployment and Service are wired up to the values in values.yaml using the {{ .Values.* }} syntax we saw earlier, so once your values are correct, the templates usually render correctly without modification. If your application has specific Kubernetes resources it needs that aren’t present or configured in the templates/ directory already, then you'd add those or modify the existing relevant template.
Once you've made your changes, run helm lint my-chart to catch mistakes like invalid YAML, missing required fields, broken template syntax. Then run helm template my-chart to render the templates locally and review the exact Kubernetes manifests that would be applied to the cluster. This is the step where you verify your values are flowing into the right places before anything touches the cluster.
Common Helm Commands
Let's now walk through some common commands you’ll find yourself using when working with Helm. Before you can install a chart, you need to add the repository it lives in. helm repo add registers a repository under a local name:
helm repo add metalbear https://metalbear-co.github.io/charts
Once added, run helm repo update to pull the latest chart index from all registered repositories. Charts are versioned and updated frequently, so it's worth running this before installing. To find a chart:
helm search repo mirrord-operator
This returns matching charts with their versions and descriptions. You can also browse Artifact Hub to discover charts. Each listing there shows the helm repo add command you need.
helm install deploys a chart as a named release:
helm install mirrord-operator metalbear/mirrord-operator
Helm renders the chart's templates, applies the resulting manifests to the cluster, and begins tracking the deployment as a release named mirrord-operator. It also prints the chart's NOTES.txt which typically has instructions for what to do after installing the chart.
Note: The chart used in the example above installs the mirrord operator which allows multiple developers to develop against the same cluster when using mirrord.
To see all releases currently running in the cluster:
helm list
To inspect a specific release and see its status and revision number:
helm status mirrord-operator
Customizing with Values
By default, helm install uses the values defined in the chart's values.yaml. You can override them in two ways. For quick changes, use --set:
helm install mirrord-operator metalbear/mirrord-operator --set license.key=ABC-DEF-GHI
For environment-specific configuration, a values file is easier to manage. Create a custom-values.yaml with only the values you want to override, then pass it with -f:
helm install mirrord-operator metalbear/mirrord-operator -f values.yaml
When both are used together, --set takes precedence over -f, which takes precedence over the chart's values.yaml defaults. To see all the values a chart allows you to configure you can run this command:
helm show values metalbear/mirrord-operator
When you want to update a release to a newer chart version and/or change its values use helm upgrade:
helm upgrade mirrord-operator metalbear/mirrord-operator --set limits.cpu=400m
Helm applies only what changed, creates a new revision, and preserves the previous one. To see the full revision history:
helm history mirrord-operator
If an upgrade causes problems, helm rollback reverts a release to an earlier revision:
helm rollback mirrord-operator 1
It's important to understand that a rollback creates a new revision rather than deleting the failed one which means the history stays intact so you can always see what happened.
helm uninstall removes all Kubernetes resources that belong to a release:
helm uninstall mirrord-operator
By default, Helm also deletes the release's history. To keep it for auditing or future rollbacks, pass --keep-history.
Frequently Asked Helm Questions
Do I have to use Helm with Kubernetes?
You don't strictly need Helm. For a simple application that doesn't change much, managing it with raw kubectl apply and plain YAML manifests works fine. Where Helm becomes worth it is when you're managing multiple environments, deploying the same application more than once, or distributing your application for others to run. Then maintaining separate YAML files per environment costs more in terms of time and effort than just learning Helm.
How do I deploy a Helm Chart on Kubernetes?
First, add the repository the chart lives in and update your local index. Then install the chart with helm install, giving the release a name and pointing to the chart:
helm repo add metalbear https://metalbear-co.github.io/charts
helm repo update
helm install mirrord-operator metalbear/mirrord-operator
If the chart requires custom configuration, pass values with --set for quick overrides or -f your-values.yaml for a full config file. After installing, helm list shows all running releases and helm status <release-name> gives details on a specific one. The Common Helm Commands section above covers all of this in detail.
Next Steps
In this guide, we covered the fundamentals of Helm: charts, releases, and repositories, how chart structure works, and the commands you'll use day to day. These basics are enough to install and manage existing charts and start writing your own charts. If you want to go deeper from here, working toward a Helm certification like Developing Helm Charts (SC104) can be a good way to continue learning Helm. For this and other topics the official Helm documentation is the best place to go.
Or if you don’t want to prepare for a certification but want to learn how to make managing multiple charts across multiple environments easier, Helmfile is the natural next tool to look at. It lets you declaratively define a set of Helm releases as a single unit, with per-environment values and deployment ordering.
Top comments (0)