Kubernetes resources use quite a few lists/arrays in defining things. This leads to the question of how do you update the value of array items, especially if the order of items isn't stable?
Say we have the following manifest, and we want to change FIZZ=buzz
to FIZZ=FUZZ
in both deployments:
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: example-deploy
5spec:
6 selectors:
7 matchLabels:
8 foo: bar
9 template:
10 metdata:
11 labels:
12 foo: bar
13 spec:
14 containers:
15 - name: example-container
16 env:
17 - name: FIZZ
18 value: buzz
19 - name: HELLO
20 value: world
21---
22apiVersion: apps/v1
23kind: Deployment
24metadata:
25 name: example-deploy-2
26spec:
27 selectors:
28 matchLabels:
29 foo: bar
30 template:
31 metdata:
32 labels:
33 foo: bar
34 spec:
35 containers:
36 - name: with-sidecar
37 - name: example-container
38 env:
39 - name: HELLO
40 value: world
41 - name: FIZZ
42 value: buzz
One option is to use a
strategic merge patch.
This uses extra data from the openapi definitions of resources
to know that certain elements should be matched using certain keys.
In this case, both the containers
list and env
list match using name
.
Usually, a strategic merge patch is only applied on resources matching metadata.name
,
but kustomize has extended that to allow targeting on
group
, version
, kind
, name
, namespace
, labelSelector
and annotationSelector
with regexes.
1apiVersion: kustomize.config.k8s.io/v1beta1
2kind: Kustomization
3resources:
4 - original.yaml
5patches:
6 - patch: |
7 apiVersion: apps/v1
8 kind: Deployment
9 metadata:
10 name: placeholder
11 spec:
12 template:
13 spec:
14 containers:
15 - name: example-container
16 env:
17 - name: FIZZ
18 value: FUZZ
19 target:
20 kind: Deployment
The other option makes use of replacements. This gives you more explicit control over how array items are targeted, but I havent thought of a good way to feed structured data in to it.
This example creates a temporary config map to hold that data that we later reference.
The config.kubernetes.io/local-config: "true"
annotation
tells kustomize
not to include it in the final output.
Then we define a replacement, sourcing data from the configmap we just created,
and targeting resources with the [key=value]
item key selector.
1apiVersion: kustomize.config.k8s.io/v1beta1
2kind: Kustomization
3resources:
4 - original.yaml
5configMapGenerator:
6 - name: data-source
7 options:
8 disableNameSuffixHash: true
9 annotations:
10 config.kubernetes.io/local-config: "true"
11 literals:
12 - new-value=FUZZ
13replacements:
14 - source:
15 name: data-source
16 fieldPath: data.new-value
17 targets:
18 - select:
19 kind: Deployment
20 fieldPaths:
21 - spec.template.spec.containers.[name=example-container].env.[name=FIZZ].value