Comparison: Kubernetes Templating¶
Category: Developer Experience Last meaningful update consideration: 2026-03 Verdict (opinionated): Helm for packaging and distributing applications. Kustomize for environment-specific overlays on your own manifests. Use both together for the best workflow. Raw manifests only for learning or trivial deployments.
Quick Decision Matrix¶
| Factor | Helm | Kustomize | Carvel (ytt + kapp) | Raw Manifests |
|---|---|---|---|---|
| Learning curve | Medium | Low | Medium-High | None |
| Operational overhead | Low (Helm CLI) | None (built into kubectl) | Low (CLI tools) | None |
| Cost | Free | Free | Free | Free |
| Community/ecosystem | Massive (charts) | Large (built into K8s) | Small (VMware/Broadcom) | N/A |
| Hiring | Easy — Helm is standard | Easy — built into kubectl | Niche | Everyone |
| Templating approach | Go templates + values.yaml | Patches + overlays (no templates) | ytt (YAML-aware templates) | None |
| Package distribution | Helm registries (OCI) | No distribution model | imgpkg (OCI bundles) | Copy-paste |
| Dependency management | Chart dependencies | No | Vendir | No |
| Release tracking | Helm releases (stored in K8s) | None (applied manifests) | kapp (app-level tracking) | None |
| Rollback | helm rollback |
Git revert + re-apply | kapp rollback | Git revert + re-apply |
| Validation | Helm lint, template rendering | kubectl validate | ytt validate | kubectl validate |
| Hooks | Pre/post install, upgrade, delete | No | kapp change groups, ordering | No |
| Environment management | Values files per environment | Overlays per environment | ytt data values per environment | Separate directories |
When to Pick Each¶
Pick Helm when:¶
- You are deploying third-party applications (Prometheus, cert-manager, Ingress-NGINX) that distribute as Helm charts
- You need a packaging format to distribute your application with configurable defaults
- Release management (track what is deployed, rollback to previous versions) is important
- You want dependency management (a chart that depends on Redis, PostgreSQL, etc.)
- Your team is familiar with Go templates (or willing to learn)
Pick Kustomize when:¶
- You want to maintain a base set of K8s manifests and customize them per environment (dev, staging, prod)
- You prefer patches over templating — modify specific fields without parameterizing everything
- You want zero additional tooling —
kubectl apply -kworks natively - Your manifests are your own applications and you do not need a packaging/distribution format
- You dislike Go template syntax and want plain YAML with strategic merge patches
Pick Carvel (ytt + kapp) when:¶
- You want YAML-aware templating that understands YAML structure (not string interpolation like Go templates)
- kapp's change tracking and ordering (apply resources in dependency order, wait for readiness) appeals to your workflow
- You are in the VMware/Tanzu ecosystem
- You want imgpkg for distributing YAML bundles as OCI images
- You value correctness — ytt's data values and overlays prevent many classes of YAML generation bugs
Pick Raw Manifests when:¶
- You are learning Kubernetes and want to understand exactly what is being applied
- You have a trivial deployment (1-2 services, one environment)
- You use a GitOps tool (ArgoCD, Flux) that applies manifests directly
- Any templating tool adds complexity that is not justified by your use case
Nobody Tells You¶
Helm¶
- Go templates are powerful and ugly.
{{- if and (not .Values.ingress.enabled) (ne .Values.service.type "LoadBalancer") }}is real production Helm code. Debugging nested conditionals in Go templates is painful. helm template(local rendering) andhelm install(server-side) can produce different results. Helm hooks, lookups, and capabilities checks only work server-side. Always test withhelm install --dry-runagainst a real cluster.- Helm stores release state as K8s Secrets (base64-encoded). At scale (hundreds of releases), these Secrets accumulate. Set
--history-maxto avoid storing every revision forever. - Chart values schemas (
values.schema.json) are underused. Without a schema, any typo in values.yaml silently passes — you find the error when the deployment fails. Write schemas. - Helm chart version pinning is essential.
helm upgrade --install myapp bitnami/rediswithout--versiongets the latest chart version, which may have breaking changes. Always pin versions. - Subcharts (chart dependencies) create a dependency tree that is hard to debug. When Redis subchart values conflict with your chart's values, the error messages are unhelpful.
- Helm does not track resources that are removed from a chart. If you delete a resource from your templates,
helm upgradewill NOT delete it from the cluster. Use--cleanup-on-failand manage lifecycle carefully.
Kustomize¶
- Kustomize strategic merge patches work well for simple cases but become unwieldy for complex modifications. Adding an entirely new container to a deployment requires a JSON patch, which is less readable.
- Kustomize does not have a
values.yamlequivalent. Per-environment customization means overlays that duplicate configuration. For many environments, overlay sprawl is a real problem. - Kustomize does not manage releases or support rollback. If you apply a broken overlay, you must revert in git and re-apply. There is no
kustomize rollback. - The
kustomize build | kubectl apply -f -pattern loses the resource tracking thatkubectl apply -kprovides. Use-kfor server-side apply and tracking. - Kustomize generators (ConfigMapGenerator, SecretGenerator) append a hash to resource names. This forces a rolling update when config changes, which is often desirable but can surprise teams not expecting it.
- Kustomize and Helm work together well: use Helm for third-party charts and Kustomize overlays for environment-specific patches. ArgoCD and Flux both support this pattern.
- Secret handling in Kustomize is awkward. SecretGenerator creates Secrets from literal values or files, but the plain-text values must exist somewhere — Kustomize does not encrypt.
Carvel (ytt + kapp)¶
- Carvel is less known outside the VMware/Tanzu ecosystem. Community adoption is low, tutorials are scarce, and hiring for Carvel experience is difficult.
- ytt's Starlark-based YAML templating is technically superior to Go templates (it understands YAML structure), but the learning curve for Starlark syntax is its own investment.
- kapp's change tracking is genuinely excellent — it shows you exactly what will change, waits for resources to become ready, and applies changes in dependency order. This is better than
kubectl applyorhelm install. - VMware's acquisition by Broadcom has created uncertainty about Carvel's future. The project is open-source but corporate investment drives development velocity.
- vendir (vendoring) and imgpkg (OCI bundle distribution) are useful but niche. If you are not distributing YAML bundles, these tools add complexity without benefit.
Raw Manifests¶
- Raw manifests are perfectly valid for small deployments managed via GitOps. ArgoCD and Flux apply raw YAML directories efficiently.
- The problem with raw manifests appears when you need per-environment customization. Copy-pasting YAML files per environment and manually changing values is error-prone.
- Without templating, you cannot parameterize chart-like configurations. This means raw manifests work best when environments are identical except for resource limits and image tags.
Migration Pain Assessment¶
| From → To | Effort | Risk | Timeline |
|---|---|---|---|
| Raw manifests → Kustomize | Low | Low | 1-2 days |
| Raw manifests → Helm | Medium | Low | 1-2 weeks |
| Kustomize → Helm | Medium | Low | 1-2 weeks per app |
| Helm → Kustomize | Medium | Low | 1-2 weeks per app |
| Either → Carvel | Medium-High | Low | 2-4 weeks |
| Any → Helm + Kustomize | Medium | Low | 2-3 weeks |
Templating migration is low-risk because you can generate the manifests, diff them against what is deployed, and apply incrementally. The tooling change does not affect the running workload.
The Interview Answer¶
"Helm and Kustomize serve different purposes and work best together. Helm is a package manager — use it for third-party applications and when you need to distribute your app as a configurable chart. Kustomize is an overlay engine — use it for environment-specific patches on base manifests without introducing templating complexity. In practice, I use Helm charts with Kustomize overlays: Helm handles packaging and values, Kustomize handles per-cluster patches. The worst pattern is reimplementing Helm's features in Kustomize or using Helm when simple overlays would suffice."
Cross-References¶
- Topic Packs: Helm, Kustomize, K8s Ecosystem
- Related Comparisons: GitOps CD, IaC Tools