Kustomize
Kustomize is a tool that allows for managing and customizing Kubernetes resource configuration files.
It is an extra layer that allows to simplify configuration by avoiding repeating code, and using the concepts of base and overlays to generate custom configurations while leaving the original YAML untouched and usable as is.
Usage
Kustomize works by defining a kustomization.yaml file. This file defines mainly two things:
- Which resources (k8 configs) should be managed by kustomize
- Which customizations need to be made
Once this is defined, one can call
kustomize build dir/ Which will print the modified configurations. This can be piped to apply in the cluster directly
kustomize build dir/ | kubectl apply -f -Alternatively,
kubectlships with kustomize built in (normally older version), and can be called withkubectl apply -k dir/to call customize and then deploy the result
Directory Structure
Kustomize can be used in many different ways. It can be used to manage a single folder of resources (e.g adding a common tag to all resources)
- dir | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blueIn here the kustomization file will look like:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# Customizations to be appliedFor more real scenarios, configuration can be split into directories, with the root kustomization.yaml including each directory.
- dir | folder
- kustomization.yaml | file-alt | red
- api | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- db | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blueIn here the root kustomization file will look like below, and the directory ones, like the one above:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/
- db/
# Customizations to be appliedFinally, Kustomize provides an organized ways of dealing with different enviroments with a base-overlays setup:
- base | folder
- kustomization.yaml | file-alt | red
- api | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- db | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- overlay | folder
- dev | folder
- kustomization.yaml | file-alt | red
- api | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- db | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- prod | folder
- kustomization.yaml | file-alt | red
- api | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blue
- db | folder
- kustomization.yaml | file-alt | red
- deployment.yaml | file-alt | blue
- service.yaml | file-alt | blueIn here the kustomization files will look like:
base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- api/
- db/prod(dev)/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base/
- api/
- db/
# Customizations to be appliedCustomizing configurations
Transformers
Transformers allow modification of all resources. These include things like:
- Attach labels
- Add annotations
- Add name prefix/suffix
- Add a namespace
These actions are done with common transformers:
commonLabels:
org: example # All resources under this k.yaml will have this label
commonAnnotations:
branch: master # All resources under this k.yaml will have this annotation
namePrefix: pre- # All resources under this k.yaml will have the name pre-<name>
nameSuffix: -dev # All resources under this k.yaml will have the name <name>-dev
namespace: lab # All resources under this k.yaml will have the namespace definedSimilarly, images transformers can be used to modify container images in all resources (that have one). Either the complete image can be replaced:
images:
- name: nginx
newName: haproxy
newTag: 2.4or just the tag
images:
- name: nginx
newTag: 2.4Patches
Patches also allow for customization, but enable a more “surgical” approach than transformers. This means that certain (not all) resources can be targeted.
Patches can be defined in-line or as separate files. They can also be specified either in:
- JSON 6902 format, defined by three values: Operation, Target (The patch target selects resources by group, version, kind, name, namespace, labelSelector and annotationSelector. ), Value (except if operation is remove)
- Using SMP (Strategic Merge Patch): Uses K8s configurations, which copy the target but only shows the fields that need change.
I find JSON6902 easier to read, so all my examples will be using that format
Available operations are:
# add: creates a new entry with a given value
- op: add
path: /some/new/path
value: value
# replace: replaces the value of the node with the new specified value
- op: replace
path: /some/existing/path
value: new value
# copy: copies the value specified in from to the destination path
- op: copy
from: /some/existing/path
path: /some/path
# move: moves the node specified in from to the destination path
- op: move
from: /some/existing/path
path: /some/existing/destination/path
# remove: delete's the node('s subtree)
- op: remove
path: /some/path
# test: check if the specified node has the specified value, if the value differs it will throw an error
- op: test
path: /some/path
value: "my-node-value"Examples
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
hello: oe
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-colorapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- target:
kind: Pod
name: simple-webapp-color
# Instead of inline, path can be used to point to a patch file
patch: |-
- op: add
path: /metadata/labels/goodbye
value: bye
- target:
kind: Pod
name: simple-webapp-color
# Instead of inline, path can be used to point to a patch file
patch: |-
- op: replace
path: /metadata/labels/hello
value: hi apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
hello: hi
goodbye: bye
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-colorapiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
- name: logger
image: loggerapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patches:
- target:
kind: Pod
name: simple-webapp-color
patch: |-
- op: remove
path: /spec/containers/1
- target:
kind: Pod
name: simple-webapp-color
patch: |-
- op: replace
path: /spec/containers/0/image
value: redis
- target:
kind: Pod
name: simple-webapp-color
# /- appends to the list
patch: |-
- op: add
path: /spec/containers/-
value:
name: lb
image: nginx apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: redis
- name: lb
image: nginxComponents
Kustomize enables the use of “reusable” blocks of configuration (resources + patches) to avoid copying code even further. These blocks are called components.
They are very useful for customizations that only certain overlays should have, and that can be turned on on demand (e.g features).
For example:
For this an extra folder is created:
- k8s/ | folder
- base/ | folder
- kustomization.yaml | file-alt | red
- api-depl.yaml | file-alt | blue
- components/ | folder
- caching/ | folder
- kustomization.yaml | file-alt | red
- deployment-patch.yaml | file-alt | green
- redis-depl.yaml | file-alt | blue
- db/ | folder
- kustomization.yaml | file-alt | red
- deployment-patch.yaml | file-alt | green
- postgres-depl.yaml | file-alt | blue
- overlays/ | folder
- dev/ | folder
- kustomization.yaml | file-alt | red
- premium/ | folder
- kustomization.yaml | file-alt | red
- standalone/ | folder
- kustomization.yaml | file-alt | redComponent kustomization.yaml files define Component objects instead of Kustomization. These objects have no resources. More info here
As the necessary deployments and patches are defined in components, the environment files can just call the components to include them:
overlays/premium/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base/
components:
- ../../components/
# Other Customizations to be applied