Kustomize
Lab Overview
In this quick lab, you will learn the essentials of Kustomize by creating a base configuration and two environment overlays (dev and production).
Duration : 10-15 minutes
Prerequisites :
kubectl installed (with Kustomize support)
Basic understanding of Kubernetes resources
Exercise 1: Setup Base Configuration
Objective
Create a base configuration for a simple nginx application.
Tasks
Create the directory structure and base files:
mkdir -p myapp/base myapp/overlays/{ dev,production}
Create myapp/base/deployment.yaml:
apiVersion : apps/v1
kind : Deployment
metadata :
name : webapp
spec :
replicas : 2
selector :
matchLabels :
app : webapp
template :
metadata :
labels :
app : webapp
spec :
containers :
- name : nginx
image : nginx:1.21
ports :
- containerPort : 80
Create myapp/base/service.yaml:
apiVersion : v1
kind : Service
metadata :
name : webapp
spec :
selector :
app : webapp
ports :
- port : 80
targetPort : 80
Create myapp/base/kustomization.yaml:
apiVersion : kustomize.config.k8s.io/v1beta1
kind : Kustomization
resources :
- deployment.yaml
- service.yaml
Test your base configuration:
kubectl kustomize myapp/base/
Expected : You should see both Deployment and Service manifests output.
Exercise 2: Create Development Overlay
Objective
Customize the base for a development environment with reduced resources.
Tasks
Create myapp/overlays/dev/kustomization.yaml:
apiVersion : kustomize.config.k8s.io/v1beta1
kind : Kustomization
namePrefix : dev-
labels :
- includeSelectors : true
pairs :
environment : dev
resources :
- ../../base
replicas :
- name : webapp
count : 1
Build and observe the changes:
kubectl kustomize myapp/overlays/dev/
Question : What changed compared to the base?
Answer
Changes applied by the dev overlay:
✅ Resources are prefixed with dev- (dev-webapp)
✅ Replicas reduced from 2 to 1
✅ Label environment=dev added to all resources
✅ Service selector automatically updated to match new labels
Exercise 3: Create Production Overlay
Objective
Create a production overlay with increased replicas, updated image, and a ConfigMap.
Tasks
Create myapp/overlays/production/kustomization.yaml:
apiVersion : kustomize.config.k8s.io/v1beta1
kind : Kustomization
namePrefix : prod-
labels :
- includeSelectors : true
pairs :
environment : production
resources :
- ../../base
replicas :
- name : webapp
count : 5
images :
- name : nginx
newTag : "1.23"
configMapGenerator :
- name : webapp-config
literals :
- ENV=production
- LOG_LEVEL=info
Create overlays/production/resources-patch.yaml to add resource limits:
apiVersion : apps/v1
kind : Deployment
metadata :
name : webapp
spec :
template :
spec :
containers :
- name : nginx
resources :
limits :
cpu : 200m
memory : 256Mi
requests :
cpu : 100m
memory : 128Mi
Update overlays/production/kustomization.yaml to include the patch:
apiVersion : kustomize.config.k8s.io/v1beta1
kind : Kustomization
namePrefix : prod-
labels :
- includeSelectors : true
pairs :
environment : production
resources :
- ../../base
patches :
- path : resources-patch.yaml
replicas :
- name : webapp
count : 5
images :
- name : nginx
newTag : "1.23"
configMapGenerator :
- name : webapp-config
literals :
- ENV=production
- LOG_LEVEL=info
Build the production overlay:
kubectl kustomize myapp/overlays/production/
Question : What are all the differences between dev and production?
Answer
Development :
Prefix: dev-
Replicas: 1
Image: nginx:1.21 (from base)
No resource limits
No ConfigMap
Label: environment=dev
Production :
Prefix: prod-
Replicas: 5
Image: nginx:1.23 (upgraded)
Resource limits and requests defined
ConfigMap generated with hash suffix (e.g., webapp-config-abc123)
Label: environment=production
The ConfigMap hash suffix ensures immutability - any change in content creates a new ConfigMap, triggering pod updates.
Exercise 4: Compare and Deploy (Optional)
Objective
Compare both environments and optionally deploy them.
Tasks
Compare the two overlays side by side:
diff <( kubectl kustomize myapp/overlays/dev/) <( kubectl kustomize myapp/overlays/production/)
Optional - If you have a cluster, deploy both:
# Create dev namespace
USER= $( whoami)
kubectl create ns "dev- $USER"
# Deploy dev
kubectl apply -n "dev- $USER" -k myapp/overlays/dev/
# Deploy production to a separate namespace
kubectl create namespace "production- $USER"
kubectl apply -k myapp/overlays/production/ -n "production- $USER"
# Verify
kubectl get all -n "dev- $USER" -l environment= dev
kubectl get configmaps -n "e- $USER"
kubectl get all -n "production- $USER" -l environment= production
kubectl get configmaps -n "production- $USER"
# Clean up
kubectl delete -n "dev- $USER" -k myapp/overlays/dev/
kubectl delete -n "production- $USER" -k myapp/overlays/production/
kubectl delete namespace "production- $USER"
kubectl delete namespace "dev- $USER"
Key Takeaways
What you learned:
✅ Base + Overlays pattern : Common config in base, environment-specific in overlays
✅ Transformers : namePrefix, commonLabels, replicas, images
✅ Patches : Strategic merge patches for targeted modifications
✅ Generators : ConfigMaps with automatic hash suffixes
✅ No templates : Pure YAML manipulation, easy to understand
Kustomize workflow:
1. Create base with common resources
2. Create overlays for each environment
3. Use transformers for simple changes
4. Use patches for complex modifications
5. Build with: kubectl kustomize <overlay-path>/
6. Apply with: kubectl apply -k <overlay-path>/
When to use what:
Need
Use
Add prefix/suffix
namePrefix/nameSuffix
Add labels to all
commonLabels
Change replicas
replicas field
Update image tag
images field
Generate ConfigMap
configMapGenerator
Modify specific fields
patches
Quick Reference
# Build kustomization
kubectl kustomize <directory>
# Apply kustomization
kubectl apply -k <directory>
# Delete kustomization
kubectl delete -k <directory>
# Validate (dry-run)
kubectl apply -k <directory> --dry-run= client
# See only specific resource
kubectl kustomize <directory> | grep -A 20 "kind: Deployment"
Challenge (If Time Permits)
Try to add a staging overlay that:
Uses prefix staging-
Has 3 replicas
Uses nginx:1.22
Adds annotation: description: "Staging environment"
Answer
# Create overlays/staging/kustomization.yaml
cat <<EOF > myapp/overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: staging-
labels:
- includeSelectors: true
pairs:
environment: staging
commonAnnotations:
description: "Staging environment"
resources:
- ../../base
replicas:
- name: webapp
count: 3
images:
- name: nginx
newTag: "1.22"
EOF
# Build it
kubectl kustomize myapp/overlays/staging/
Resources