You have a bunch of YAML files and want to customize them various ways. The Helm approach looks like this:
Template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ name-prefix }}runner
namespace: {{ namespace }}
labels:
{{ .extraLabels }}
Values:
name-prefix: dev-
namespace: my-namespace
extraLabels:
app: foo
(Example based on robusta.dev Helm chart, simplified for clarity)
There’s nothing wrong with the above, but after {{ time_period }} your {{ application_name }} has more swirly brackets than {{ noun }}. Is templating the only solution?
What are overlays?
Instead of using templates, we can use overlays. The general pattern goes like this:
You write base YAML files. These contain regular YAML that could be kubectl applied without modification.
You write an overlay file, which defines modifications and patches to the base.
Let’s re-write the above example. We’ll use Kustomize, an overlay tool for Kubernetes.
Base:
apiVersion: apps/v1
kind: Deployment
metadata:
name: runner
Overlay:
namespace: my-namespace
namePrefix: dev-
commonLabels:
app: foo
Note that namespace, namePrefix, and extraLabels in the Helm chart were arbitrary variable names!
On the other hand, namespace, namePrefix, and commonLabels in the overlay are Kustomize keywords that do something very specific. For example, when Kustomize sees a namespace variable then it parses all your YAML files into Kubernetes resources and adds a namespace to each and every resource that supports it. (It is smart enough to not add the namespace attribute to cluster-level resources like ClusterRoleBinding.)
Are overlays and templates the same?
Helm templates consist of:
Templated YAML files (the template)
A values file (template variables)
Kustomized files consist of:
Base YAML files (the base)
A modifications file (the overlay)
On the surface, these two approaches seem similar. However, they’re fundamentally different.
What is the core difference between overlays and templates?
With templates, the base template is aware of all possible customizations. The template needs to expose every {{ knob }} that end users want to change. Templates and value files are tightly coupled.
With overlays, the base has no knowledge of future customizations. Overlays can change anything in the base, regardless of the base-writer’s intentions.
Why does this matter? Over time, Helm charts need to expose more and more variables for every possible customization. This makes them hard to maintain.
With Kustomize, the base is always kept simple. The burden moves to the end user’s Kustomization, which is often less complex for each individual end user.
Kustomize in two sentences
Here’s an alternative perspective that doesn’t speak about Helm, templates, or overlays.
Imagine that kubectl apply had an --add-label parameter. Take that imaginary flag, make it a little more advanced, and you get Kustomize.
What should I use - Kustomize or Helm?
Try them both and choose what fits your use case best!
You can also use them togther with Helm post-render hooks.