Generators
Clone the Repository
To try out the examples in the succeeding sections, clone the project repository from GitHub.
- Github repo: joseeden/labs-kustomize
Clone the repository:
git clone https://github.com/joseeden/labs-kustomize.git
You will need a Kubernetes cluster to try out the examples.
To setup a basic cluster, you can use k3d.
Before Generators
In Kubernetes, updating a ConfigMap or Secret won’t automatically update a running pod.
To test it out, we'll set up a simple deployment that uses a ConfigMap for a database password. Later, we'll update the ConfigMap and see that the app doesn't reflect the change unless we manually restart it.
Start by navigating to the directory:
cd labs-kustomize/code-samples/05-before-generators
You'll find two manifest files:
-
configmap.yaml defines a ConfigMap with a password:
apiVersion: v1kind: ConfigMapmetadata:name: db-credentialsdata:password: password1 -
deployment.yaml references that ConfigMap as an environment variable:
apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-deploymentspec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxenv:- name: DB_PASSWORDvalueFrom:configMapKeyRef:name: db-credentialskey: password
The container reads DB_PASSWORD from the ConfigMap, but this value won't automatically change if the ConfigMap is updated later.
Apply the manifests:
kubectl apply -f .
Verify that everything is running:
kubectl get all
Output:
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-6cc58477b8-blz8d 1/1 Running 0 101s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 1/1 1 1 101s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-6cc58477b8 1 1 1 101s
You should see a running pod under the nginx-deployment. Now check that the environment variable was picked up correctly:
kubectl exec nginx-deployment-6cc58477b8-blz8d -- printenv | grep DB
You’ll get:
DB_PASSWORD=password1
Now, simulate a password update. Edit configmap.yaml to change the password to:
data:
password: password2
Apply the change:
kubectl apply -f configmap.yaml
Notice that the pod is still the same pod seen previously:
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE
nginx-deployment-6cc58477b8-blz8d 1/1 Running 0 101s
Check the pod again:
kubectl exec nginx-deployment-6cc58477b8-blz8d -- printenv | grep DB
You’ll still see:
DB_PASSWORD=password1
Even though the ConfigMap has changed, the running pod still uses the old value. That’s because Kubernetes doesn't restart pods when a referenced ConfigMap or Secret changes.
To see the update take effect, manually restart the deployment:
kubectl rollout restart deployment nginx-deployment
A new pod should now replace the old NGINX pod:
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE
nginx-deployment-6cc58477b8-mblwh 1/1 Running 0 101s
Then re-check the new pod:
kubectl exec nginx-deployment-6cc58477b8-mblwh -- printenv | grep DB
This time you’ll see:
DB_PASSWORD=password2
This example shows a core problem:
ConfigMap updates do not trigger pod restarts automatically.
This is where Kustomize generators come in. They help automate restarts by generating new resource names whenever content changes.
Enter Generators
Generators are used to create new Kubernetes resources automatically.
- Used to create config maps and secrets
- Can be written inline or defined in a YAML file
- Support advanced settings like behavior and naming
Kustomize mainly uses two types of generators:
- ConfigMapGenerator creates one or more ConfigMaps
- SecretGenerator creates Kubernetes Secrets
Defining Generators/Transformers
Generators are defined just like transformers. You can set them up in a few simple ways:
- Use a separate configuration file
- Write them as inline YAML
- Use convenience fields provided by Kustomize
You can use all three of these methods when setting up generators too.
For more information, please see Defining Transformers/Generators.
Common Generators
ConfigMap Generators
ConfigMap generators help automate config updates by generating unique names. This ensures Kubernetes detects changes and restarts pods automatically.
- Generator name stays the same, but output name gets a random suffix
- Any change in values or files creates a new ConfigMap
- New ConfigMap name is used in the deployment automatically
- Pods are redeployed without running
kubectl rollout restart
Here’s a simple config map generator:
configMapGenerator:
- name: app-config
behavior: create
files:
- app.properties
literals:
- mode=dev
This will create a ConfigMap named app-config with values from both file and literal inputs.
namesets the name of the generated config mapbehaviordefines how to treat existing config mapsfilesandliteralsallow data to come from files or inline
You can also generate multiple ConfigMaps:
configMapGenerator:
- name: app-config
behavior: create
files:
- app.properties
literals:
- mode=dev
- name: test-config
behavior: create
files:
- name: dev-config
behavior: create
literals:
To see it in action, please see the labs section below.
Secret Generators
Secrets are generated similarly, but values must be base64 encoded:
secretGenerator:
- name: app-secret
literals:
- token=abcd1234
Running kustomize build . will produce something like:
apiVersion: v1
kind: Secret
metadata:
name: app-secret-hg8f9234
data:
token: YWJjZDEyMzQ= # base64 encoded
Whether you're using literals or files, any change triggers a new name and automatic deployment update. This ensures your pods always pick up the latest configs or secrets without needing extra commands.
To see it in action, please see the labs section below.
Behavior Field
The behavior field controls what happens if the config map already exists.
createmakes a new onemergeadds new values to existingreplacefully replaces any existing version
Use this to manage how your customizations affect the base configuration.
Generator Options
You can use generatorOptions in your kustomization.yaml to control generator behavior globally.
generatorOptions:
disableNameSuffixHash: true
labels:
env: dev
annotations:
owner: ops-team
This will:
- Disables random suffix added to generated resources
- Applies the same labels and annotations to all generated items
These settings help ensure consistent metadata and stable resource names.
Labs
Lab 1: Simple ConfigMap
To try it out, go to the appropriate lab directory inside the repo:
cd labs-kustomize/code-sample/06-generators-configmaps/lab_01_simple_configmap
We have a generator defined in the kustomization.yaml:
namespace: test-labs-1
configMapGenerator:
- name: db-cred
literals:
- password=secret123
Before anything else, create the namespace first:
kubectl create ns test-labs-1
Then run:
kustomize build .
The output will look like:
apiVersion: v1
kind: ConfigMap
data:
password: secret123
metadata:
name: db-cred-h9286b2f78
namespace: test-labs-1
Notice the h9286b2f78 part is randomly generated.
After applying the config:
kubectl apply -k .
You can confirm the ConfigMap was created with the random suffix:
kubectl get cm -n test-labs-2
Example output:
NAME DATA AGE
db-cred-h9286b2f78 1 44s
kube-root-ca.crt 1 4m8s
If you change the value in the generator (kustomization.yaml), a new ConfigMap is created with a different name, and Kustomize automatically updates the deployment to reference the new ConfigMap. This triggers a pod restart without any manual intervention.
Update the password in the kustomization.yaml:
namespace: test-labs-2
configMapGenerator:
- name: db-cred
literals:
- password=secret123456789
Then re-apply:
kubectl apply -k .
When you check the resources again, you will now see two ConfigMaps created, each with a different randomly generated hash suffix:
kubectl get cm -n test-labs-2
Example output:
NAME DATA AGE
db-cred-h9286b2f78 1 3m
db-cred-ttcgtm58fb 1 2s
kube-root-ca.crt 1 6m24s
Lab 2: ConfigMap from a File
This lab shows how to generate a ConfigMap from a file using Kustomize.
Change to the lab directory:
cd labs-kustomize/code-sample/06-generators-configmaps/lab_02_configmap_from_file
Inside this directory, we have the following files:
*kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: test-labs-2
commonLabels:
version: lec-12
namePrefix: lec-12-
configMapGenerator:
- name: nginx-config
files:
- nginx.conf
resources:
- nginx-deployment.yml
nginx.conf
events {
worker_connections 1024;
}
http {
server {
listen 80;
listen [::]:80;
server_name localhost;
root /usr/share/nginx/html;
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
location /google {
proxy_pass http://www.google.com/search;
}
location / {
try_files $uri $uri/ =404;
}
}
}
nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: test-labs-2
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23.3-alpine-slim
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/nginx.conf
name: nginx-config
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf
The generator creates a ConfigMap where the filename is the key, and the content is the value.
Create the namespace first:
kubectl create ns test-labs-2
Apply the changes:
kubectl apply -k .
Verify the deployment:
$ kubectl get all -n test-labs-2
NAME READY STATUS RESTARTS AGE
pod/nginx-deployment-8667b86845-2dq2z 1/1 Running 0 59s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx-deployment 1/1 1 1 59s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-deployment-8667b86845 1 1 1 59s
Check that the ConfigMap was created:
$ kubectl get cm -n test-labs-2
NAME DATA AGE
kube-root-ca.crt 1 20m
nginx-config-48gchkg456 1 5s
You can also verify the contents of the ConfigMap by running the describe command:
kubectl describe cm nginx-config-48gchkg456 -n test-labs-2
Just like with ConfigMaps, you can generate Secrets using secretGenerator. It works the same way, but values are base64-encoded and a random suffix is also added.
To verify that the configuration actually work, we can do port-fowarding:
kubectl port-forward -n test-labs-2 deploy/nginx-deployment 31000:80
It should return:
Forwarding from 127.0.0.1:31000 -> 80
Forwarding from [::1]:31000 -> 80
Open a browser and navigate to http://localhost:31000/:
Lab 3: ConfigMap with File and Literal
We can also create a ConfigMap using a mix of file and literal values.
Change to the lab directory:
cd labs-kustomize/code-sample/06-generators-configmaps/lab_03_configmap_from_file_and_literal
Inside the directory:
-
kustomization.yaml
namespace: test-labs-3configMapGenerator:- name: app-configbehavior: createfiles:- app.propertiesliterals:- mode=dev -
app.properties
host=example.comport=8080
Create the namespace:
kubectl create ns test-labs-3
Apply the configuration:
kubectl apply -k .
Check the ConfigMap:
kubectl get cm -n test-labs-3
You’ll see a name like this, with a hash suffix added automatically:
NAME DATA AGE
app-config-h4mftk9kcc 2 3s
kube-root-ca.crt 1 14s
Verify that the ConfigMap used both the file and the literal:
kubectl describe cm app-config-h4mftk9kcc -n test-labs-3
Output:
Name: app-config-h4mftk9kcc
Namespace: test-labs-3
Labels: <none>
Annotations: <none>
Data
====
app.properties:
----
host=example.com
port=8080
mode:
----
dev
BinaryData
====
Events: <none>