Skip to main content

Kubernetes Kustomize: Kustomize Configuration Management Example

971 words·
Kubernetes Kustomize Kubectl
Kubernetes-Components - This article is part of a series.
Part 21: This Article

Overview
#

My Cluster
#

In this tutorial I’m using the following K3s Kubernetes cluster:

NAME      STATUS   ROLES                  AGE     VERSION        INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu1   Ready    control-plane,master   2d13h   v1.30.5+k3s1   192.168.30.10   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu2   Ready    worker                 2d13h   v1.30.5+k3s1   192.168.30.11   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu3   Ready    worker                 2d13h   v1.30.5+k3s1   192.168.30.12   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2
ubuntu4   Ready    worker                 2d13h   v1.30.5+k3s1   192.168.30.13   <none>        Ubuntu 24.04.1 LTS   6.8.0-45-generic   containerd://1.7.21-k3s2

Kustomize Summary
#

  • Kustomize is used for customizing configurations of Kubernetes resources / deployments.

  • Overlays are applied on top of a base configurations like Deployments, Services, ConfigMaps,…

  • It allows to manage different environments (dev, production, project1, project2,…) by applying these overlays to a base configuration.

  • Unlike tools like Helm, Kustomize doesn’t use templates. It works by merging YAML files.

  • Kustomize relies on directories to organize files. Each environment has its own folder with a kustomization.yaml file that lists the base files and any overlays or patches.

Main Kustomize Commands
#

# View merged manifests
kubectl kustomize /path/to/kustomization

# Apply the Kustomize configuration from the specified directory
kubectl apply -k /path/to/kustomization



Kustomize Example
#

Create Namespaces
#

# Create namespaces for the overlay deployments
kubectl create ns nginx-dev
kubectl create ns nginx-prod

Folder Structure
#

# Create the folder structure
mkdir -p nginx-example/{base,overlays/{dev,prod}}

The file and folder structure looks like this:

── nginx-example
   ├── base
   │   ├── base-configmap.yaml
   │   ├── base-deployment.yaml
   │   ├── base-service.yaml
   │   └── kustomization.yaml
   └── overlays
       ├── dev
       │   ├── configmap-patch.yaml
       │   └── kustomization.yaml
       └── prod
           ├── configmap-patch.yaml
           ├── deployment-patch.yaml
           └── kustomization.yaml

Base Manifests
#

Base Deployment
#

  • base/base-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine3.20
        volumeMounts:
          - name: nginx-html
            mountPath: /usr/share/nginx/html
      restartPolicy: Always
      volumes:
        - name: nginx-html
          configMap:
            name: nginx-html

Base ConfigMap
#

  • base/base-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-html
data:
  index.html: |
        Nginx Example

Base Service
#

  • base/base-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 8080 # Port within the cluster
    targetPort: 80 # Pod port
    nodePort: 30080 # External port
  type: NodePort

Base kustomization.yaml
#

  • base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
  name: nginx-example
commonLabels:
  app: nginx

resources:
- base-configmap.yaml
- base-deployment.yaml
- base-service.yaml
  • metadata This section is used in Kubernetes resources to store data that helps uniquely identify the object. It usually includes fields like name, namespace, labels.

  • commonLabels This section is used to define common labels that will be applied to all resources in this Kustomize configuration.

  • resources Lists the Kubernetes resources that should be managed by Kustomize. By default, Kustomize connects the resources in the order they appear and applies any overlays if they are specified.


Dev Overlay
#

Overlay kustomization.yaml
#

  • overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: nginx-dev  # Specify namespace for dev overlay
resources:
  - ../../base

patches:
  - path: configmap-patch.yaml
  - target:
      kind: Service
      name: nginx-service
    patch: |
      - op: replace
        path: /spec/ports/0/nodePort
        value: 30081
      - op: replace
        path: /spec/ports/0/port
        value: 8081      

namespace: nginx-dev
commonLabels:
  env: dev

Overlay ConfigMap Patch
#

  • overlays/dev/configmap-patch.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-html
data:
  index.html: |
        Nginx Dev

Production Overlay
#

Overlay kustomization.yaml
#

  • overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
namespace: nginx-prod  # Specify namespace for production overlay

patches:
  - path: configmap-patch.yaml
  - path: deployment-patch.yaml
  - target:
      kind: Service
      name: nginx-service
    patch: |
      - op: replace
        path: /spec/ports/0/nodePort
        value: 30082
      - op: replace
        path: /spec/ports/0/port
        value: 8082      

commonLabels:
  env: prod

Overlay ConfigMap Patch
#

  • overlays/prod/configmap-patch.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-html
data:
  index.html: |
        Nginx Production

Overlay Deployment Patch
#

- overlays/prod/deployment-patch.yaml`

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3  # More replicas for production
  template:
    metadata:
      labels:
        version: prod



Apply the Overlays
#

Verify the Merged Configuration
#

# Test the "prod" overlay configuration
kubectl kustomize overlays/prod/

# Shell output:
apiVersion: v1
data:
  index.html: |
    Nginx Production
kind: ConfigMap
metadata:
  labels:
    app: nginx
    env: prod
  name: nginx-html
  namespace: nginx-prod
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
    env: prod
  name: nginx-service
  namespace: nginx-prod
spec:
  ports:
  - nodePort: 30082
    port: 8082
    targetPort: 80
  selector:
    app: nginx
    env: prod
  type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
    env: prod
  name: nginx-deployment
  namespace: nginx-prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
      env: prod
  template:
    metadata:
      labels:
        app: nginx
        env: prod
        version: prod
    spec:
      containers:
      - image: nginx:alpine3.20
        name: nginx
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: nginx-html
      restartPolicy: Always
      volumes:
      - configMap:
          name: nginx-html
        name: nginx-html

Deploy the Overlays
#

# Apply the "dev" overlay
kubectl apply -k overlays/dev

# Apply the "prod" overlay
kubectl apply -k overlays/prod

Verify the Deployment
#

Verify the “dev” deployment:

# List all resources in "nginx-dev" namespace
kubectl get all -n nginx-dev

# Shell output:
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-565dbd744d-4r77v   1/1     Running   0          4s

NAME                    TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/nginx-service   NodePort   10.43.205.201   <none>        8081:30081/TCP   4s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   1/1     1            1           4s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-565dbd744d   1         1         1       4s

Verify the “prod” deployment:

# List all resources in "nginx-prod" namespace
kubectl get all -n nginx-prod

# Shell output:
NAME                                   READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-5fd55f9bc-k7lmq   1/1     Running   0          9s
pod/nginx-deployment-5fd55f9bc-lt8h6   1/1     Running   0          9s
pod/nginx-deployment-5fd55f9bc-mfl59   1/1     Running   0          9s

NAME                    TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/nginx-service   NodePort   10.43.100.80   <none>        8082:30082/TCP   9s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           9s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-5fd55f9bc   3         3         3       9s

Test the Overlay Deployments
#

Test the “dev” deployment

# Curl the "dev" overlay
curl 192.168.30.11:30081

# Shell output:
Nginx Dev

Test the “prod” deployment

# Curl the "dev" overlay
curl 192.168.30.11:30082

# Shell output:
Nginx Production

Delete the Overlay Deployments
#

# Delete the overlay deployments
kubectl delete -k overlays/dev
kubectl delete -k overlays/prod



Links #

# Documentation
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/

# Official Documentation
https://kustomize.io/
Kubernetes-Components - This article is part of a series.
Part 21: This Article