Inside Helm - How Charts, Releases, and State Work in Kubernetes
By Tatiana Mikhaleva · Developer Advocate · Docker Captain · IBM Champion
Hey my DevOps queens (and kings, too)! 👑
Ever deployed an app to Kubernetes and then sat there thinking, “Wait… what actually happens after I type helm install?” Yeah. This one’s for you, sis.
Helm makes Kubernetes deployments look easy. Too easy, honestly. Because behind the scenes it’s doing way more than rendering a few YAML files. It’s a stateful release manager. It tracks every change you make, stores versioned state inside your cluster, and handles upgrades like it actually knows what it’s doing — and there’s no external database anywhere in sight.
So let’s peek behind the curtain. How are charts put together? Where does your release data actually live? And how does Helm keep the whole thing consistent and versioned without breaking a sweat? Grab your coffee. 💅
What’s Inside a Helm Chart
A Helm chart is a package. It describes how your app should land on Kubernetes, and it’s structured and predictable. Do it right and it becomes gorgeously reusable, too.
my-chart/ Chart.yaml # metadata (name, version, dependencies, etc.) values.yaml # default configuration values templates/ # Go templates for Kubernetes manifests _helpers.tpl # reusable named templates and functions charts/ # subcharts (dependencies) files/ # arbitrary files used in templates crds/ # CustomResourceDefinitions (installed first) .helmignore # like .gitignore for packagingPicture it as the blueprint for your app. You flex it through values.yaml, and you can override the defaults at deploy time whenever you like.
Pro tip: CRDs in the crds/ directory are:
- installed first,
- not templated,
- and never upgraded or deleted — this protects existing Custom Resources and data.
What Actually Happens When You Run helm install
There’s a sequence here, and it matters. Run helm install and Helm doesn’t just “apply some YAML.” It walks through clear steps:
- Loads the chart (local or remote).
- Merges values from multiple sources:
- base
values.yaml; - any additional files:
-f base.yaml -f prod.yaml(left-to-right; later overrides earlier); - inline flags:
--set,--set-string,--set-file,--set-json(these always take precedence).
- base
- Renders Go templates into complete Kubernetes manifests.
- Applies them to the cluster.
Clean install? Helm just creates the resources. Easy.
Things get a little more interesting if the resources already exist. When they carry the correct Helm annotations (meta.helm.sh/*, app.kubernetes.io/managed-by=Helm), Helm will happily adopt them. If they don’t, here’s what you get:
Error: invalid ownership metadataDuring upgrades or rollbacks, the story changes again. Helm runs a three-way strategic merge, comparing the previous manifest, the new manifest, and the current cluster state. That whole comparison happens client-side, through client-go.
Where Helm Stores Release State
Every Helm release lives inside your cluster. No external DBs. No magic. Promise.
By default, your release info goes into a Kubernetes Secret. You can swap that out for a ConfigMap or a SQL driver (PostgreSQL) if you’d rather.
Default object structure:
kind: Secrettype: helm.sh/release.v1metadata: name: sh.helm.release.v1.<release>.v<revision> namespace: <release-namespace>Now, the .data.release field. This is where the good stuff hides: a base64-encoded, gzip-compressed blob holding the chart archive, the rendered manifests, your merged values, hooks, plus release metadata like revision, timestamps, and status.
One quirk worth knowing. Kubernetes already base64-encodes Secret data, and the release payload also includes encoded sections of its own, so you end up with nested encoding. Encoding inside encoding. Cute, in a confusing way.
Heads up: etcd enforces a ~1 MiB limit for Secret data. Bump into this:
Too long: must have at most 1048576 charactersand it’s time to switch to SQL storage:
export HELM_DRIVER=sqlexport HELM_DRIVER_SQL_CONNECTION_STRING=postgresql://user:pass@host/dbLabels and Annotations
Helm labels everything it touches so it can track ownership down to the detail.
Added automatically:
app.kubernetes.io/managed-by=Helmmeta.helm.sh/release-name=<release-name>meta.helm.sh/release-namespace=<namespace>Best-practice labels (usually added by chart templates):
app.kubernetes.io/instance=<release-name>helm.sh/chart=<chart-name>-<version>When these don’t line up during an upgrade, Helm refuses to take ownership. And that, darling, is exactly where the classic invalid ownership metadata error comes from.
What Is a Helm Release?
A release is one installed instance of a chart, with a specific set of values, living in a namespace.
Every change you make becomes a new revision. Install, upgrade, rollback, doesn’t matter. Each one gets stored right there in your cluster. No external database. No API extension. Just plain old Kubernetes objects, quietly doing their job.
The Three-Way Merge Explained
Here’s what Helm lines up side by side when you upgrade:
- the previous rendered manifest,
- the new manifest (after your changes),
- the current live resources.
From those three, it works out a three-way strategic merge patch and applies only what actually changed. Less disruption that way, and your manual tweaks survive where they can.
NOTEThis logic runs client-side, not via Server-Side Apply. For CRDs or unstructured resources, Kubernetes uses JSON merge-patch, which can behave slightly differently.
Namespaces: Release vs Target
Helm splits namespaces into two flavors:
- Release namespace — where Helm stores its Secret or ConfigMap.
- Target namespaces — where chart resources are deployed (can be multiple).
--create-namespaceonly creates the release namespace (the one you pass with--namespace).
Got a chart that spreads across namespaces? Then create them yourself, or template them inside the chart.
Tip: Try not to hardcode metadata.namespace unless you genuinely need to. Otherwise helm template | kubectl apply might quietly shove your resources into default.
Storage Drivers
Helm gives you a few backends for storing release state:
export HELM_DRIVER=secret # default (encoded, secure)export HELM_DRIVER=configmap # readable, not encryptedexport HELM_DRIVER=sql # PostgreSQL – best for large releasesexport HELM_DRIVER=memory # ephemeral, for tests onlyManaging Release History
Helm hangs onto all revisions unless you tell it not to. So put a cap on it:
helm upgrade --history-max 10 ...export HELM_MAX_HISTORY=10Want to poke through the history? Anytime:
helm history <release>helm get values <release>helm get manifest <release>TL;DR
Helm isn’t magic. It’s just clean engineering. Every time you fire off helm install, it:
- loads, merges, and renders templates,
- stores state inside your cluster,
- tags resources for ownership tracking,
- applies three-way strategic merges on upgrade,
- manages revisions — all with zero external dependencies.
Once the inner workings click for you, Helm stops feeling like a mystery box. It starts feeling like your favorite DevOps assistant. 💖
Quick Debug Tip
helm ls -Akubectl get secrets -A -l "owner=helm" -l "status=deployed"Great for a fast audit, or just snooping on what Helm’s been up to lately.
Related Posts
- 1How to Secure AI Agents in Production: IBM's Six-Phase FrameworkDevOps & Cloud · Teams secure AI agents like normal software, and production breaks. Here's IBM and Anthropic's six-phase framework for securing them, phase by phase.
- 2Your AI Agent Doesn't Need a Better Prompt. It Needs a CeilingDevOps & Cloud · A prompt is not a security control. It's a wish. The Vault → Sentinel → MCP → ADLC → watsonx Orchestrate stack that gives AI agents a hard ceiling — and why IBM consolidating HashiCorp made the whole thing boring, in the best possible way.
- 3CNCF Q1 2026 Report — Why Feature Flagging Is the Hidden Gateway to Cloud Native MaturityDevOps & Cloud · CNCF Q1 2026 cloud native report analysis. Why feature flagging is the bridge from mainstream to advanced engineering practice, with exclusive commentary from the report's author.
- 4AI SRE Joined My On-Call — A Beginner-Friendly Walkthrough of RootlyDevOps & Cloud · What an AI SRE actually does on call. A hands-on walkthrough of Rootly — how it observes, advises, and (when you let it) acts. With a real look at the four-level trust model.
Random Posts
- 1Helm in Kubernetes - What It Is and Why You Need ItDevOps & Cloud · Helm simplifies Kubernetes deployments. Learn what it is, how it works, and why it's essential for managing scalable apps and infrastructure.
- 2How Generative AI Actually Understands YouAI & MLOps · Discover how generative AI understands text, images, video, and sound — explained simply with real examples of tokens, chunks, and embeddings.
- 3DevSecOps Explained - Security for DevOps in 2025DevOps & Cloud · A no-fluff DevSecOps guide for DevOps engineers. Learn how to build secure pipelines, protect secrets, and integrate security from day one.
- 4How to Secure AI Agents in Production: IBM's Six-Phase FrameworkDevOps & Cloud · Teams secure AI agents like normal software, and production breaks. Here's IBM and Anthropic's six-phase framework for securing them, phase by phase.