SEANK.H.LIAO

kustomize targeting array items

how do you change the value of an array item with kustomize?

kustomize array items

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

strategic merge patch

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

replacements

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