Helm: The Kubernetes Package Manager That Fired Its Own Daemon

A Deis hackathon package manager merged with Google's in-cluster Deployment Manager in January 2016; the merged server became Tiller — and Helm's biggest liability.

Sources

The most widely used tool in the Kubernetes ecosystem started life twice. Once as a Deis hackathon project that wanted to be Homebrew for Kubernetes, and once as a quiet Google port of its cloud Deployment Manager — a repo whose first commit reads, without any of today's branding, "Initial commit for DeploymentManager on k8s." The two teams merged instead of forking, gave the merged thing a nautical name, and for three years shipped an in-cluster server called Tiller that became the default-install liability penetration testers turned into standard material. This is the story of how the Kubernetes package manager was born, how its founding architecture turned into a crisis that every cluster administrator learned by heart, and how the project survived it by performing major surgery on itself — then spent the next six years, and counting, managing its own succession.

The Origin: Born Twice, Named Once

A hackathon project at Deis (October 2015)

By its own maintainer's account, Helm began as an internal hackathon project at Deis, the PaaS startup that had moved its platform from Fleet to Kubernetes in mid-2015. The rewrite forced the team to rebuild deisctl, its installation tool, and what came out of that rebuild was modeled not on Terraform-style infrastructure code but on package managers — Homebrew, apt, yum. The git record is unusually clean: the repository that would become Helm was created on , and its first commit is a single line from Matt Butcher: initial add. Within a day, Jack Francis was committing design docs and Matt Butcher was scaffolding chart models and the helm command. That first version — announced at the inaugural KubeCon in San Francisco in November 2015 — was retroactively named Helm Classic, and its repo survives today, archived, with the description "⚠️(OBSOLETE) Helm Classic v1."

Google's Deployment Manager, a port with a server (October–November 2015)

Meanwhile, a team inside Google had been porting the Google Cloud Deployment Manager to Kubernetes. The repo object that hosts today's Helm was created on — two weeks before Deis's first commit — and its root commit landed on November 2, 2015, from Victor Agababov: "Initial commit for DeploymentManager on k8s." The early commit log is a Google roster — Jack Greenfield, Ville Aikas, Brendan Melville, Zach Loafman — shipping templates for Spark and WordPress as "DM templates." Within five days the repo was being merged from the kubernetes/deployment-manager remote, and the project lived in the Kubernetes org. Crucially, dm had something Helm Classic did not: a server-side component running inside the cluster that held deployment state and talked to the Kubernetes API on the client's behalf.

The git archaeology that proves the lineage — because GitHub's own redirect API tells the story more honestly than any history page:

helm/helm  (GitHub repo ID 43723161, created 2015-10-06)
├── root  94db53d0  "Initial commit for DeploymentManager on k8s."   (Victor Agababov, 2015-11-02)
├──       0868355d  "feat(cmd): add grpc client and server"          (Matt Butcher, 2016-04-08)
│                    — first commit under cmd/tiller: dm's server has a new name
└── path  kubernetes/deployment-manager (2015-11)
            → kubernetes/helm (2016, post-merger)
            → helm/helm (July 2018, org move; same repo object)

helm/helm-classic  (GitHub repo ID 44570556, created 2015-10-19, archived)
└── root  ecad6e2ef  "initial add"                                    (Matt Butcher, 2015-10-19)
            — Helm Classic v1, announced at the inaugural KubeCon, November 2015

Seattle, January 2016: merge, don't fork (2016)

As 2015 wound to a close, the Google team reached out to the Helm team; both had been building a Kubernetes deployment tool, and in January 2016 the two teams sat down in Seattle. As Matt Butcher tells it on the Kubernetes Podcast: "we just kind of did something rarely done in open source projects and merged two projects and just played up to the strengths of each of the two." Skippbox joined the development team, then Bitnami. The merged project was built inside the Deployment Manager repo — which is why today's helm/helm has dm's root commit — and the merged codebase moved under the Kubernetes org as kubernetes/helm. The server-side component that survived from dm got its new name by April 2016, when the first commit under cmd/tiller landed: Tiller, the lever that turns a boat's rudder. Kubernetes is Greek for helmsman; Helm steers the ship, Tiller turns the rudder, and Charts are nautical charts. The naming was never an accident.

The first public artifact of the merged project, Helm 2.0.0-alpha.1 (May 25, 2016), described the architecture plainly: "The helm client, whose responsibility is to provide tooling for working with charts and uploading them to the server" and "the tiller server, whose responsibility is to manage releases into the Kubernetes cluster." The v2.0.0 GA release (November 2016) reported 2,200 commits from almost 70 contributors in one year, and a chart repository with "over two dozen charts" — the seed of the ecosystem's biggest dependency.

The Timeline: From Two Repos to the Package Manager of Record

Crisis Points & Architectural Pivots

Tiller: the server that became the liability

The Tiller architecture was not an accident; it was the point of the 2016 merger. dm's server-side component was what Google brought to the table, and it answered a real 2016 problem: clusters were shared, multiple operators worked the same releases, and state needed to live somewhere everyone could see. Tiller held release state, rendered on request, and applied manifests to the Kubernetes API — as Tiller, using its own service account, not the identity of the person running helm.

The collision arrived with RBAC. In the project's own retrospective: "With role-based access controls (RBAC) enabled by default in Kubernetes 1.6, locking down Tiller for use in a production scenario became more difficult to manage. Due to the vast number of possible security policies, our stance was to provide a permissive default configuration... Unfortunately, this permissive configuration could grant a user a broad range of permissions they weren't intended to have." The path from there to full cluster takeover was two steps, and every tutorial installed it that way:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin          # "the easiest way to get up and running"
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system

With Tiller listening on gRPC port 44134 inside the cluster, without authentication by default, the takeover demo that ropnop published in January 2019 reduced to a single command from any compromised pod:

# attacker inside the cluster — Tiller applies the chart as cluster-admin
helm --host tiller-deploy.kube-system:44134 install --name pwn ./malicious-chart

The official fix was TLS and mTLS between client and Tiller — a documented, multi-step certificate ceremony that — as ropnop observed — countless tutorials and Stack Overflow answers glossed over, which is why organizations were "ditching the cluster side install of Helm ('Tiller') entirely for security reasons." The community's answer was blunter: the Tillerless plugin (July 2018) ran Tiller as a local subprocess under each operator's own kubeconfig, so the in-cluster server could be deleted outright. When the community's escape hatch is a plugin whose entire job is to stop the tool's server from existing, the architecture is already dead — it just hadn't been announced yet.

The announcement came with the Helm 3 preview series, whose second installment is titled, without euphemism, "A Gentle Farewell to Tiller." The reasoning is the most instructive part of the story: the team had concluded that "Tiller's primary goal could be accomplished without Tiller" — fetch from the API server, render charts client-side, store release records as Secrets in Kubernetes. The one architectural bet of the 2016 merger was deleted, and with it the entire class of port-44134 advisories:

flowchart LR
    subgraph H2["Helm 2 (2016 - 2019): client and server"]
        C1["helm CLI
renders charts"] --> T["Tiller in-cluster server
port 44134, gRPC, no auth by default
state in kube-system"] T --> K1["Kubernetes API
as Tiller's service account
(usually cluster-admin)"] end subgraph H3["Helm 3 (2019 - today): client only"] C2["helm CLI
renders charts"] --> K2["Kubernetes API
as your kubeconfig identity
releases stored as Secrets"] end
DimensionHelm 2 (2016–2020)Helm 3 (2019–present)
ArchitectureClient + in-cluster Tiller serverSingle client binary
Who talks to the API serverTiller's service account — too often cluster-adminYou, via kubeconfig identity and RBAC
Network exposuregRPC on 44134, unauthenticated by defaultNone — no in-cluster component
Release stateConfigMaps in kube-systemSecrets in the release's own namespace
Release namesCluster-globalScoped to a namespace
Install ceremonyhelm init, service account, RBAC, optional TLSNone — point it at a cluster
Chart metadataChart.yaml v1 + requirements.yamlChart.yaml apiVersion v2 (consolidated)
Values validationNoneOptional JSON schema
Support endedNovember 13, 2020Security patches end February 10, 2027

The charts empire, and its managed decline

Helm's second structural pivot was about ownership of the catalog. The official stable and incubator chart repositories — two dozen charts at v2.0.0's GA, hundreds by 2018 — were the project's crown jewels and its operational nightmare: a single curated repo every vendor wanted merged into and nobody wanted to maintain. The unwinding was deliberate and well-sequenced: the repositories moved out of the Kubernetes org with Helm itself (2018), the bug-fix window for the era closed in August 2020, v2.17.0 (October 26, 2020) shipped explicitly as the EOL release that moved the stable and incubator repositories "to a new location that will serve as a long term archive," and on November 13, 2020 both Helm 2 and the curated-repo model died together — archive locations announced, repo marked obsolete.

Discovery moved first: the Monocular-based Helm Hub (December 2018) became the front door for chart search, and was redirected to the Artifact Hub in October 2020 — the project's own admission that running a chart search engine had become a different job from building a package manager. Distribution followed: Helm 3.8.0 (early 2022) made OCI registries a generally available alternative to chart repository servers, so charts now live in the same registries as images — the same registries your platform already authenticates to, scans, and rate-limits. The package manager stopped being a publisher; the ecosystem inherited the quality-control problem, and platform teams inherited the vetting.

The CVE nobody agreed with (2024)

Five years after the Tiller era ended, Helm picked up a crisis that tells you more about security-disclosure culture than about Helm. In March 2024, CVE-2019-25210 — a 2019-pool CVE ID assigned half a decade late — was published against Helm, claiming that helm install --dry-run printing Secret manifests to stdout was a vulnerability, filed without engaging the project's documented security process and with no notice. The project's response was unusual for an OSS project: a public rejection. "The Helm project rejects this disclosure's assertion of a vulnerability within Helm" — dry-run output is the feature, the CWE (200) is one whose own documentation discourages its use, and "if this functionality is used in an environment that captures the output for unauthorized actors, such as in a CI system, then the vulnerability is in the use of a tool that outputs this information, rather than in the tool itself." Then, pragmatically, they added documentation and a flag to hide secret values in dry-run output anyway. NVD scored it 6.5 medium — and embedded the vendor's rebuttal inside the CVE description itself. A decade-old tool with two third-party audits, a fuzzing audit, a security assurance case, and signed releases still has to spend maintainer time litigating drive-by CVEs; the disclosure pipeline has no EOL.

Helm 4 and the slow fade of Helm 3

Helm 4 arrived on November 12, 2025 — during the Helm 4 presentation at KubeCon + CloudNativeCon, six years after Helm 3, and a few weeks after the project's own ten-year retrospective. Matt Farina's release post is candid about why it took six years: "we also saw where we wanted to add features but the internal architecture of Helm didn't provide a path forward without breaking public APIs in the SDK." The changes are mostly plumbing modernization with teeth: a redesigned plugin system that supports WebAssembly plugins, post-renderers becoming plugins, server-side apply support, kstatus-based resource waiting, local content caching, reproducible chart archives, and an experimental v3 chart API version. The teeth: renamed flags (--atomic is now --rollback-on-failure, --force is --force-replace) — the kind of breaking change that hunts every CI script written since 2019.

The more interesting 2026 story is the succession management. The original plan (HIP-0012) gave Helm 3 security fixes until November 2026; in June 2026 the maintainers extended that to February 10, 2027, "giving the community more time to complete the migration," with one final, deliberately limited v3 minor in September 2026 (Kubernetes client library updates only). The dual-branch tax is visible in the release feed: v4.3.1 and v3.22.1 shipped the same day (October 15, 2026), and the schedule still pairs 3.22.2 with 4.3.2 on November 11, 2026 before 4.4.0 lands on January 13, 2027. Helm has now run every major-version handover twice: the v2→v3 window (2019–2020, one year, plus a COVID extension) and the v3→v4 window (2025–2027, fifteen months plus a three-month extension). The pattern is honest — overlap beats hard cutoffs — but it also means the maintainers have effectively been maintaining two majors at a time for most of the project's life.

BranchLatest (Nov 2026)StatusEnd of life
Helm 4 (v4.3.x)v4.3.1 (2026-10-15)Active development; 4.4.0 due January 13, 2027—
Helm 3 (v3.22.x)v3.22.1 (2026-10-15)Security patches only; final minor was v3.22.0 (Sept 9, 2026)February 10, 2027
Helm 2 (v2.17.0)v2.17.0 (2020-10-26)Unsupported; docs still online for referenceNovember 13, 2020

Community Engine & Corporate Influence: Who Actually Built It

Helm's cast is unusually legible because it was born from a merger of engineering cultures. On the Deis side: Matt Butcher (the initial add author, and — eleven years on — still listed in the maintainer OWNERS file as technosophos), Jack Francis, and Rimas Mocevicius, who moved to emeritus in 2018. On the Google side: Jack Greenfield (the dm architect), Ville Aikas, Victor Agababov, and Brendan Melville. Around them: Skippbox and then Bitnami, the company that had been building production-grade images and charts before Helm 2 existed and supplied much of the early charting expertise. The first GA release notes read like a census of the merged team: 2,200 commits from almost 70 contributors inside a year.

The corporate story matters here more than usual, because Helm's independence was engineered after the fact. Microsoft announced its acquisition of Deis on April 10, 2017 (from Engine Yard, as TechCrunch noted), which meant the package manager of the Kubernetes ecosystem had its core maintainers on Microsoft payroll while the Kubernetes org it lived in was dominated by Google. The resolution was the standard one, executed cleanly: Helm entered the CNCF in June 2018 as an incubating project, completed its move out of the Kubernetes org in July 2018, and on April 30, 2020 became the tenth CNCF project to graduate. The graduation release counted 28 active maintainers from 16 organizations — "including Blood Orange, IBM, Microsoft, Samsung SDS" — 13,000+ contributions from over 1,500 companies, ~2 million downloads a month, and named production users from AT&T to CERN to Conde Nast. No single company controls Helm — the foundation does, by charter and by audit.

The security maturity arc is real and worth crediting: a CNCF-funded Cure53 audit of Helm 3 (November 2019) — "recommended for public deployment," one noteworthy finding, no exploit — a second security audit in 2021, a completed fuzzing audit in 2023 with continuous fuzzing after, a documented security process, and release binaries GPG-signed by the maintainer producing the release. Today's maintainer roster in OWNERS is ten people — banjoh, gjenkins8, joejulian, marckhouzam, mattfarina, robertsirc, sabre1041, scottrigby, technosophos, TerryHowe — with an emeritus list (adamreese, bacongobbler, fibonacci1729, hickeyma, jascott1, jdolitsky, michelleN, migmartri, nebril) that reads as a memorial to every era of the project. The repo itself counts 369 contributors and 30,000+ stars, and the release notes for v3.22.1 still end with the same Slack channel and Thursday developer call the alpha releases advertised in 2016.

Current Trajectory: The Verdict

The trajectory question for Helm in late 2026 is not whether the tool works — it demonstrably does, and the February 10, 2027 deadline for v3 security patches is the only hard date anyone on a v3 pipeline needs memorized. The question is what kind of software Helm is becoming, and the honest answer is: less of a command-line product and more of a format and a library. Charts are the industry's packaging lingua franca — your GitOps controller almost certainly renders them (see our Argo CD tale and Flux tale for the controllers that consume charts without Helm-the-CLI being the deployer), the SDK is embedded across the delivery tooling on the CNCF landscape, and distribution has quietly shifted to the OCI registries teams already operate. The CLI you run by hand is increasingly the smallest part of Helm's footprint.

Three open threads for platform teams. First, the migration math: if you still run v3 in CI, the renamed flags and plugin-based post-renderers are the two things most likely to break your pipelines on the v4 hop — and after February 2027, staying on v3 means riding unpatched Kubernetes client libraries, the exact corner the Helm 3 EOL post tells you to leave. Second, hygiene beyond releases: the May 2026 baltocdn.com domain-lapse notice was a small incident with a large lesson — a package manager's attack surface includes mirror domains that outlive their maintainers, so pin your install scripts to get.helm.sh and verify signatures. Third, keep the dependency model honest: helm dependency update vendors dependencies into your chart's charts/ directory and manages them from there — a vendored-subtree model, not a dependency solver in the apt/yum sense; version drift between Chart.lock and reality is your problem, not Helm's.

Verdict: Helm earned its monopoly the hard way — by shipping the format everyone agreed on, and by being willing to delete its own load-bearing component when the security math turned against it. The Tiller crisis is still the best case study in the CNCF portfolio of a project surviving its founding architecture, and the current dual-branch fade-out shows the same institutional discipline: no hard cutoffs, no heroics, just a published schedule and an EOL date enforced in public. Who should skip it? Teams running fully declarative GitOps delivery don't need the Helm CLI in their pipelines at all — their controllers render charts fine — and greenfield teams with no chart estate should not adopt one just because everyone else did. Everyone else should be on Helm 4 before February 10, 2027, with signature verification on, and a Chart.lock committed. (For the delivery systems that consume Helm's output rather than its CLI, see our Argo CD and Flux tales; for the packaging story's infrastructure counterpart, our containerd tale covers the other half of what actually runs in your cluster.)