Kustomize Patches: Strategic Merge vs. JSON 6902, Explained Simply

After my post on deleting a resource with Kustomize, a common follow-up question was how to change things instead of removing them. Kustomize calls this patching, and it offers two styles.

Both live under the patches field of your kustomization.yaml. (The older patchesStrategicMerge and patchesJson6902 fields are deprecated, so prefer patches.)

Strategic merge: “here’s what it should look like”

You write a partial manifest, and Kustomize merges it into the original by matching kind and metadata.name.

replicas.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3

kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
patches:
  - path: replicas.yaml

It reads like the resource itself, which makes it easy to review. It also knows how to merge lists of containers by name instead of replacing the whole list.

JSON 6902: “here are the exact operations”

You list operations (add, replace, remove) against explicit paths, and a target picks the resource.

patches:
  - target:
      kind: Deployment
      name: web
    patch: |-
      - op: replace
        path: /spec/template/spec/containers/0/image
        value: ghcr.io/example/web:1.4.2

This is precise, and it can do things a merge can’t, like removing a single field or editing one list item by index. The downside is brittleness: containers/0 breaks if someone reorders the containers.

Which should I use?

  • Changing a value or adding a field: strategic merge.
  • Removing a field, or a surgical edit: JSON 6902.
  • Applying the same tweak to many resources: either one, with a target that uses a label selector or a kind.

Deleting with a patch

A strategic merge patch can also remove a resource:

$patch: delete
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web

Check your work

Always render before you commit:

kubectl kustomize overlays/prod | less

If the output isn’t what you expected, the patch isn’t doing what you think. This takes ten seconds and saves a bad deploy.