Kustomize is often presented as a simpler, more declarative alternative to Helm, but its real power lies in its ability to patch and overlay configurations without requiring a full templating engine.
Let’s see Kustomize in action. Imagine you have a base Kubernetes deployment.
base/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: main
image: nginx:latest
ports:
- containerPort: 80
Now, you want to create an overlay for production that increases the replica count and changes the image tag.
overlays/production/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- deployment-patch.yaml
overlays/production/deployment-patch.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
template:
spec:
containers:
- name: main
image: nginx:1.23.0
Running kustomize build overlays/production will output the combined YAML:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: main
image: nginx:1.23.0
ports:
- containerPort: 80
This system solves the problem of managing configuration drift across different environments (dev, staging, prod) and for different use cases without resorting to complex templating logic. Instead of variables and functions, Kustomize uses a declarative patching mechanism. You define a base configuration and then specify "overlays" that modify or add to that base. This makes it incredibly easy to understand what changes are being applied for a specific environment.
Internally, Kustomize works by parsing your base YAML files and then applying patches. These patches can be strategic merges (using Kubernetes’ patchStrategy) or JSON merges. The kustomization.yaml file is the heart of the operation, pointing to base resources and defining how those resources should be modified. You can also add new resources, configure common labels and annotations, and even define generators for ConfigMaps and Secrets.
The exact levers you control are primarily through the kustomization.yaml file and the patch files. You can:
resources: Point to directories containing base YAML files or otherkustomization.yamlfiles.patches/patchesStrategicMerge/patchesJson6902: Define how existing resources should be modified.patchesStrategicMergeis a common choice for its ability to intelligently merge fields.commonLabels/commonAnnotations: Apply labels or annotations to all resources generated by the kustomization.images: Override image tags and names for all containers across your resources. This is incredibly powerful for managing image versions.configMapGenerator/secretGenerator: Create ConfigMaps and Secrets declaratively from literal values, files, or even by encoding files.
Helm, on the other hand, is a full-fledged package manager. It uses Go templating to allow for dynamic generation of Kubernetes manifests. This means you can use loops, conditionals, and functions to create highly parameterized charts. While this offers immense flexibility, it can also lead to complex, hard-to-debug templates. Helm charts are also designed to be installable, upgradable, and deletable as a single unit, managing release lifecycles. Kustomize, by contrast, is purely a configuration builder; it doesn’t manage the lifecycle of your deployed applications. You use kubectl apply with Kustomize output.
A critical distinction often missed is how Helm handles multiple versions of the same chart. Helm installations are tied to "releases," and upgrading a release with a new chart version doesn’t typically overwrite the old chart’s templating logic in place. Kustomize, however, operates on the principle of immutable configurations. When you build a Kustomize configuration for a specific environment, the output is a set of static Kubernetes manifests. If you want to change something, you modify your Kustomize files and re-run kustomize build, generating a new, complete set of manifests to apply. This immutability can simplify auditing and ensure that the deployed configuration precisely matches what’s defined in your Git repository.
The next challenge you’ll likely face is integrating these tools into a CI/CD pipeline, deciding whether to use Helm charts directly or to use Kustomize to overlay and customize Helm chart outputs.