Packaging: Helm 3 & Kustomize
Two complementary tools manage manifest complexity. Helm 3 uses templating plus chart packaging plus release lifecycle management. Kustomize uses structured overlay files that transform base manifests
Two complementary tools manage manifest complexity. Helm 3 uses templating plus chart packaging plus release lifecycle management. Kustomize uses structured overlay files that transform base manifests for different environments with no templates and no render step.
-
Helm 3 renders Go templates from a chart's templates/ directory combined with values into raw Kubernetes manifests.
-
Release state stored as a Secret in the target namespace. No Tiller in Helm 3 -- operations use invoking user's kubeconfig.
-
Kustomize is a pure patch/overlay system: a base directory with plain YAML, overlays add/modify via strategic merge patches.
-
Both can be combined: helm template renders to manifests that become a Kustomize base.
-
For Helm: scaffold a chart (helm create ) with Chart.yaml, values.yaml, and a templates/ directory of Go-templated manifest files.
-
Parameterize the manifests in templates/ with {{ .Values.* }} references, and define sane defaults in values.yaml.
-
Install a release with helm install -f values-prod.yaml, layering environment-specific value overrides on top of the chart defaults.
-
Upgrade with helm upgrade, and roll back with helm rollback using Helm's tracked release history (stored as a Secret in the target namespace).
-
For Kustomize: start with a base/ directory of plain, un-templated Kubernetes YAML plus a kustomization.yaml listing those resources.
-
Create overlays/ (e.g. overlays/staging, overlays/production) each with their own kustomization.yaml applying strategic-merge or JSON patches on top of the shared base, then apply with kubectl apply -k overlays/production.
-
Publishing a reusable Helm chart for an internal platform service so every team installing it gets consistent defaults, customized per-team only via values.yaml overrides.
-
Using Kustomize overlays for dev/staging/production variants of the same base manifests -- same Deployment, different replica counts and resource limits per overlay, with no templating logic to maintain.
-
Combining both: helm template renders a third-party chart (e.g. a database operator) down to plain manifests, which then become a Kustomize base for further environment-specific patching.
-
Using helm rollback to revert a bad production release to the previous known-good revision during an incident, using Helm's built-in release history instead of manual git-revert-and-reapply.
-
A platform team maintaining a library of Kustomize bases for common patterns (e.g. a standard Deployment+Service+HPA trio) that individual services overlay with their own image and config.
-
Keep Helm chart values.yaml well-documented with comments and sensible defaults -- a chart with cryptic, undocumented values is hard for other teams to safely adopt.
-
Use
helm templatelocally (or in CI) to review the exact rendered manifests before install/upgrade, since Go template logic can produce subtly wrong YAML that's hard to spot from the template source alone. -
Prefer Kustomize's strategic-merge patches over full-resource replacement in overlays -- smaller, targeted patches are easier to review and less likely to silently drop fields the base defines.
-
Pin chart versions explicitly in CI/CD (not just 'latest') so deployments are reproducible.
-
Structure Kustomize overlays to differ minimally from the base -- if an overlay patches nearly every field, that's usually a sign the base isn't shared enough to be worth the indirection.
-
Use
helm diff(plugin) orkustomize build | kubectl diff -f -before applying changes in production, to see exactly what will change before it does.
-
Writing complex conditional logic deep inside Helm Go templates instead of keeping charts simple -- hard-to-read templates become hard-to-debug production incidents when a value doesn't render as expected.
-
Assuming
helm upgradeis always safe -- a chart change combined with a values change can trigger far more resource replacement than expected; always review withhelm diffor--dry-runfirst. -
Duplicating near-identical full manifests across Kustomize overlays instead of patching a shared base -- defeats the purpose of Kustomize and multiplies drift risk.
-
Forgetting Helm 3 stores release state as a Secret in the target namespace -- deleting that namespace loses Helm's own history/rollback capability even if the actual resources are managed elsewhere.
-
Not pinning chart versions in production deployment pipelines, so 'the same install command' silently deploys a different chart version over time.
-
Using Kustomize's patchesStrategicMerge in a way that unintentionally drops list fields (like container args) since strategic merge patch semantics for lists differ from a naive merge people expect.
-
helm template/helm installrendering cost grows with chart complexity (nested subcharts, heavy template logic) -- very large umbrella charts can noticeably slow CI pipeline render/lint steps. -
Kustomize's build step re-parses the full overlay+base tree on every invocation -- for very large multi-overlay repos, this can add real seconds to CI; keep overlay trees reasonably shallow.
-
Splitting one giant Helm chart into several smaller, independently-releasable charts reduces blast radius and per-deploy render/diff time compared to one monolithic chart covering an entire platform.
-
Avoid unnecessary Helm subchart dependencies that aren't actually used -- each adds to install/upgrade time and rendered manifest size.
-
Store chart values (especially production values files) in version control alongside application code, reviewed through the same PR process as everything else -- not passed ad hoc on the command line.
-
Use
helm upgrade --install --atomic(or equivalent CI wrapping) so a failed upgrade automatically rolls back rather than leaving the release in a broken intermediate state. -
Keep a documented rollback procedure tested in advance (
helm rollbackrevision numbers, or reapplying a prior Kustomize overlay commit) -- don't discover how rollback works during an incident. -
Lock Helm chart versions and Kustomize base image tags to specific, reviewed values in production overlays -- never track 'latest' in a production deployment path.
-
Scaffold a Helm chart with
helm create, parameterize the replica count via values.yaml, and install it with two different values files producing different replica counts. -
Run
helm rollbackafter an intentional bad upgrade (e.g. an invalid image tag) and confirm the release returns to the prior working revision. -
Build a Kustomize base with a Deployment and Service, then create a staging and production overlay that each patch just the replica count and resource limits.
-
Run
helm template <chart> | kubectl apply -f -to render a chart to plain manifests, then use that output as the base/ directory for a new Kustomize setup.
-
Helm 3 templates + packages + tracks release lifecycle (install/upgrade/rollback) using per-namespace Secrets.
-
Helm 3 removed Tiller -- all operations use the invoking user's kubeconfig credentials.
-
Kustomize patches plain YAML bases with overlay patches -- no templating, built into kubectl.
-
Helm for packaging reusable software; Kustomize for environment-specific variation.
Want a visual for this concept?
Generate a diagram tailored to “Packaging: Helm 3 & Kustomize” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.
Sign in to generate a visual →