Helm vs. Kustomize: When Should You Use Each?
Helm is a full package manager with templating, dependency management, and release lifecycle. Kustomize is a template-free overlay system built into kubectl. Use Helm for distributing reusable charts and Kustomize for customizing plain YAML manifests across environments.
Detailed Answer
Helm and Kustomize are complementary tools for managing Kubernetes manifests. They solve different problems and are often used together in mature platform setups.
Philosophy Comparison
| Aspect | Helm | Kustomize | |--------|------|-----------| | Approach | Templating (generate YAML) | Patching (overlay YAML) | | Input | Go templates + values | Plain YAML + patches | | Output | Rendered YAML | Merged YAML | | Packaging | Charts (.tgz, OCI) | Directory structure | | Lifecycle | Install, upgrade, rollback, delete | None (just generates YAML) | | Dependencies | Built-in | None | | Distribution | Chart repositories, OCI registries | Git repositories |
Helm: When and Why
Helm is best when you need:
1. Package Distribution
# Publishing a reusable chart
helm package ./my-chart
helm push my-chart-1.0.0.tgz oci://registry.example.com/charts
# Consuming a third-party chart
helm install postgres bitnami/postgresql --set auth.database=myapp
2. Complex Parameterization
# values.yaml supports deep nesting and defaults
ingress:
enabled: true
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.example.com
3. Release Management
helm install my-app ./chart -f production.yaml
helm upgrade my-app ./chart -f production.yaml
helm rollback my-app 2
helm history my-app
helm uninstall my-app
4. Hooks and Tests
# Pre-upgrade database migration
annotations:
"helm.sh/hook": pre-upgrade
Kustomize: When and Why
Kustomize is best when you need:
1. Environment-Specific Overlays
base/
├── kustomization.yaml
├── deployment.yaml
├── service.yaml
└── configmap.yaml
overlays/
├── dev/
│ ├── kustomization.yaml
│ └── patch-replicas.yaml
├── staging/
│ ├── kustomization.yaml
│ └── patch-replicas.yaml
└── production/
├── kustomization.yaml
├── patch-replicas.yaml
└── patch-resources.yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: prod-
namespace: production
patches:
- path: patch-replicas.yaml
- path: patch-resources.yaml
images:
- name: myapp
newTag: "3.0.0"
# overlays/production/patch-replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 10
# Apply production overlay
kubectl apply -k overlays/production/
2. Plain YAML with No Templating
Kustomize works with standard YAML — no template syntax, no special delimiters. This makes manifests readable and validatable by standard YAML tools.
3. Built into kubectl
# No installation needed
kubectl apply -k ./overlays/production
kubectl diff -k ./overlays/production
kubectl kustomize ./overlays/production
Side-by-Side Example
The same customization in both tools:
Helm Approach
# values-production.yaml
replicaCount: 10
image:
tag: "3.0.0"
resources:
requests:
cpu: "500m"
memory: "512Mi"
helm install web ./chart -f values-production.yaml
Kustomize Approach
# overlays/production/kustomization.yaml
resources:
- ../../base
patches:
- target:
kind: Deployment
name: web
patch: |
- op: replace
path: /spec/replicas
value: 10
- op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "500m"
images:
- name: myapp
newTag: "3.0.0"
Using Both Together
A powerful pattern: use Helm for chart packaging and Kustomize for environment customization:
# Render Helm chart to plain YAML
helm template my-release bitnami/postgresql -f values.yaml > base/postgresql.yaml
# Apply Kustomize overlays
kubectl apply -k overlays/production/
ArgoCD supports this natively:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
spec:
source:
repoURL: https://charts.bitnami.com/bitnami
chart: postgresql
targetRevision: "12.0.0"
helm:
valueFiles:
- values.yaml
kustomize:
patches:
- target:
kind: StatefulSet
patch: |
- op: add
path: /metadata/annotations/custom
value: "true"
Decision Guide
| Criterion | Choose Helm | Choose Kustomize | |-----------|------------|-----------------| | Distributing to external consumers | Yes | No | | Complex conditional logic | Yes | No | | Environment overlays on plain YAML | No | Yes | | Release lifecycle (upgrade, rollback) | Yes | No | | Dependency management | Yes | No | | No additional tools | No | Yes (built into kubectl) | | Readable, standard YAML | No (templates) | Yes | | Third-party charts (Bitnami, etc.) | Yes | No |
Common Pitfalls
- Over-templating in Helm: Not everything needs to be a template parameter. Keep values.yaml focused on what actually changes.
- Deep overlay nesting in Kustomize: Too many overlay layers make it hard to understand what the final output looks like.
- Not rendering locally: Always run
helm templateorkubectl kustomizeto inspect output before applying. - Choosing based on preference, not requirements: Evaluate based on your distribution model, team expertise, and CI/CD tooling.
Why Interviewers Ask This
Teams frequently debate which tool to adopt. This question tests your ability to evaluate tools pragmatically based on use case rather than picking favorites.
Common Follow-Up Questions
Key Takeaways
- Helm excels at packaging, distribution, and managing the release lifecycle of complex applications.
- Kustomize excels at environment-specific customizations of plain YAML without templating.
- Many teams use both: Helm for chart packaging and Kustomize for environment overlays.