Helm Charts in Kubernetes
Learn how Helm packages a whole application into one versioned chart, fills in the blanks with your settings, and installs, upgrades, and rolls it back with a few simple steps, and how to use it safely in real teams.
Imagine ordering a meal kit. The box arrives with all the ingredients measured out, a recipe card, and a small form where you choose how spicy you want it and how many people it should feed. You do not go shopping for twenty separate items or invent the recipe yourself. You pick your options, follow the card, and the same dish comes out right every time, whether you cook it in a small flat or a big family kitchen.
A Helm chart is a meal kit for Kubernetes applications. It bundles every file an application needs, along with a set of choices you can change, so the whole thing can be installed, updated, and removed as one unit. This tutorial explains Helm from the ground up, shows what happens inside it during an install and an upgrade, and gives you the patterns, warnings, and habits that working teams rely on.
1Why Deploying to Kubernetes Gets Messy
Kubernetes is powerful, but describing a real application to it takes many files. To see why Helm exists, we first need to feel that pain.
Applications are described in many files
Kubernetes is a system that runs your programs, packaged as containers, across many computers. You tell Kubernetes what you want by writing manifests. A manifest is a text file, usually in a format called YAML, that describes one thing you want, such as a running program, a network address, or a piece of configuration.
A simple web application often needs many manifests. One describes the running program, called a Deployment. One gives it a stable network address, called a Service. One holds its settings, called a ConfigMap. One holds its passwords, called a Secret. One lets outside visitors reach it, called an Ingress. A real application can easily have ten to thirty such files.
The same application, many environments
Teams rarely run one copy of an application. There is a development copy, a testing copy, and a production copy, and each differs slightly. Production may run ten replicas, testing only one. Each environment has its own web address, its own database location, and its own memory limits. The bulk of the files are identical, but a handful of values change.
Without a tool, teams copy the whole folder of files for each environment and edit the differences by hand. Over time the copies drift apart. A fix made in one is forgotten in another. Nobody is sure which environment matches which version of the application.
Imagine moving house with all your belongings in loose piles instead of labelled boxes. You have no list of what is where, you cannot tell whether something is missing, and if you must move again, you must sort everything from scratch. A packaging system that puts everything into numbered, labelled boxes makes the same move easy and repeatable.
The daily pains Helm was built to solve
Too Many Files
Installing one application means applying many separate manifests in the right order, and remembering all of them later.
Repetition Across Environments
Development, testing, and production need nearly the same files with a few differences, which leads to copy-and-paste drift.
No Version of the Whole
Kubernetes tracks each object, but nothing says “these thirty files together are version 1.4 of my application”.
Hard Upgrades and Rollbacks
Changing many objects together, and undoing the change if it fails, is slow and error-prone when done by hand.
Sharing Is Awkward
Installing common tools, such as a database or a monitoring system, means copying dozens of files from someone else.
Cleaning Up
Removing an application completely means finding and deleting every object it created, without missing any.
All six pains come from treating an application as a pile of unrelated files. Helm treats it as one named, versioned package with adjustable settings, and remembers what it installed, so the whole thing can be managed together.
2Helm: The Core Idea
Helm is the package manager for Kubernetes. It rests on three simple ideas: a chart, your values, and a release.
The idea in plain words
You may know a package manager from your phone or computer, such as an app store. You ask for an application by name, and the store downloads it, installs it, and can later update or remove it. Helm does the same job for applications running on Kubernetes. It is a program you run on your own computer, and it talks to your cluster on your behalf.
The package Helm installs is called a chart. A chart is a folder of files that contains templates, which are manifests with blanks in them, plus default values for those blanks. When you install a chart, you give Helm your own values to override the defaults. Helm fills in the blanks, produces ordinary manifests, and sends them to Kubernetes. Each installed copy of a chart is called a release, and Helm remembers every release so it can upgrade or remove it later.
A chart is like a form letter with blank spaces for a name and an address, plus a suggested default for each blank. Your values are the names and addresses you write in. Helm is the office assistant who fills in every letter, posts them all together, and keeps a copy of each batch so any batch can be recalled or reprinted later.
The vocabulary you will use
Chart
A packaged application: a folder or archive holding templates, default values, and descriptive information.
Release
A named, installed instance of a chart. You can install the same chart many times, each as a separate release.
Values
The settings that customise a chart, such as the number of replicas or the web address.
Template
A manifest with placeholders that Helm fills in with values to produce a real manifest.
Repository
A place that stores and shares charts, either a simple web server or a container registry.
Revision
One numbered version of a release. Each install, upgrade, or rollback creates a new revision.
Subchart
A chart included inside another chart as a dependency, such as a database bundled with an application.
Hook
A resource that Helm runs at a special moment, such as before an install or after an upgrade.
Helm does not run inside your cluster as a permanent service. It is a tool you run when you need it, on your laptop or in an automated pipeline. It uses the same access to the cluster that you already have.
3Kubernetes Building Blocks You Need First
Helm builds on top of ordinary Kubernetes objects. Knowing them makes charts easy to read.
Manifest
A text file that declares a thing you want in the cluster. Kubernetes reads it and works to make reality match.
Deployment
An object that keeps a chosen number of copies of a program running and knows how to update them safely.
Service
A stable name and address in front of a changing group of pods, so other programs can find your application.
ConfigMap
An object that holds ordinary settings, such as file contents or option values, that pods can read.
Secret
An object for sensitive data such as passwords and keys, handled with extra care compared with a ConfigMap.
Namespace
A named room in the cluster that groups objects. Releases are installed into a namespace.
Ingress
A front door that routes outside web traffic to the right Service, based on the address and path.
Custom Resource Definition
A way of teaching Kubernetes a brand new kind of object, often shipped by add-on tools.
API Server
The front door of the cluster’s control plane. Every request to create or change an object goes through it.
Kubeconfig
A file that tells tools like Helm which cluster to talk to and which credentials to use.
Declarative: describe the goal, not the steps
Kubernetes works in a declarative way. You do not tell it “start three programs, then open this port”. You write down what the finished state should look like, and Kubernetes continually works to reach and keep that state. If a program crashes, Kubernetes starts a new one, because your manifest said three should exist.
This is the property Helm relies on. Helm does not invent a new way of running programs. It produces ordinary manifests, hands them to Kubernetes, and lets Kubernetes do the rest. Helm is a manager of manifests, not a replacement for anything Kubernetes already does.
Think of ordering a building from an architect. You do not tell the builders which brick to lay first. You hand over the plans, which are the manifests, and the builders keep working until the building matches the plans. Helm is the person who prepares the plans from a standard design, adjusted to your needs, and keeps a record of every version of the plans.
Many beginners think Helm is a different way of running applications. It is not. Everything Helm installs is a normal Kubernetes object, and you can look at it, and even change it, with ordinary tools. Helm only adds packaging, settings, and history on top.
4The Anatomy of a Chart
A chart is just a folder with a known layout. Once you know the parts, any chart becomes easy to read.
flowchart TD
CH["Chart folder"] --> Y["Chart.yaml: name, version, description"]
CH --> VV["values.yaml: default settings"]
CH --> T["templates folder: manifest templates"]
CH --> D["charts folder: subcharts"]
CH --> CR["crds folder: custom resource definitions"]
T --> HL["helpers file: reusable named templates"]
T --> NT["NOTES file: message shown after install"]
Read the figure from the top. The chart folder holds a description file, a file of default settings, and a templates folder that contains the real substance. It may also contain a folder of subcharts, which are dependencies, and a folder of custom resource definitions. Inside the templates folder, there are usually one file per Kubernetes object, plus a helpers file and a notes file.
Chart.yaml
The identity card of the chart: its name, its own version, the version of the application inside it, and its dependencies.
values.yaml
The default settings. Every blank in the templates should have a sensible default here.
templates folder
The manifest templates that Helm fills in. Each file describes one or more Kubernetes objects.
Helpers file
Reusable named snippets, such as a standard set of labels, so the same text is not repeated in every template.
NOTES file
A short message printed after installation, telling the user how to reach the application or what to do next.
charts folder
Where downloaded dependencies, called subcharts, are stored so the chart can be installed as one package.
crds folder
Custom resource definitions that Helm installs before the templates, for charts that add new object kinds.
values.schema.json
An optional file that describes what values are allowed, so mistakes are caught before anything is installed.
Chart.lock
A record of the exact dependency versions that were downloaded, so builds are repeatable.
.helmignore
A list of files that should be left out when the chart is packaged, such as notes and editor files.
Two version numbers, two meanings
A chart carries two separate version numbers, and confusing them is a very common mistake. The chart version describes the chart itself: its templates, its defaults, its structure. The application version describes the software inside, for example the version of the web server or database that the chart deploys. They change independently.
| Field | What it describes | Changes when |
|---|---|---|
| Chart version | The packaging: templates, defaults, structure | You change how the application is deployed |
| Application version | The software being deployed | You deploy a newer build of the software |
Think of a cookbook page. The edition number of the page is the chart version, because it changes when the instructions are rewritten. The type of dish, such as “tomato soup, 2024 recipe”, is like the application version. You can print a new edition of the page without changing the soup, and you can change the soup without reprinting the page layout.
Charts should follow semantic versioning, where a change in the first number signals a breaking change. This lets users of your chart know whether an upgrade might need extra care.
5Templates and Values
Templates and values are the heart of Helm. Together they turn one chart into many different, ready-to-use sets of manifests.
What a template is
A template is a manifest with blanks. In place of a fixed number of replicas, a template contains a marker that means “put the replica value here”. The markers are written between double curly braces. Helm reads the template, finds each marker, looks up the matching value, and writes the finished text.
Helm uses a text templating language that is common in the Go programming world, together with a library of extra helper functions. You do not need to be a programmer to read most templates. They are mostly ordinary manifests with a few markers scattered through them.
Consider a mail merge in a word processor. You write one letter with fields such as the recipient’s name and address. The program then combines the letter with a list of people, and produces a personalised letter for each. A Helm template is the letter with fields, the values are the list, and the rendered manifests are the finished letters.
What templates can do
Insert values
The simplest use is to place a setting into the manifest, such as the image name, the number of replicas, or the web address.
Use built-in information
Helm provides ready-made facts inside templates: the release name, the namespace, the chart’s own name and version, and details about the cluster’s abilities. This lets names and labels be generated consistently.
Make choices
Templates can include a section only when a setting is turned on. For example, the Ingress object is created only if the user has enabled it.
Repeat things
Templates can loop over a list of items, such as a list of environment variables or hostnames, and produce one entry for each.
Reuse snippets
Named templates, kept in the helpers file, hold reusable text such as standard labels. Any template can include them, which keeps the chart tidy and consistent.
Require input
A template can insist that a value is provided, and stop with a clear message if it is missing, rather than producing a broken manifest.
How values are layered
Values come from several places, and later sources override earlier ones. The chart’s own defaults come first. Then any values files you pass in are applied, in order. Finally, settings you give directly on the command line have the last word. This layering lets you keep one shared file of common settings and one small file for each environment.
| Order | Source | Typical use |
|---|---|---|
| 1 (weakest) | The chart’s default values file | Safe, general defaults for everyone |
| 2 | The parent chart’s values, for subcharts | Tuning a bundled dependency |
| 3 | Values files you pass in, in order | Per-environment settings such as production sizes |
| 4 (strongest) | Individual settings given on the command line | Quick overrides, such as an image tag set by a pipeline |
Catching mistakes early with a schema
A chart can ship a schema file that describes which values are allowed, what type each must be, and which are required. When someone provides a value that does not fit, Helm stops before installing anything and says what is wrong. This turns silent misconfiguration into a clear, early error.
YAML is sensitive to indentation, and templates produce text, so a misplaced space can silently break a manifest. Numbers that should be strings, such as version labels, also need quoting. Always render templates and read the result before installing, especially after editing them.
Every extra option makes a template harder to read and test. Add a setting only when someone truly needs to change it, and keep sensible defaults for the rest.
6Architecture: Client, Charts, Repositories, and Releases
Helm has a small and clean architecture. Understanding where each piece lives explains how it behaves.
Helm today is a client-only tool. You run it on a computer, and it reads your cluster connection file, renders charts locally, and talks directly to the cluster’s API server. There is no Helm program running permanently inside the cluster. Older versions of Helm used a server component called Tiller, which sat in the cluster with wide permissions. It was removed in the third major version, mainly for security reasons, and the record of each release is now stored in the cluster as ordinary objects.
flowchart LR
C["Chart: templates and default values"] --> H["Helm client renders the templates"]
V["Your values"] --> H
H -->|"plain Kubernetes manifests"| A["Kubernetes API server"]
A --> R["Running resources"]
H -->|"release record"| S["Secret stored in the cluster"]
Read the figure from the left. A chart and your values come together inside the Helm client, which renders them into plain manifests. Those manifests go to the API server, which creates the running resources. Helm also saves a release record in the cluster, so it can later find out what it installed. The client is the only active part, and it disappears when it finishes.
Helm Client
The command line program that fetches charts, renders templates, and talks to the cluster.
Chart Archive
A chart packed into a single compressed file with a version number, ready to be stored and shared.
Chart Repository
A web server that hosts chart archives along with an index file listing every chart and version it has.
OCI Registry
A container registry that stores charts in the same way as container images, and is now a common home for charts.
Release Record
A Secret in the cluster, one for each revision, that stores the chart, values, and manifests of that revision.
Kubernetes API Server
Receives the rendered manifests and creates or updates the actual objects in the cluster.
Plugins
Extra programs that add abilities to Helm, such as comparing a planned upgrade with what is currently installed.
Discovery Sites
Public directories, such as Artifact Hub, where you can search for charts published by many projects.
Where charts are stored
Charts can be shared through two kinds of homes. The older kind is a chart repository, which is a plain web server holding chart archives and an index file. The newer and increasingly popular kind is an OCI registry, the same type of storage that holds container images. Storing charts in a registry means teams can reuse their existing image storage, access controls, and signing tools.
| Aspect | Chart repository | OCI registry |
|---|---|---|
| What it is | Web server with archives and an index file | Container registry that also stores charts |
| Finding charts | Add the repository, then search its index | Refer to the chart by its full address |
| Access control | Depends on the web server used | Uses the registry’s own permissions |
| Reuse of tooling | Separate from image tooling | Shares scanning and signing with images |
| Common today | Widely used, long history | Growing quickly and favoured for new setups |
Think of a library. A chart repository is a small local library with a printed catalogue of its books. An OCI registry is a big modern library that stores books, films, and music in the same building, with one membership card and one set of rules. Both hand you the same book, but the second is easier to fit into a system you already use.
Because release records are stored as objects in the namespace where the release was installed, anyone with the right access can find them, and they survive if your laptop is lost. The flip side is that anyone who can read those objects can read the values used, so access to them must be protected.
7Internal Working: What Happens During an Install
An install looks like one command, but Helm performs a careful sequence of steps. Following them explains most of the messages you will ever see.
sequenceDiagram
participant U as User
participant H as Helm Client
participant R as Chart Source
participant A as API Server
U->>H: Install a chart with a release name and values
H->>R: Fetch the chart and its dependencies
H->>H: Merge values and render the templates
H->>A: Send hooks first, then the manifests
A-->>H: Resources accepted
H->>A: Save the release record as a Secret
H-->>U: Report the status and the notes
Fetch the chart
Helm loads the chart from a local folder, a downloaded archive, a repository, or a registry, and makes sure its dependencies are present.
Merge and check the values
Helm layers the default values, your files, and your direct settings into one final set. If the chart has a schema, the values are checked against it now.
Render the templates
Every template is filled in with the final values and the release information, producing plain manifests. Nothing has reached the cluster yet.
Install custom resource definitions
Any definitions in the special folder are installed first, so the new kinds of objects exist before templates try to use them.
Run pre-install hooks
Helm runs any resources marked as pre-install hooks, such as a job that prepares a database, and waits for them to finish.
Create the resources in order
Helm sends the manifests to the API server in a sensible order, for example namespaces and settings before the programs that use them.
Optionally wait
If asked, Helm waits until the programs report themselves ready, and fails the install if they do not do so in time.
Run post-install hooks and record the release
Finally, post-install hooks run, the release record is saved as a Secret in the cluster, and the notes message is shown to the user.
Think of a building contractor starting a project. First the plans are collected and checked, then the site is prepared, then foundations are laid before walls, and only when everything is standing does the contractor sign off and file a record of what was built. Skipping the order or the sign-off would leave a confusing site that nobody could later repair.
Look before you leap
Helm offers two safe ways to look at what will happen. A rendering-only mode produces the final manifests on your screen, without contacting the cluster, so you can read exactly what would be sent. A dry-run mode goes a step further and asks the cluster to check the manifests without creating anything. Both catch typing errors, missing values, and mismatched settings before they cause harm.
Reading the rendered manifests is the single most valuable habit in Helm. It shows the real objects, real names, and real settings, cutting through any confusion about what the templates and values produce together.
If an install fails half way, some resources may already exist while the release is marked as failed. Fix the cause and upgrade or reinstall the release, or remove it fully before starting again, so leftover objects do not cause conflicts.
8Upgrades, Rollbacks, and the Three-Way Merge
Upgrading is where Helm earns its keep. It compares three pictures of your application and sends only the difference.
How an upgrade decides what to change
When you upgrade a release, Helm renders the new manifests from the new chart and values. It then compares three things: the manifests from the previous revision, the newly rendered manifests, and the live state of the objects in the cluster. This is called a three-way merge. It lets Helm work out which fields the chart wants to change, and it takes account of what is actually running.
flowchart TD
O["Previous release manifest"] --> M["Three-way comparison"]
N["New rendered manifest"] --> M
L["Live state in the cluster"] --> M
M --> P["Patch sent to the API server"]
P --> Q{"Upgrade succeeded?"}
Q -->|"Yes"| S["New revision recorded as deployed"]
Q -->|"No"| F["Release marked failed, roll back to an earlier revision"]
The figure shows three inputs feeding one comparison. The result is a patch, which is a small set of changes, sent to the API server. If the changes are accepted and the application becomes healthy, a new revision is recorded. If not, the release is marked as failed, and you can return to an earlier revision.
Imagine editing a shared document with tracked changes. To decide what to change, the editor compares the original version, the new version you want, and the copy as it looks right now, since someone else may have touched it in the meantime. Only the differences that matter are applied, instead of overwriting the whole page.
Rollback: going back to a good revision
Every install and upgrade produces a numbered revision, and Helm keeps a limited history of them. A rollback takes the manifests from an earlier revision and applies them again. Importantly, the rollback itself becomes a new revision at the end of the history, so the history is never rewritten, only extended. You can always see what was done and in which order.
Two options make upgrades much safer. A wait option makes Helm hold until the programs are ready, so a broken upgrade is reported as a failure. An atomic option goes further, and automatically rolls back if the upgrade fails. Together they turn a risky change into one that undoes itself.
| Situation | What Helm does | What you should remember |
|---|---|---|
| Upgrade succeeds | Records a new revision as deployed | Older revisions stay in history, up to a limit |
| Upgrade fails with wait only | Marks the release as failed | Objects may be partly changed, so investigate or roll back |
| Upgrade fails with atomic | Rolls back automatically | The failed attempt stays visible in history |
| You request a rollback | Reapplies an older revision as a new revision | Data changes made in between are not undone |
| History grows large | Trims the oldest revisions past the limit | Very old revisions can no longer be restored |
What a rollback cannot undo
A rollback only restores the Kubernetes objects. It cannot undo changes to data. If an upgrade ran a database migration, rolling back the application does not reverse the migration, and the old version may not understand the new data. Hooks are also not reversed, and custom resource definitions are not removed by a rollback. Plan for these limits before relying on rollback as a safety net.
Configuration changes that do not restart anything
A classic surprise is that changing a settings object does not restart the programs that read it. The deployment itself has not changed, so Kubernetes sees no reason to replace the pods. A well-known remedy is to put a fingerprint of the settings, called a checksum, into a label on the pod template. When the settings change, the fingerprint changes, the pod template changes, and Kubernetes rolls the pods automatically.
Certain fields in Kubernetes objects are fixed once created, such as the selector of a Deployment. If an upgrade tries to change one, it fails. You may then need to remove and recreate that object, so plan such changes carefully and keep selectors stable across chart versions.
A popular plugin shows exactly what an upgrade would change compared with what is running now. Reviewing that difference in a pipeline before applying it catches surprises while they are still harmless.
9Dependencies, Subcharts, Hooks, and Tests
Real applications are rarely alone. Helm has built-in ways to bundle other charts, to run special jobs at key moments, and to test a release after it is installed.
Dependencies and subcharts
A chart can list other charts it depends on, such as a database or a cache. Helm downloads them into the charts folder, and installs them together with the parent as one release. The parent chart can switch a dependency on or off with a setting, and can pass values down to it using the dependency’s name as a section in its own values.
A lock file records the exact versions that were downloaded, so that everyone who builds the chart gets the same result. There is also a shared area of values, called global values, that every subchart can read. It is useful for settings such as a common domain name.
Umbrella chart
A chart whose main purpose is to bundle several other charts into one installable product. For example, a platform chart may include a web front end, an API, and a database as subcharts, installed together.
Library chart
A chart that contains no deployable objects, only reusable templates. Other charts include it to share common snippets, such as a standard Deployment layout, keeping many charts consistent.
A chart with subcharts is like a gift hamper that contains smaller gift boxes. The big box carries the label and the ribbon, while each small box holds its own contents. You can leave one small box out, or change what is inside it, without redesigning the whole hamper.
Hooks: special moments in a release
A hook is a resource that Helm runs at a chosen moment in the life of a release, instead of installing it as a normal part of the application. Hooks are marked with an annotation naming the moment. They are most often jobs, such as one that prepares a database before the new version starts.
Pre-install
Runs after templates are rendered but before any resources are created. Useful for one-time preparation.
Post-install
Runs after all resources are created. Useful for final setup or notifications.
Pre-upgrade
Runs before an upgrade changes anything. Often used for database migrations that the new version needs.
Post-upgrade
Runs after the upgrade has been applied, for checks or clean-up steps.
Pre-delete and Post-delete
Run around removal of a release, for tasks such as saving data or de-registering a service.
Test
Runs only when you ask Helm to test a release, and reports whether the application behaves correctly.
Hooks run in an order controlled by a weight number, and a delete policy decides when finished hook objects are cleaned up. A hook that fails also fails the release step it belongs to, which is useful for stopping a bad upgrade early, but can also block a release if the hook is not written carefully.
Tests: proving a release works
A chart can include test resources, usually small pods that run a check and exit with success or failure. A user can ask Helm to run them after installing, and the result shows whether the application answers, connects to its database, or passes whatever check the chart’s author wrote. This gives every chart a simple, repeatable way to confirm it is healthy.
Objects created by hooks are not managed as part of the release in the usual way. They are not updated or removed with it unless a delete policy says so, and they are not undone by a rollback. Leftover hook jobs are a common source of clutter and confusing errors.
Hooks may run more than once, for example after a failed attempt and a retry. Write them so that running twice does no harm, such as a migration that checks whether it has already been applied.
10Helm in CI/CD Pipelines and GitOps
In most teams, nobody installs charts by hand in production. Helm sits inside automated pipelines that build, check, and deliver every change.
A typical delivery pipeline
A pipeline takes a chart from a developer’s change to a running release, with checks at each step. A well-built one catches nearly every mistake before it reaches a live cluster.
Lint the chart
Helm’s built-in checker looks for structural mistakes, missing fields, and common errors in the chart.
Render with test values
Templates are rendered for each environment’s values, so any failures in the templates appear early.
Validate the manifests
Tools check the rendered output against the Kubernetes object definitions and against your own policy rules.
Package, sign, and publish
The chart is packed into a versioned archive, optionally signed, and pushed to a repository or registry.
Show the diff
The pipeline shows what would change in the target environment, so a person or a rule can approve it.
Deploy with wait and atomic
The release is upgraded in a way that waits for health and rolls back on failure.
Test and promote
Chart tests run, and the same chart version, with different values, is promoted from one environment to the next.
A delivery pipeline is like a factory assembly line with quality inspectors at each station. Parts are checked for size, then assembled, then tested, then boxed and sealed. A defect is caught at the station where it appears, not by the customer who opens the box.
GitOps: the desired state lives in Git
In a GitOps approach, the desired state of the cluster is kept in a Git repository, and a tool inside the cluster continuously makes reality match it. Two popular tools handle Helm charts in different ways. Argo CD renders charts itself and applies the plain result, so it does not use Helm’s own release records. Flux uses a resource that describes a Helm release, and runs Helm operations inside the cluster on your behalf, so ordinary Helm records exist.
| Aspect | Push from a pipeline | GitOps controller in the cluster |
|---|---|---|
| Who applies changes | A pipeline job with cluster credentials | A controller running inside the cluster |
| Source of truth | The pipeline’s last successful run | The Git repository |
| Drift handling | Only corrected at the next run | Detected and corrected continuously |
| Credentials | Pipeline needs access to the cluster | Controller pulls changes, fewer outside credentials |
| Helm release records | Present, used by Helm commands | Depends on the tool used |
If a GitOps tool manages a release, running manual Helm commands against it causes confusion and drift. Choose one owner for each release, and let everyone know which it is.
The safest promotion story is to build one chart version once, test it, and move that exact version through the environments, changing only the values files. What you tested is then exactly what you release.
11Data Flow and the Lifecycle of a Release
A release has a life of its own: it is born, changes, sometimes fails, and eventually is removed. Knowing its states helps you read the signs.
flowchart LR
A["pending-install"] --> B["deployed"]
B --> C["pending-upgrade"]
C --> D["deployed as a new revision"]
C --> E["failed"]
D --> F["older revision becomes superseded"]
E --> G["rollback creates a new revision"]
B --> H["uninstalled"]
| Status | Meaning | What to do |
|---|---|---|
| pending-install | An install is in progress | Wait, or investigate if it stays for long |
| deployed | The latest revision was applied successfully | Nothing, this is the normal state |
| pending-upgrade | An upgrade is in progress | Wait, or check for an interrupted operation |
| failed | The last operation did not succeed | Read the error, fix it, then upgrade or roll back |
| superseded | An older revision replaced by a newer one | Kept only as history |
| uninstalled | The release was removed but history was kept | Can be inspected, or reinstalled under the name |
Birth
The chart is installed under a chosen name in a chosen namespace, and revision one is recorded.
Change
Each upgrade creates a new revision. Older revisions are kept up to the history limit, and can be inspected or restored.
Trouble
If an upgrade fails, the release enters a failed state. A rollback creates a fresh revision that restores the earlier objects.
Removal
An uninstall deletes the objects that the release created, and by default removes its history, unless told to keep it.
Think of a library record for a rented book. It shows when it was borrowed, each time it was renewed, whether it came back damaged, and when it was finally returned. The record lets the library understand the whole story of the book at a glance, instead of guessing from the book alone.
What stays behind after removal
Uninstalling a release removes the objects it created, but not everything. Storage volumes created by stateful programs are deliberately kept, so data is not lost by accident. Custom resource definitions placed in the special folder are also left in place, because removing them would delete every object of that kind across the cluster. Both are safe defaults, but they mean a full clean-up sometimes needs extra manual steps.
If Helm is interrupted during an install or upgrade, for example when a pipeline is cancelled, the release can remain in a pending state, and further operations refuse to run. Investigate the state first, then roll back or reset it deliberately, rather than deleting records blindly.
Helm installs definitions from the special folder once, but it does not upgrade or delete them. Teams often manage such definitions in a separate step or chart, so they can be upgraded safely and on purpose.
12Security When Using Helm
A chart is a program that creates other programs. Installing one from a stranger is a serious act of trust, and that deserves care.
A chart can create almost anything in your cluster, including powerful permissions, programs that run with high privileges, and jobs that execute at install time. Most charts are perfectly benign, but you cannot know that without looking. Treat charts the way you treat any software you download and run.
Buying a meal kit from an unknown supplier means trusting them with what goes into your kitchen. Sensible cooks check the ingredients, read the label, and prefer suppliers with a track record. The same care is wise before letting a chart create objects in a cluster that holds real data.
Review Third-Party Charts
Render the chart and read what it will create, especially permissions, privileged pods, hooks, and definitions, before installing.
Verify Provenance
Use chart signing and signature checks, or registry signing tools, to confirm that a chart is genuine and unmodified.
Pin Versions
Install exact chart versions and reference images by version or digest, so a surprise change cannot slip in with an update.
Protect Release Records
Release records hold your values. Restrict who can read them, and use encryption at rest for Secrets in the cluster.
Keep Secrets Out of Values Files
Do not commit passwords into values files in Git. Use an external secrets system, or encrypted secrets tooling, and reference them instead.
Least-Privilege Installs
Helm acts with the credentials it is given. Give pipelines access only to the namespaces they need, not the whole cluster.
Policy Checks on Output
Scan the rendered manifests with policy tools, and use admission rules in the cluster, so unsafe settings are rejected whoever produced them.
Private, Trusted Sources
Mirror the charts and images you depend on into a registry you control, with its own access rules and scanning.
Why removing Tiller mattered
In the older design, a server component with very broad rights sat inside the cluster, and anyone who could reach it could do almost anything. Helm now performs actions with the caller’s own permissions, so a person or pipeline can only do what their credentials allow. This is a much safer default, and it fits normal cluster access control.
Even Secrets in Kubernetes are only encoded, not encrypted, unless encryption at rest is configured. A release record holds every value you supplied, including any passwords. Assume that anyone who can read those objects can read your secrets.
Search the rendered output for objects that grant permissions across the whole cluster, for pods that ask for elevated privileges, and for jobs run by hooks. These are the places where a chart has the most power, and where a review pays off most.
13Monitoring, Logging, and Troubleshooting
Helm itself is quiet, but the state of your releases matters. A few habits make failures visible early and easy to untangle.
Think of a shipping company’s tracking page. Every parcel shows its status, its history, and any delay. Nobody needs to phone the depot to guess where a parcel is. Watching your releases in the same way lets you see what is deployed, what failed, and what changed, without guessing.
What to watch
Release Status
Watch for releases in a failed or pending state. They mean an operation did not finish, and they can block later changes.
Revision History
The history shows who changed what and when. Unexpected revisions are an early sign of hand-made or unplanned changes.
Version Inventory
Keep a list of which chart and application version runs in each environment, to spot stale or mismatched deployments.
Health After Release
Check that pods become ready and stay ready after a change. Restarts and failing probes right after a release point to the change.
Drift
Compare what the chart says with what is live. Differences mean someone changed objects by hand or another tool interfered.
Deprecated APIs
Charts using old Kubernetes object versions will break when the cluster is upgraded. Scan for them ahead of time.
Some of these signals come from Helm’s own listing and history commands. Others come from the cluster’s normal monitoring, such as pod health and events. Community tools can also publish release information as metrics, so that dashboards and alerts can show failed releases beside the rest of your monitoring. GitOps tools report their own sync and health status, which is usually the best place to watch releases they manage.
Logs that help
Several logs tell the story of a release. The pipeline log shows what commands ran and what they printed. The logs of hook jobs show what a migration or setup step did. The application’s own logs show how it behaved after the change. The cluster’s audit log records who made each change to the API server, including Helm’s actions, which is essential when asking who changed what.
Untangling a failed release
Read the error carefully
Helm’s messages usually name the object and the reason, such as an invalid field, a missing value, or a conflict with an existing object.
Render the chart yourself
Produce the manifests with the same values, and read them. Most problems are visible in the rendered text.
Look at what was deployed
Ask Helm for the values, manifests, and status of the current revision, and compare them with what you expected.
Check hooks and events
Look at hook jobs and at events in the namespace. A failing hook or an unschedulable pod often hides behind a vague message.
Fix forward or roll back
If the cause is clear, correct it and upgrade again. If not, roll back to the last good revision, and continue the investigation in calm conditions.
Alerts worth setting up
Alert when a release stays failed or pending beyond a set time, when the running chart version differs from the intended one, when drift is detected, and when a chart uses object versions that the next Kubernetes upgrade will remove. Also alert when a release has not changed in a very long time, since old releases often hide old security problems.
Kubernetes removes old object versions over time. Before upgrading a cluster, scan the rendered output of every chart for removed versions, and update the charts first. Otherwise the next upgrade of a release can fail in confusing ways.
14Advantages, Disadvantages, and Trade-offs
Helm is the most widely used way to package Kubernetes applications, but it is not the only way, and it has real costs.
Advantages
- Packages a whole application as one versioned, shareable unit.
- One chart serves many environments, changed only through values.
- Tracks releases and history, with simple upgrade and rollback.
- Has a huge ecosystem of ready-made charts for common software.
- Supports dependencies, hooks, and tests for real-world needs.
- Fits well into pipelines and GitOps workflows.
Disadvantages / Trade-offs
- Templating text is harder to read and debug than plain manifests.
- Charts can become over-parameterised, with hundreds of settings nobody understands.
- Rollback restores objects only, not data or hook effects.
- Custom resource definitions are handled awkwardly, with no upgrade or removal.
- Third-party charts vary widely in quality and safety.
- The release record in the cluster holds values, which needs protection.
Thinking about cost honestly
The cost of Helm is mostly the cost of complexity and learning. Someone must learn the template language, understand how values layer, and keep charts tidy. Charts must be versioned, tested, and stored. A team that has three small applications may find plain manifests simpler than maintaining charts. A team that has thirty applications in five environments will find that the discipline pays back quickly.
The trap is treating every setting as a value. Each one adds a path that must be understood and tested. The best charts expose only the settings people actually need, and keep the rest fixed.
How Helm compares with other approaches
| Approach | How it works | Strength | Weakness |
|---|---|---|---|
| Helm | Templates plus values, packaged as charts with release tracking | Packaging, sharing, history, and a huge catalogue | Template complexity and text-based logic |
| Kustomize | Plain manifests plus overlays that patch them | No templating language, easy to read the base | No packaging or release history of its own |
| Plain manifests | Files applied directly | Simple and transparent | Repetition and drift across environments |
| Operators | Programs in the cluster that manage an application’s life | Deep application knowledge and automation | Each needs its own installation and learning |
Plain manifests are like handwritten recipes copied for each kitchen. Kustomize is like a master recipe with sticky notes that change a few ingredients for each kitchen. Helm is like a meal kit with an order form. An operator is like a resident chef who not only cooks the meal but stays to keep it fresh.
Helm and Kustomize are not enemies. Teams often install a public chart with Helm, and then adjust its rendered output with Kustomize, and operators are often installed using Helm. Use each tool for what it does best.
15Design Patterns and Anti-patterns
A few habits make charts easy to live with. A few shortcuts make them a burden for years.
Patterns that work well
One Values File per Environment
Keep shared defaults in the chart and a small file of differences for each environment, stored in version control.
Umbrella Chart for a Product
Bundle the pieces of one product as subcharts, so the whole product is versioned and installed together.
Library Chart for a Standard Shape
Put common Deployment and Service layouts in a library chart, so many services share one reviewed design.
Checksum on Configuration
Add a fingerprint of settings to the pod template so that configuration changes roll the pods automatically.
Render, Diff, Review
Make the pipeline show the rendered output and the difference from live state before anything is applied.
Schema-Checked Values
Ship a values schema so that wrong or missing settings are rejected clearly before an install starts.
Anti-patterns to avoid
Problem
A chart turns every field of every object into a configurable value, ending up with hundreds of settings.
Why It’s Harmful
Nobody understands the options, the templates become full of conditions, and testing every combination is impossible. The chart becomes harder to read than the manifests it was meant to simplify.
Correct Approach
Expose only settings that truly vary between users or environments, keep good defaults for the rest, and split very different use cases into separate charts.
Problem
Passwords and keys are written into values files that are committed to Git in plain text.
Why It’s Harmful
Anyone with access to the repository, now or in the past, can read the secrets. They are also copied into release records in the cluster and into pipeline logs.
Correct Approach
Keep secrets in an external secrets system or use encrypted secrets tooling, and pass only references through values.
Problem
Charts are installed without a version, and images use a moving tag such as “latest”.
Why It’s Harmful
The same command can install different things on different days. Environments quietly diverge, and a bad release cannot be reproduced or traced.
Correct Approach
Pin exact chart versions, reference images by version or digest, and update them on purpose through a reviewed change.
Problem
Production problems are fixed by editing live objects directly, without changing the chart or the values.
Why It’s Harmful
The live state drifts from what the chart describes. The next upgrade may overwrite the fix, or fail in a confusing way, and nobody remembers what was changed.
Correct Approach
Make every change through the chart or values, and use the pipeline. In an emergency, make the manual fix, then record it in the chart straight afterwards.
16Best Practices and Common Mistakes
A short field guide collected from teams that use Helm every day, and from the mistakes that repeat.
Best practices
- Render before you install — read the manifests that your values produce, every time you change something important.
- Lint and validate in the pipeline — catch structure errors, schema errors, and policy violations automatically.
- Keep values small and documented — comment each setting and give safe defaults.
- Add a values schema — reject wrong types and missing required values early.
- Pin chart and image versions — make every deployment reproducible.
- Use wait and atomic for upgrades — let failed upgrades report clearly and undo themselves.
- Diff before applying — show reviewers exactly what will change in the target environment.
- Sign and verify charts — especially those shared between teams or with customers.
- Keep secrets out of Git — use external secrets tools and reference them.
- Keep selectors and names stable — changing them across versions forces objects to be recreated.
- Manage custom definitions deliberately — plan how they are installed, upgraded, and removed.
- Choose one owner for each release — either a pipeline, or a GitOps tool, not both.
Common mistakes
Installing a popular chart without reading what it creates can give it wide permissions or privileged pods in your cluster. Render it, review it, and pin its version.
A rollback returns objects, not data. After a migration, an old version may not understand the new database. Plan rollback with data in mind, not only manifests.
A number that should be text, or text that looks like a number or a true and false word, can be interpreted differently from what you meant. Quote such values, and rely on a schema to catch the rest.
Many charts install cleanly but fail to upgrade from the previous version. In a test environment, install the older chart first, then upgrade to the new one, exactly as production will.
17Real-World and Industry Examples
Helm is used wherever teams need to install and manage applications on Kubernetes repeatedly and reliably.
Installing cluster add-ons
Most clusters need common building blocks such as ingress controllers, certificate managers, and monitoring stacks. The projects behind them publish charts, so a platform team can install and upgrade them in a repeatable way, with settings kept in version control.
Internal platform charts
Platform teams often provide a standard chart, sometimes built on a library chart, that captures the company’s approved way to run a service: sensible security settings, labels, probes, and resource limits. Application teams only supply a small values file.
Software shipped to customers
Vendors who let customers run their software on their own clusters commonly ship a Helm chart. Customers supply values for their environment, and the vendor updates the chart as new versions are released.
Promotion across environments
Organisations build a chart version once, test it in development, and promote the same version to staging and production, changing only the values. This gives them confidence that what was tested is what runs.
Fleets of similar microservices
When dozens of services share the same shape, teams use one shared chart, or a library chart, so that a security improvement made once reaches every service on its next release.
Regulated and disconnected environments
Organisations with strict controls or no direct internet access mirror the charts and images they use into a private registry. They scan and approve each version, then install only from that trusted copy.
Moving from loose manifests to charts
Teams with a growing pile of copied YAML files often move to charts step by step. They start by turning the duplicated files into one template, then add values for each environment, and finally add tests and pipeline checks.
18Frequently Asked Questions
Quick answers to the questions that come up most often when teams start using Helm.
No. You can use plain manifests, Kustomize, or other tools. Helm becomes valuable when you have many applications, many environments, or want to install and share packaged software.
Helm uses templates and values and adds packaging and release history. Kustomize patches plain manifests using overlays and has no templating language. Many teams use them together.
Tiller was the server component of Helm’s earlier design. It was removed in Helm’s third major version. Helm now runs as a client tool and uses your own permissions.
By default, in Secrets in the namespace of the release, one for each revision. Other storage options exist, but this is the usual one, and it means the records live in the cluster.
Yes. Each installation needs its own release name, and charts should be written so that two releases do not collide, for example by including the release name in object names.
Use an external secrets system or encrypted secrets tooling, and have the chart refer to a secret by name instead of holding its contents.
Changing a settings object does not change the Deployment, so Kubernetes sees nothing to roll. Add a checksum of the settings to the pod template so a change triggers a rollout.
The chart version describes the packaging. The application version describes the software inside. They change independently and are recorded in separate fields.
No. Rollback restores Kubernetes objects only. Data changes, including migrations run by hooks, remain, so plan for data separately.
With care, yes. Helm can adopt existing objects if they carry the labels and annotations that show which release owns them. Without these, Helm refuses to overwrite objects it did not create.
Both are protected on purpose. Storage volumes hold data that should not disappear by accident, and definitions, if removed, would delete every object of that kind across the cluster.
Lint it, render it, run a dry run, look at the diff against the current release, install it in a test environment, run the chart’s tests, and also test the upgrade from the previous version.
19Summary and Key Takeaways
Helm packages a Kubernetes application as a chart, a folder of templates and default values. You provide your own values, Helm renders them into ordinary manifests, and each installed copy becomes a release with a numbered history. Upgrades compare the old manifests, the new ones, and the live state, and rollbacks return to an earlier revision. Around this core sit dependencies, hooks, tests, repositories, and registries, which together let teams share and reuse software reliably.
Helm is a strong tool, not a magic one. Templates can grow too complex, rollbacks do not undo data, custom definitions need special care, and third-party charts must be reviewed. Teams that keep charts small, pin versions, protect secrets, and check every change in a pipeline find that Helm turns messy deployments into steady, repeatable routines.
Key Takeaways
- A chart is a package, values are your choices, a release is the result — Helm fills in templates with values and sends ordinary manifests to Kubernetes.
- Helm is a client-only tool — it renders locally, acts with your permissions, and stores release records as Secrets in the cluster.
- Upgrades use a three-way comparison — the old manifests, the new ones, and the live state, with wait and atomic options for safe changes.
- Rollback restores objects, not data — plan separately for database changes, hooks, and custom definitions.
- Always render, lint, and diff — reading the rendered output is the best habit for finding mistakes early.
- Treat charts as software you run — review third-party charts, verify signatures, pin versions, and keep secrets out of values files.
- Keep charts simple and owned — expose only needed settings, use one values file per environment, and give each release exactly one owner.