Customize an Application with Kustomize

KubernetesBeginner
Practice Now

Introduction

Helm packages Kubernetes templates as releases. Kustomize takes a different approach: it starts from ordinary Kubernetes YAML and layers changes on top without using template expressions. This is useful when you want a shared base and small environment-specific differences such as names, namespaces, replica counts, or patches.

In this lab, you will create a base Deployment and Service, render that base with Kustomize, then create a production overlay that changes the name, namespace, replica count, and application message. Finally, you will deploy the overlay with kubectl apply -k and test the resulting Service.

Prepare a Kustomize Workspace

In this step, you will prepare a namespace and confirm that Kustomize support is available through kubectl.

Start in /home/labex/project. This lab keeps the base manifests and overlay files in this workspace.

mkdir -p /home/labex/project
cd /home/labex/project

Check that the Kubernetes API server is reachable. If the VM has just started and the node is not ready yet, wait a few seconds and run the command again.

kubectl get nodes --request-timeout=5s

Expected output includes:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Wait until the cluster networking Pod is Ready. You will test a Service at the end of the lab, so cluster networking needs to be healthy.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Expected output:

pod/calico-node-... condition met

Create a namespace named ckad-prep-kustomize and set it as the current namespace:

kubectl create namespace ckad-prep-kustomize
kubectl config set-context --current --namespace=ckad-prep-kustomize

Confirm the namespace and check that kubectl kustomize is available. kubectl kustomize renders Kustomize directories without applying them.

kubectl config view --minify --output 'jsonpath={..namespace}'; echo
kubectl kustomize --help | sed -n '1,3p'

Expected output includes:

ckad-prep-kustomize
Build a set of KRM resources...

Create a Reusable Base

In this step, you will create a Kustomize base from ordinary Kubernetes YAML.

A base is the shared starting point. It should contain complete, valid Kubernetes objects before any environment-specific customization is added. Here the base contains one Deployment and one Service. The application writes the value of the MESSAGE environment variable into a small web page.

Create the base directory:

mkdir -p kustomize-demo/base

Write the base Deployment:

cat > kustomize-demo/base/deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kustomize-web
  labels:
    app: kustomize-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kustomize-web
  template:
    metadata:
      labels:
        app: kustomize-web
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: web
        image: busybox:1.36
        env:
        - name: MESSAGE
          value: base-v1
        command:
        - /bin/sh
        - -c
        - |
          mkdir -p /www
          echo "$MESSAGE" > /www/index.html
          httpd -f -p 8080 -h /www
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /
            port: 8080
          initialDelaySeconds: 1
          periodSeconds: 2
EOF

Write the base Service. Its selector matches the Pod label from the Deployment.

cat > kustomize-demo/base/service.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  name: kustomize-web
spec:
  selector:
    app: kustomize-web
  ports:
  - port: 80
    targetPort: 8080
EOF

Create the base kustomization.yaml. This file tells Kustomize which resources belong to the base.

cat > kustomize-demo/base/kustomization.yaml <<'EOF'
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
EOF

Render the base without applying it:

kubectl kustomize kustomize-demo/base | sed -n '1,120p'

Expected output includes a Service named kustomize-web, a Deployment named kustomize-web, replicas: 1, and value: base-v1.

Add a Production Overlay

In this step, you will create an overlay that customizes the base for a production-style deployment.

An overlay points to a base and then adds changes. This overlay will put the objects in ckad-prep-kustomize, add the prod- name prefix, scale the Deployment to three replicas, and patch the MESSAGE value to prod-v2.

Create the overlay directory:

mkdir -p kustomize-demo/overlays/prod

Write a Deployment patch. The patch names the original base object, kustomize-web. Kustomize matches the patch before it adds the prod- prefix.

cat > kustomize-demo/overlays/prod/deployment-patch.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kustomize-web
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: web
        env:
        - name: MESSAGE
          value: prod-v2
EOF

Create the overlay kustomization.yaml. The resources entry points back to the base, while namespace, namePrefix, and patches describe the customization.

cat > kustomize-demo/overlays/prod/kustomization.yaml <<'EOF'
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: ckad-prep-kustomize
namePrefix: prod-
resources:
- ../../base
patches:
- path: deployment-patch.yaml
EOF

Render the production overlay:

kubectl kustomize kustomize-demo/overlays/prod | sed -n '1,160p'

Expected output includes:

name: prod-kustomize-web
namespace: ckad-prep-kustomize
replicas: 3
value: prod-v2

Deploy and Test the Customized Application

In this step, you will apply the production overlay and test the Service it creates.

The command kubectl apply -k renders a Kustomize directory and sends the rendered objects to the Kubernetes API server. You do not need to create a temporary YAML file.

Apply the production overlay:

kubectl apply -k kustomize-demo/overlays/prod

Expected output includes:

service/prod-kustomize-web created
deployment.apps/prod-kustomize-web created

Wait for the customized Deployment:

kubectl rollout status deployment/prod-kustomize-web --timeout=120s

Expected output:

deployment "prod-kustomize-web" successfully rolled out

Inspect the objects created from the overlay:

kubectl get deployment,service prod-kustomize-web

Expected output includes:

deployment.apps/prod-kustomize-web   3/3
service/prod-kustomize-web

Create a client Pod and test the Service. The response should be prod-v2, which proves that the overlay patch changed the running application configuration.

kubectl run kustomize-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/kustomize-client --timeout=120s
kubectl exec kustomize-client -- wget -qO- http://prod-kustomize-web

Expected output:

prod-v2

Summary

You built a Kustomize base from ordinary Deployment and Service YAML, then created a production overlay that changed the namespace, object names, replica count, and application message. You rendered both the base and overlay before applying the overlay with kubectl apply -k, then verified the customized application through its Service.