Kustomize’s patchesStrategicMerge and patchesJson6902 allow you to modify existing Kubernetes resources, but sometimes you need to exclude specific resources from these patches.
Let’s see Kustomize in action. Imagine you have a base set of deployments and a patch that increases the replica count for all deployments.
base/deployment-a.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a
spec:
replicas: 1
selector:
matchLabels:
app: deploy-a
template:
metadata:
labels:
app: deploy-a
spec:
containers:
- name: main
image: nginx:latest
base/deployment-b.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-b
spec:
replicas: 1
selector:
matchLabels:
app: deploy-b
template:
metadata:
labels:
app: deploy-b
spec:
containers:
- name: main
image: httpd:latest
overlays/production/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- patch-replicas.yaml
overlays/production/patch-replicas.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a # Patching deployment-a
spec:
replicas: 3
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-b # Patching deployment-b
spec:
replicas: 5
If you run kustomize build overlays/production, you’ll see both deployment-a and deployment-b updated:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a
spec:
replicas: 3
selector:
matchLabels:
app: deploy-a
template:
metadata:
labels:
app: deploy-a
spec:
containers:
- image: nginx:latest
name: main
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-b
spec:
replicas: 5
selector:
matchLabels:
app: deploy-b
template:
metadata:
labels:
app: deploy-b
spec:
containers:
- image: httpd:latest
name: main
Kustomize’s patching mechanisms (patchesStrategicMerge and patchesJson6902) work by identifying resources based on their apiVersion, kind, and metadata.name. When you provide a patch file, Kustomize attempts to apply that patch to every resource in the generated output that matches the patch’s apiVersion, kind, and metadata.name. This is powerful for applying common changes, but it means you can’t easily exclude a resource from a patch if that patch targets a specific resource by name.
The trick to excluding resources from patches, especially when using patchesStrategicMerge or patchesJson6902, is to leverage Kustomize’s resources field in conjunction with a kustomization.yaml that doesn’t include the problematic patch.
Here’s how you’d exclude deployment-b from the replica patch. You create a separate kustomization.yaml for the production overlay that only includes the specific patch for deployment-a.
overlays/production/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
# This kustomization.yaml will *only* apply the patch-a.yaml
# We'll handle deployment-b separately or not at all if it's not meant to be patched.
patchesStrategicMerge:
- patch-a.yaml
overlays/production/patch-a.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a # Only patching deployment-a
spec:
replicas: 3
Now, if you run kustomize build overlays/production, you’ll see only deployment-a updated:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-a
spec:
replicas: 3
selector:
matchLabels:
app: deploy-a
template:
metadata:
labels:
app: deploy-a
spec:
containers:
- image: nginx:latest
name: main
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-b
spec:
replicas: 1 # deployment-b remains unchanged
selector:
matchLabels:
app: deploy-b
template:
metadata:
labels:
app: deploy-b
spec:
containers:
- image: httpd:latest
name: main
The key insight is that Kustomize processes patchesStrategicMerge and patchesJson6902 after resolving the resources list. If a patch file targets a resource by name, and that resource isn’t present in the output from the resources directive (or is removed by a previous transformation), the patch simply won’t find anything to apply. You’re not "skipping" a patch in the traditional sense; you’re structuring your Kustomize configuration so that the patch is never presented with the resource it’s intended to modify.
This also means you can have multiple kustomization.yaml files for different environments or purposes, each including or excluding specific patches as needed. For instance, you might have a base kustomization.yaml that lists all resources, and then an overlays/staging/kustomization.yaml that applies a subset of patches, and an overlays/production/kustomization.yaml that applies a different subset, effectively allowing you to "skip" patches for specific deployments in different contexts by simply not including them in the overlay’s kustomization.yaml.
The next challenge is often conditionally adding or removing entire resources, not just patching them.