I was a Helm believer. Charts, values files, the whole ecosystem - I thought it was the way to manage Kubernetes manifests. Then one day, a single misplaced curly brace made me question everything.
π₯ The Breaking Point
It was a Friday afternoon (because when else do things break?). I was updating our production Helm chart to add a new environment variable. Simple task, right? Just add one line to the values.yaml and update the template.
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- if .Values.extraEnv }}
{{ toYaml .Values.extraEnv | indent 2 }} # <- The indent was wrong
{{- end }}
One wrong indent. That's all it took. The deployment went out, pods started crashing, and I spent the next 3 hours debugging YAML templating instead of actual infrastructure problems.
π€ What Was Wrong With Helm
Don't get me wrong - Helm is powerful. But with power comes complexity:
- Templating syntax is confusing - Go templates inside YAML? My brain hurts.
- Debugging is painful -
helm template --debugonly gets you so far - Values inheritance is complex - Multiple values files can lead to unexpected overrides
- The rendered output is hard to review - What actually gets applied?
β¨ Discovering Kustomize
Kustomize takes a different approach: instead of templating, it uses overlays and patches. Your base manifests are plain YAML - no templates, no special syntax. Then you layer modifications on top.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
namePrefix: prod-
patches:
- patch: |-
- op: replace
path: /spec/replicas
value: 3
target:
kind: Deployment
The beauty? Every file is valid YAML. You can kubectl apply the base directly. You can see exactly what changes each overlay makes.
π The Migration
Migrating wasn't instant, but it was straightforward:
- Run
helm templateto get the rendered manifests - Split them into logical base files
- Create overlays for each environment
- Test with
kustomize build
βοΈ The Verdict
After 6 months with Kustomize, here's my take:
Simpler Mental Model
Base + Patches = Final manifest. That's it.
Better Git Diffs
Plain YAML means meaningful code reviews.
Native kubectl Support
kubectl apply -k just works.
Less Flexible
Complex logic is harder (but maybe that's good?).
Would I go back to Helm? For complex third-party charts, maybe. For my own applications? Kustomize all the way.
What's your experience with Helm vs Kustomize? Share your thoughts!