Pitfalls of Helm – Insights from 3 years with the leading K8s package manager
Helm, Kubernetes’ de facto package manager, draws criticism for relying on string-based templating over YAML, sprawling `values.yaml` “APIs” without strong schemas, and brittle behaviors around upgrades, CRDs, and hooks. Many engineers argue Helm works best for distributing third‑party apps but is ill‑suited for day‑to‑day internal deployments, favoring alternatives like Kustomize, operators with CRDs, or full programming-language approaches (Pulumi, Jsonnet, CUE, Starlark, cdk8s). A recurring theme is that treating configuration as real code—with types, tooling, and clear ownership of state—yields more maintainable and debuggable Kubernetes workflows than Helm’s templating model.
Role of Helm and When It Fits
- Many see Helm’s main strength as packaging and publicly distributing complex Kubernetes apps, especially when consumers don’t want to understand all the details.
- Others argue Helm is a poor “package manager” and more of a mediocre templating engine; they compare it unfavorably to traditional OS package managers.
- For internal apps, several prefer other models: simple static YAML, kustomize overlays, or full-fledged operators/CRDs.
Common Pain Points with Helm
values.yamlis effectively an untyped, chart-specific API. Large, poorly documented values trees are seen as overwhelming and error-prone.- Lack of strong schema validation for values is a recurring complaint; some want inferred types from the underlying Kubernetes API.
- Go text templating over whitespace-sensitive YAML causes fragile charts, hard-to-read templates, and confusing error messages and line numbers.
- Maintaining complex, widely-distributed charts tends to push every field into values, leading to sprawling configuration surfaces.
- Operational issues raised: hooks considered an antipattern, unsafe or surprising upgrades, limited diff/plan capabilities, CRD and API version handling problems, and inability to easily see hook logs in CI.
Alternatives and Workarounds
- Common pattern: use
helm templateto render manifests, then apply them with other tools (Pulumi, Terraform, kapp, kustomize, Tanka/Jsonnet). - Kustomize is praised for a base+patch model and last-mile customization (including patching Helm output), but criticized for awkward syntax and multiple files per environment.
- Many advocate “config as code” with real languages: Pulumi (TS/Python/etc.), cdk8s, plain Python/TypeScript/Kotlin scripts, Pydantic models, or Terraform+generators.
- Dedicated config languages (Jsonnet, CUE, Dhall, Starlark) are seen by some as a better middle ground; others find them still too clunky or hard to debug.
- Operators + CRDs are viewed as more idiomatic for complex behavior and upgrades, but harder to write and sometimes blocked by cautious ops teams.
Broader Config-Language Reflections
- Strong backlash against string templating for structured data and “YAML everywhere.”
- Several predict a shift toward typed, schema-aware, language-based tooling and/or WASM-sandboxed modules, with GitOps tools (ArgoCD, Flux, Carvel) orchestrating the final applied manifests.