Kustomize’s strategic merge patch lets you selectively override fields in a base manifest without resorting to full-blown JSON merges, making your overlays cleaner and more predictable.

Let’s see Kustomize in action with a typical Kubernetes deployment.

Here’s our base deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: nginx:1.23.0
        ports:
        - containerPort: 80

And here’s our kustomization.yaml in a separate directory (let’s call it overlays/dev):

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base

patchesStrategicMerge:
- deployment-patch.yaml

Now, deployment-patch.yaml in the same overlays/dev directory:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: my-app-container
        image: nginx:1.24.0

When you run kustomize build overlays/dev, you get this output:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: nginx:1.24.0
        ports:
        - containerPort: 80

Notice how replicas changed from 1 to 3, and the image for my-app-container updated from nginx:1.23.0 to nginx:1.24.0. The ports section, however, was untouched because it wasn’t specified in the patch. This is strategic merge patching in action. Kustomize intelligently merges the patch with the base manifest, prioritizing the patch’s values for the fields it specifies.

The core problem Kustomize strategic merge patch solves is managing environment-specific configurations without duplicating entire Kubernetes manifests. Imagine you have a base application deployment. For development, you might want fewer replicas and a newer image. For production, you’ll need more replicas, possibly a different resource request/limit, and a stable image tag. Without strategic merge, you’d have to copy your entire deployment.yaml for dev, staging, and prod, making even small changes a tedious, error-prone process. Strategic merge allows you to define a base and then apply targeted "patches" that modify only the necessary fields for each environment.

Internally, Kustomize uses a JSON merge patch strategy but with a "strategic" overlay. For lists, it tries to be smart. If a list has items with a unique identifier (like name for containers or path for volumes), Kustomize will find the matching item in the base and merge the patch’s changes into it. If no matching item is found, it appends the new item from the patch. For simple lists without unique identifiers, it replaces the entire list. This intelligent merging is what makes it "strategic."

The key levers you control are the patchesStrategicMerge field in your kustomization.yaml. This field takes a list of YAML files. Each file contains a partial Kubernetes resource that Kustomize will attempt to merge with its corresponding resource in the base. The matching is done by apiVersion, kind, and metadata.name. If a resource with the same apiVersion, kind, and metadata.name exists in the base, Kustomize will apply the patch.

The most surprising thing about Kustomize’s strategic merge patch is how it handles lists. While many might assume it always appends or always replaces, it actually attempts to merge based on specific fields. For example, when patching a Deployment’s spec.template.spec.containers list, Kustomize looks for a container with the same name in the base and the patch. If it finds my-app-container in both, it merges the image and other fields from the patch into the base’s my-app-container. If you add a completely new container definition in the patch, it will be appended to the list. This behavior is crucial for understanding how to effectively modify or add to existing lists of resources within your Kubernetes objects.

You can also use patches (not patchesStrategicMerge) for more complex, non-strategic JSON merges or when you need to target resources without a name (like Namespace or ServiceAccount in some contexts), but patchesStrategicMerge is preferred for its predictability when dealing with common Kubernetes resources.

The next concept you’ll likely encounter is managing secrets and configmaps, and how Kustomize can help generate or modify them safely.

Want structured learning?

Take the full Kustomize course →