How to modify lists with Kustomize?

Kustomize is a really useful tool to customize Kubernetes deployment files without modifying the original source.

This is a good pratice to use customization instead of modifying the original source files:

  • all customizations are described at the same place, like specifications of your customizations
  • it’s easier to peform updates

This can also be used to apply different configurations per environment. I will probably write a post to present Kustomize but this is not the purpose of this article.

In this blogpost I will simply illustrate how to create, modify and remove lists using Kustomize.

Let’s imaging we have the below deployment setup.yaml YAML file (it’s a part of the Fluent operator deployment file).

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: operator
    app.kubernetes.io/name: fluent-operator
  name: fluent-operator
  namespace: fluent
spec:
  selector:
    matchLabels:
      app.kubernetes.io/component: operator
      app.kubernetes.io/name: fluent-operator
  template:
    spec:
      initContainers:
      - command:
        - /bin/sh
        - -c
        - set -ex; echo CONTAINER_ROOT_DIR=$(docker info -f '{{.DockerRootDir}}' 2>
          /dev/null) > /fluent-operator/fluent-bit.env
        image: docker:19.03
        name: setenv
        volumeMounts:
        - mountPath: /fluent-operator
          name: env
        - mountPath: /var/run/docker.sock
          name: dockersock
          readOnly: true
      serviceAccountName: fluent-operator
      volumes:
      - emptyDir: {}
        name: env
      - hostPath:
          path: /var/run/docker.sock
        name: dockersock

How to remove an entire list

Let’s imagine we want to remove all the volumes, the below part:

      volumes:
      - emptyDir: {}
        name: env
      - hostPath:
          path: /var/run/docker.sock
        name: dockersock

To do so, we have to create a kustomization.yaml file with the below patch:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- setup.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: fluent-operator
  patch: |-
     - op: remove
       path: /spec/template/spec/volumes

The result will be:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: operator
    app.kubernetes.io/name: fluent-operator
  name: fluent-operator
  namespace: fluent
spec:
  selector:
    matchLabels:
      app.kubernetes.io/component: operator
      app.kubernetes.io/name: fluent-operator
  template:
    spec:
      initContainers:
      - command:
        - /bin/sh
        - -c
        - set -ex; echo CONTAINER_ROOT_DIR=$(docker info -f '{{.DockerRootDir}}' 2>
          /dev/null) > /fluent-operator/fluent-bit.env
        image: docker:19.03
        name: setenv
        volumeMounts:
        - mountPath: /fluent-operator
          name: env
        - mountPath: /var/run/docker.sock
          name: dockersock
          readOnly: true
      serviceAccountName: fluent-operator

How to create a list

Now let’s imagine we want to re-create the volumes list and add a new volume as below

      volumes:
      - emptyDir: {}
        name: env

The below kustomization will be used:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- setup.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: fluent-operator
  patch: |-
     - op: remove
       path: /spec/template/spec/volumes
     - op: add
       path: /spec/template/spec/volumes
       value: [{ "emptyDir": {}, "name":"env" }]

How to remove only one element of the list, with its index

We have also the possibility to remove an element of a list, with its index.

For example, from the below list.

      volumes:
      - emptyDir: {}
        name: env
      - hostPath:
          path: /var/run/docker.sock
        name: dockersock

To remove the second element, we have to apply to the below patch.

  patch: |-
     - op: remove
       path: /spec/template/spec/volumes/1

And the result would be:

      volumes:
      - emptyDir: {}
        name: env