The power of kustomize lies in its ability to transform yaml, and one of the methods for this is patchesStrategicMerge.
Where the strategic merge patch excels is in inserting elements and replacing values, allowing you to specify the desired patch using the same indentation level as the target, which makes the intended result very intuitive.
Although this patch type has support for replace, merge, and delete, I would recommend you use it primarily for merge which can replace existing values and add new elements. The syntax for other operations is clunky and documentation is thin. If you need delete and replace operations, consider a Json6902 patch instead.
Example project
All the source from this article can be found in my github project.
git clone https://github.com/fabianlee/kustomize-overlays-with-reload.git cd kustomize-overlays-with-reload root_dir=$(realpath .) cd $root_dir/base/simple-with-strategic-merge
The main file we will be manipulating is “deployment.yaml”, which is a very simple Kubernetes deployment using the hello-app image from Google.
apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment namespace: default labels: app: simple-deployment spec: selector: matchLabels: app: simple-deployment to_del: to_be_removed # will delete to_del_6902: to_be_removed # will delete tier: web # will change to 'api' template: metadata: labels: app: simple-deployment tier: web # will replace with to 'api' #foo: bar TO BE ADDED #key_added_6902 TO BE ADDED from op file #key_added_6902b TO BE ADDED from op file spec: # podAntiAffinity TO BE ADDED containers: - name: simple-app image: gcr.io/google-samples/hello-app:1.0 ports: - containerPort: 8080 env: - name: my_key # will replace with 'my_replaced_key' value: My value - name: key_todel # will delete value: will delete with patch # will add 'my_patched_key' resources: requests: cpu: 200m
The kustomize.yaml file is where the patches are specified, and you can preview the results using the built-in kustomize.
kubectl kustomize
Adding patches in kustomization.yaml
To add strategic merge patches, you can either place them under the ‘patchesStrategicMerge’ element, OR the ‘patches’ element where their type will be automatically sensed.
# could also use this keyword #patchesStrategicMerge: # but 'patches' keyword auto-senses patch types patches: # patches using local files - patch-selector.yaml - patch-labels.yaml # patches using inline definitions - |- apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment ...
The patch operations can be specified either in a separate local file or the definition can be inlined, but I won’t use the inline version in this article because in my opinion it negates one of the major benefits of this patch type which is being able to use the exact yaml indentation of the desired patch.
Strategic merge for Map/Dictionary
Referring back up to our deployment.yaml source, the spec.template.metadata.labels has two keys.
app: simple-deployment tier: web
Below is a strategic merge that changes ‘web’ to ‘api’, and then adds three more keys: ‘foo’, ‘key_added_6902’ and ‘key_added_6902b’.
apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment spec: template: metadata: labels: tier: api foo: bar key_added_6902: value1 key_added_6902b: value
Replace for Map/Dictionary
Referring back up to our deployment.yaml source, the spec.selector.matchLabels has four keys.
app: simple-deployment to_del: to_be_removed to_del_6902: to_be_removed tier: web
To change ‘web’ to ‘api’ and remove the two ‘to_del’ keys, we can use the replace operation (as opposed to the default merge behavior) which replaces all the matchLabels values with our newly specified ones.
apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment spec: selector: matchLabels: $patch: replace tier: api app: simple-deployment
Strategic Merge for Array
The spec.template.spec.containers[0].env contains two key/value pairs.
- name: my_key value: My value - name: key_todel value: will delete with patch
If you wanted to add another item to this array (‘my_new_key’).
apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment spec: template: spec: containers: - name: simple-app env: - name: my_new_key value: my new value
This would result in a total of 3 items in the array.
Replace for Array
If you wanted to:
- rename ‘my_key’ as ‘my_replaced_key’
- remove the ‘key_todel’
- add a new key ‘my_patched_key’
Then you would need to change the behavior to ‘$patch: replace’ instead of merge which would replace all the items in the env array with our own.
apiVersion: apps/v1 kind: Deployment metadata: name: simple-deployment spec: template: spec: containers: - name: simple-app env: - $patch: replace - name: my_replaced_key value: My new patched value - name: my_patched_key value: "true"
Summary
Strategic merge patches excel in their ability to insert elements and replace values, and their match of the target yaml indentation makes them very intuitive to understand as well as copy-paste.
If you feel the syntax is not expressive enough for the operation you are attempting, I would urge you to look at JSON6902 patches.
REFERENCES
kustomize docs, patchesStrategicMerge
kustomize, patch types supported
github sig, strategicMerge patch