Helm 3: What Changed and Why It's Better
Back to Blog

Helm 3: What Changed and Why It's Better

5 min read
Read in Deutsch

Tiller Is History

In mid-November 2019, the Helm project released version 3.0. This major release introduces fundamental architectural changes that every Helm user should be aware of. The most important one upfront: Tiller is gone. For good.

If you read our article on Helm Charts, you may remember the section about Tiller -- the server-side component that ran inside the cluster and performed the actual deployments. We had written at the time that Tiller should be secured in production environments with restricted RBAC permissions and TLS. And that the community was actively debating Tiller's future. That debate is now settled.

The problems with Tiller were impossible to overlook in practice. In the default configuration, Tiller ran with cluster-admin privileges -- a single pod with full access to all namespaces and resources. In shared-cluster environments where multiple teams work on the same cluster, this was a security risk that couldn't be ignored. Securing it via dedicated service accounts, TLS certificates, and restricted namespaces was possible but complex and error-prone. In our projects, configuring Tiller was regularly the most complicated part of the Helm setup.

The New Architecture: Helm Talks Directly to the API

Helm 3 makes things radically simpler. There is no server-side process anymore. The Helm client communicates directly with the Kubernetes API server using the existing kubeconfig -- the same configuration that kubectl uses. A Helm user's permissions now correspond exactly to their Kubernetes permissions. If someone only has RBAC access to the staging namespace, they can only install Helm releases there. No workarounds, no special privileges.

This simplifies the setup considerably. Instead of installing Tiller, configuring service accounts, and managing TLS certificates, Helm 3 works right out of the box -- as long as kubectl already works. The helm init command is gone entirely.

# Helm 2: Tiller had to be installed first
helm init --service-account tiller --tiller-namespace my-team

# Helm 3: Just use it. Helm uses the active kubeconfig.
helm install my-app ./my-spring-app -f values-prod.yaml

Three-Way Strategic Merge: Upgrades That Know the Live State

One of the subtler but most impactful changes concerns the upgrade logic. Helm 2 only compared two states during a helm upgrade: the old chart manifest and the new chart manifest. What was actually running in the cluster didn't matter.

This led to a concrete problem. Suppose someone changed a configuration directly in the cluster via kubectl edit -- a replica count, a resource limit, an annotation. On the next helm upgrade, Helm only compared the old and new manifests. If nothing had changed there, nothing happened. The manual change persisted even though it wasn't reflected in the chart. Or worse: the manual change was silently overwritten if the same value happened to change in the new manifest.

Helm 3 uses a three-way strategic merge patch instead. It compares three states: the old manifest, the actual live state in the cluster, and the new manifest. Manual changes are detected. If the new manifest doesn't modify a value that someone manually adjusted, the manual change is preserved. If the new manifest explicitly sets the value, the manual change is overwritten -- but consciously and traceably.

In practice, this means fewer surprises during upgrades and more predictable behavior, especially in environments where hotfixes occasionally land directly on the cluster.

Release Storage: Secrets Instead of ConfigMaps

Helm 2 stored release information as ConfigMaps in the kube-system namespace. Each revision of a release created its own ConfigMap -- and these ConfigMaps contained the entire rendered manifest, including all values. Since ConfigMaps are not encrypted, sensitive values like database passwords or API keys were stored in plaintext in kube-system -- readable by anyone with access to that namespace.

Helm 3 stores release information as Kubernetes Secrets, in the same namespace as the release itself. This has two advantages: Secrets can be encrypted with encryption at rest, and the release data resides where it belongs -- alongside the resources it describes. Visibility follows the existing RBAC rules of the namespace.

Validation and New Chart Features

Helm 3 introduces two features that make charts more robust and maintainable.

JSON Schema Validation: Charts can now include a JSON Schema (values.schema.json) that validates the values.yaml. Incorrect or missing values are caught at helm install time, not at runtime in the cluster.

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["image", "replicaCount"],
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1
    },
    "image": {
      "type": "object",
      "required": ["repository", "tag"],
      "properties": {
        "repository": { "type": "string" },
        "tag": { "type": "string" }
      }
    }
  }
}

Especially for charts used by multiple teams or in CI pipelines, this prevents an entire class of errors. Instead of a cryptic template error message, you get a clear statement: "replicaCount must be an integer."

Library Charts: A new chart type that provides templates and helper functions but doesn't create any Kubernetes resources of its own. In the Chart.yaml, you mark a library chart with type: library. Other charts include it as a dependency and use its templates. For teams maintaining many similar charts -- such as a base template for Spring Boot services -- this significantly reduces duplication.

Migrating from Helm 2: The helm-2to3 Plugin Approach

The Helm team provides an official migration plugin that makes the transition easier. The plugin converts the Helm 2 configuration and migrates existing releases.

# Install the plugin
helm plugin install https://github.com/helm/helm-2to3

# Migrate Helm 2 configuration (repositories, plugins)
helm 2to3 convert my-release

# Clean up old Helm 2 release data
helm 2to3 cleanup

The migration is performed per release. helm 2to3 convert reads the ConfigMap from kube-system, converts it into a Secret in the release namespace, and creates the Helm 3 release structure. After that, Helm 3 manages the release, and the old ConfigMaps can be removed with cleanup.

Our advice: don't migrate everything at once. Start with the development environments, test the upgrades, and work your way toward production step by step. Helm 2 and Helm 3 can coexist since they use different storage backends.

Other Notable Changes

A few smaller but noteworthy changes:

  • helm install requires a release name: In Helm 2, you could have the name auto-generated (helm install ./chart). Helm 3 requires an explicit name or the --generate-name flag.
  • Namespaces are no longer created automatically: Helm 3 expects the target namespace to exist. You can use --create-namespace to enforce the old behavior.
  • helm test reworked: Test pods are no longer automatically deleted after the test run. This makes it easier to debug failed tests.
  • requirements.yaml removed: Chart dependencies are now defined directly in Chart.yaml under the dependencies key.

Conclusion

Helm 3 addresses the key weaknesses of Helm 2. The removal of Tiller alone justifies the migration -- RBAC setup becomes drastically simpler, and the attack surface in the cluster shrinks. The three-way merge makes upgrades more predictable, secret-based release storage more secure, and JSON Schema validation more robust.

If you're still running Helm 2 today, you should plan the migration soon. Helm 2 will only receive security updates until August 2020. The helm-2to3 plugin makes the transition manageable, and the CLI changes are limited. In our projects, we completed the migration within a few days per cluster -- the most time-consuming task wasn't Helm itself but updating the CI/CD pipelines.

Patrick Hütter

Written by

Patrick Hütter

Founder & Software Architect

Software architect, engineer and entrepreneur. Patrick has been building products and platforms for over a decade — from enterprise backends and cloud-native infrastructure to AI-powered applications. As founder of encircle360, he combines deep technical expertise with entrepreneurial vision, driving open source projects that create real impact.