Introduction to Kustomize - How to customize Kubernetes objects
Tags: kubernetes, kustomize, devops, yaml
Published: 2021-07-08 19:00:49

## What is Kustomize?

Kustomize is a tool used to customize Kubernetes objects in a template-free way. It provides several features that allow us to customize the application’s configuration.

We can use Kustomize in two ways: use the standalone version of Kustomize or use kubectl. Kustomize is a part of Kubectl since version 1.14.

Kustomize is easy to learn and use because the customization file is the same as the Kubernetes manifest. It is very handy when you work with Kubernetes. That makes the learning curve low.

One advantage of Kustomize is that it uses a kustomization.yaml file to customize Kubernetes manifests. That avoid us editing directly the manifests. So we can use the original manifests without needing Kustomize.

We will see above, the main features of Kustomize.

## Features

### 1. secretGenerator and configMapGenerator
With Kustomize, we can generate secrets and configMaps from literals or files and rolling out changes. This is possible through the use of secretGenerator and configMapGenerator.

####Example : Using Kustomize to generate Kubernetes secret to store tls certificate and key file.
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
 - namespace.yaml

secretGenerator:
- name: my-tls
 files:
 - cert/tls.cert
 - cert/tls.key
 type: "kubernetes.io/tls"
 namespace: my-app
```
#### Example: Using Kustomize to generate Kubernetes secret to store database password.

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

secretGenerator:
- name: database-password
 literals:
   - password=pass
```
For secretGenerator, as we see, we can specify the namespace where we want to store the secrets. We can also specify the type of secret and add labels and annotations.

#### Example : Generate a configMap YAML:
```
# config-file.cnf
character-set-server=utf8mb4
```
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: database-config-file
  files:
  - config-file.cnf
```
### 2. Container image
Kustomize allows us to override container's name and version. We can specify a tag or a digest for container's version. 
```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  template:
    spec:
      containers:
      - name: app-one
        image: app-one:latest
      - name: app-two
        image: app-two:latest
      - name: app-three
        image: app-three:latest
``` 
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

images:
- name: app-one
  newName: main-application
- name: app-two
  newTag: 1.0.1
- name: app-three
  digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3

resources:
- deployment.yaml
```
### 3. Namespaces and names
We can use Kustomize, to set for all resources within a project or for a group of resources, namespace, name prefix, or name suffix.

If a namespace is already set, Kustomize will override it.

#### Example: Set namespace with Kustomize
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: backend-services
resources:
- deployment.yaml
```

#### Example: Prepends the value to the names of all resources and references.
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namePrefix: staging-

resources:
- deployment.yaml
```

#### Example : Appends the value to the names of all resources and references
```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

nameSuffix: -beta

resources:
- deployment.yaml
```

### 4. Set labels and annotations
We can use Kustomize to set labels and annotations for a group of resources. To do that, use commonLabels and commonAnnotations.

```yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  environment: staging
commonAnnotations:
  imageregistry: "https://hub.docker.com/"
resources:
- deployment.yaml
```

### 5. Bases
When we use Kustomize, we need a directory, called the base. In this directory, we put a set of resources and a kustomization.yaml file.

To avoid rewriting the base content and to enable reusability, the base content can be versioned in a remote repository. Make sure there is a kustomization file inside the repository.

```yaml
# kustomization.yaml
bases:
# GitHub URL
- github.com/example/kustomize/bases/staging/?ref=v1.1.1
```

### 7. Overlays
An overlay is a directory with a kustomization.yaml that refers to one or multiple bases directory.

### 8. Inline patches

Kustomize uses patches to introduce environment specific changes on an already existing standard config file without disturbing it.

There are 3 ways for patching a kustomization file :
* Strategic Merge patch
```yaml
# kustomization.yaml
patchesStrategicMerge:
- |-
  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: deploy
  spec:
    template:
      spec:
        containers:
        - name: nginx
          image: nginx:1.20.0-alpine
        - $patch: replace
```
* Json patch
```yaml
# kustomization.yaml
patchesJSON6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: deploy
  patch: |-
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: nginx:1.20.0-alpine
```
* A list of patches

## Conclusion
There are many ways to customize Kubernetes objects, and the purpose of this post is to introduce Kustomize and show how to customize Kubernetes objects with kustomization files.