1052 words
5 minutes

Inside Helm - How Charts, Releases, and State Work in Kubernetes

Cover image for Inside Helm - How Charts, Releases, and State Work in Kubernetes

Hey my DevOps queens (and kings, too)! 👑

If you’ve ever deployed an app to Kubernetes and thought, “Wait… what actually happens after I type helm install?” — this one’s for you.

Helm makes Kubernetes deployments look easy. But behind the scenes, it’s doing a lot more than just rendering YAML files. It’s a stateful release manager that tracks every change, stores versioned state inside your cluster, and handles upgrades intelligently — no external database required.

Today, let’s pull back the curtain and see how Helm actually works: how charts are structured, where your release data lives, and how Helm keeps everything consistent and versioned like a pro.


What’s Inside a Helm Chart#

A Helm chart is a package that describes how your app should be deployed to Kubernetes. It’s structured, predictable, and — if you do it right — beautifully reusable.

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 packaging

Think of it as your app blueprint — flexible through values.yaml and easily overridden at deploy time.

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#

Let’s break it down. When you run helm install, Helm doesn’t just “apply some YAML.” It follows a clear sequence:

  • 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).
  • Renders Go templates into complete Kubernetes manifests.
  • Applies them to the cluster.

On a clean install, Helm creates the resources.

If resources already exist and contain the correct Helm annotations (meta.helm.sh/*, app.kubernetes.io/managed-by=Helm), Helm will adopt them. Otherwise, you’ll see:

Error: invalid ownership metadata

During upgrades or rollbacks, Helm performs a three-way strategic merge — comparing the previous manifest, the new manifest, and the current cluster state — handled client-side through client-go.


Where Helm Stores Release State#

Every Helm release is stored inside your cluster. No external DBs, no magic.

By default, Helm saves release info in a Kubernetes Secret, though you can switch to a ConfigMap or SQL driver (PostgreSQL).

Default object structure:

kind: Secret
type: helm.sh/release.v1
metadata:
name: sh.helm.release.v1.<release>.v<revision>
namespace: <release-namespace>

The .data.release field contains a base64-encoded, gzip-compressed blob with:

  • the chart archive,
  • rendered manifests,
  • merged values,
  • hooks,
  • and release metadata (revision, timestamps, status).

Because Secret data is base64-encoded by Kubernetes — and the release payload also includes encoded sections — the result is effectively nested encoding.

Heads up: etcd enforces a ~1 MiB limit for Secret data. If you hit:

Too long: must have at most 1048576 characters

switch to SQL storage:

Terminal window
export HELM_DRIVER=sql
export HELM_DRIVER_SQL_CONNECTION_STRING=postgresql://user:pass@host/db

Labels and Annotations#

Helm labels everything it manages to track ownership precisely.

Added automatically:

app.kubernetes.io/managed-by=Helm
meta.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>

If these don’t match during an upgrade, Helm will refuse ownership — hence the classic invalid ownership metadata error.


What Is a Helm Release?#

A release is one installed instance of a chart with a specific set of values (in a namespace).

Each change — install, upgrade, rollback — becomes a new revision stored right in your cluster. No external database. No API extension. Just Kubernetes objects doing their job.


The Three-Way Merge Explained#

When you upgrade, Helm compares:

  • the previous rendered manifest,
  • the new manifest (after your changes),
  • the current live resources.

Then it calculates a three-way strategic merge patch and applies only what changed — reducing disruption and preserving manual tweaks where possible.

NOTE

This 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 separates namespaces into two categories:

  • Release namespace — where Helm stores its Secret or ConfigMap.
  • Target namespaces — where chart resources are deployed (can be multiple).
  • --create-namespace only creates the release namespace (the one you pass with --namespace).

If your chart deploys across namespaces, create them manually or template them inside your chart.

Tip: Avoid hardcoding metadata.namespace unless you really need to — otherwise helm template | kubectl apply might push resources to default.


Storage Drivers#

Helm supports multiple backends for storing release state:

Terminal window
export HELM_DRIVER=secret # default (encoded, secure)
export HELM_DRIVER=configmap # readable, not encrypted
export HELM_DRIVER=sql # PostgreSQL – best for large releases
export HELM_DRIVER=memory # ephemeral, for tests only

Managing Release History#

Helm keeps all revisions unless you limit it. You can cap history like this:

Terminal window
helm upgrade --history-max 10 ...
export HELM_MAX_HISTORY=10

Explore release history anytime:

Terminal window
helm history <release>
helm get values <release>
helm get manifest <release>

TL;DR#

Helm isn’t magic — it’s clean engineering. Behind every 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 you understand how Helm really works, it stops feeling mysterious and starts feeling like your favorite DevOps assistant.


Quick Debug Tip#

Terminal window
helm ls -A
kubectl get secrets -A -l "owner=helm" -l "status=deployed"

Perfect for quick audits or just checking what Helm has been managing lately.

💬 Have a weird Helm issue or a release gone rogue?

Drop it in the comments — I love solving real DevOps mysteries together 💖

Tools I Personally Trust#

If you’re building things, breaking things, or just trying to keep your digital life a little calmer - these are tools I actually use every day:

🛸 Proton VPN (60% off link) - my invisible cloak online. It secures your Wi-Fi, hides your IP, and blocks trackers - even on the sketchiest café Wi-Fi.

🔑 Proton Pass (50% off link) - my password vault. On-device encryption for logins, 2FA, and notes - all mine and only mine.

🦑 GitKraken Pro (50% off link) - my visual Git sidekick. Gorgeous commit graph, painless merges, and fewer “what just broke?” moments.

💖 These links give you sweet discounts - and help support DevOps.Pink at no extra cost. Thanks a ton!


Social Channels#

🎬 YouTube
🐦 X (Twitter)
🎨 Instagram
🐘 Mastodon
🧵 Threads
🎸 Facebook
🦋 Bluesky
🎥 TikTok
💻 LinkedIn
📣 daily.dev Squad
✈️ Telegram
🐈 GitHub


Community of IT Experts#

👾 Discord


Refill My Coffee Supplies#

💖 PayPal
🏆 Patreon
🥤 BuyMeaCoffee
🍪 Ko-fi
Telegram Boost


Is this content AI-generated?

Absolutely not! Every article is written by me, driven by a genuine passion for Docker and backed by decades of experience in IT. I do use AI tools to polish grammar and enhance clarity, but the ideas, strategies, and technical insights are entirely my own. While this might occasionally trigger AI detection tools, rest assured—the knowledge and experience behind the content are 100% real and personal.

Inside Helm - How Charts, Releases, and State Work in Kubernetes
https://www.devops.pink/inside-helm-how-charts-releases-and-state-work-in-kubernetes/
Author
Tatiana Mikhaleva
Published at
2025-11-09
License
CC BY-NC-SA 4.0