Kustomize is not only useful for applying overlays, patches, prefixes, suffixes, labels, and namespaces. It can also generate Kubernetes
ConfigMap objects directly from different sources of information.This is very useful when you want to keep configuration close to your overlay, but you do not want to manually write complete ConfigMap manifests every time. Instead of creating long YAML files by hand, you can define a configMapGenerator in kustomization.yaml and let Kustomize produce the final Kubernetes resources.
In this article, we will focus only on configMapGenerator. We will look at literals, files, env files, generated name hashes, per-generator options, and global generatorOptions.
secretGeneratorfollows a similar generator model, but Secrets have different security implications. I will cover that separately in another article.
In the examples below, I use the modern
labelsfield instead ofcommonLabels, because recent Kustomize versions warn thatcommonLabelsis deprecated.
Why ConfigMap Generators Are Useful
In a Kubernetes project, application configuration often comes from several places:
- Simple key-value settings, such as feature flags.
- Configuration files, such as
.properties,.json,.yaml, or JavaScript initialization scripts. - Environment-style files, such as
.env.local. - Environment-specific values that differ between
dev,staging, andprod.
You can write these ConfigMaps manually, but generators give you a cleaner workflow. Your source files remain normal files in your repository, and Kustomize converts them into Kubernetes resources during the build step.
For example, a JavaScript database initialization script can stay as a real .js file. Your editor can highlight it, format it, and validate it as JavaScript. Kustomize can then package the file into a ConfigMap when building the overlay.
Example Overlay Structure
Imagine the following structure:
k8s/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
└── overlays/
└── dev/
├── .env.local
├── db-init.js
└── kustomization.yaml
The dev overlay can include the base resources and generate additional environment-specific configuration:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
namePrefix: dev-
nameSuffix: -alpha
resources:
- ../../base
labels:
- pairs:
app.kubernetes.io/part-of: color-api
environment: dev
includeTemplates: true
includeSelectors: false
A few important details are already visible here:
resourcesincludes the shared base.namespaceassigns namespaced resources to thedevnamespace.namePrefixandnameSuffixmodify resource names.labelsapplies labels without using the deprecatedcommonLabelsfield.includeSelectors: falseavoids changing immutable selectors after resources already exist.includeTemplates: truealso applies the labels to pod templates, which is useful for workloads such as Deployments.
Generating a ConfigMap from Literal Values
The simplest generator source is literals. A literal is a key-value pair written directly in kustomization.yaml.
configMapGenerator:
- name: feature-flags-config
literals:
- USE_DB=true
- EXPOSE_METRICS=true
- ENABLE_NEW_UI=true
Now build the overlay:
kubectl kustomize k8s/overlays/dev
Or, if you use the standalone Kustomize binary:
kustomize build k8s/overlays/dev
Kustomize generates a ConfigMap similar to this:
apiVersion: v1
data:
ENABLE_NEW_UI: "true"
EXPOSE_METRICS: "true"
USE_DB: "true"
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/part-of: color-api
environment: dev
name: dev-feature-flags-config-alpha-7m2k9g5h8b
namespace: dev
The important part is the generated name:
dev-feature-flags-config-alpha-7m2k9g5h8b
This name is built from:
dev-fromnamePrefix.feature-flags-configfrom the generator name.-alphafromnameSuffix.- A content hash suffix generated by Kustomize.
The hash suffix changes when the generated content changes. For example, if you add another feature flag, Kustomize produces a new ConfigMap name.
That behavior is intentional. When a Deployment references the generated ConfigMap by its logical name, Kustomize rewrites the reference to the hashed generated name. When the ConfigMap data changes, the referenced name changes too, and that gives Kubernetes a new pod template specification to roll out.
Generating a ConfigMap from a File
Now let us create a JavaScript initialization script:
console.log("Initializing DB");
console.log("Performing some operations");
console.log("Successfully initialized");
Save it as:
k8s/overlays/dev/db-init.js
Then add another generator entry:
configMapGenerator:
- name: db-init-config
files:
- db-init.js
Kustomize will create a ConfigMap where the file name becomes the key and the file contents become the value:
apiVersion: v1
data:
db-init.js: |
console.log("Initializing DB");
console.log("Performing some operations");
console.log("Successfully initialized");
kind: ConfigMap
metadata:
name: dev-db-init-config-alpha-4kgfh9k8hb
namespace: dev
This is useful when your application expects a file to exist inside the container. You can mount the ConfigMap as a volume and expose db-init.js as a file.
Customizing the Key Name for a File
By default, the key is the file name. You can override it with this syntax:
configMapGenerator:
- name: db-init-config
files:
- init-script.js=db-init.js
The generated output then uses init-script.js as the key:
data:
init-script.js: |
console.log("Initializing DB");
console.log("Performing some operations");
console.log("Successfully initialized");
This gives you flexibility when the file name in your repository should be different from the file name that the application expects in the container.
A practical example is a MongoDB initialization script. You may want to keep the local file as db-init.js, but mount it inside a container under a more specific name such as init-script.js or 001-create-users.js.
Generating a ConfigMap from an Env File
Another useful option is envs. This tells Kustomize to parse a file that contains key-value pairs.
Create a local env file:
ENVIRONMENT=local
DB_HOST=http://localhost:27017
EXPOSE_METRICS=true
Save it as:
k8s/overlays/dev/.env.local
Then reference it with envs:
configMapGenerator:
- name: local-config
envs:
- .env.local
Kustomize creates one ConfigMap key per env file entry:
apiVersion: v1
data:
DB_HOST: http://localhost:27017
ENVIRONMENT: local
EXPOSE_METRICS: "true"
kind: ConfigMap
metadata:
name: dev-local-config-alpha-bm7h2g6t5f
namespace: dev
This is different from using files.
envs vs files
The difference between envs and files is one of the most important details to understand.
| Generator source | Input example | Result in ConfigMap |
|---|---|---|
literals | USE_DB=true | One key-value pair per literal |
files | db-init.js | One key using the file name, with the full file content as value |
files with custom key | init-script.js=db-init.js | One key using the custom key, with the full file content as value |
envs | .env.local | One key-value pair per line in the env file |
For example, this configuration:
configMapGenerator:
- name: local-config
files:
- .env.local
Does not parse the env file into separate keys. Instead, it creates one key named .env.local:
data:
.env.local: |
ENVIRONMENT=local
DB_HOST=http://localhost:27017
EXPOSE_METRICS=true
Use envs when you want each line to become a separate key. Use files when you want the whole file to be stored as one value.
Disabling the Name Suffix Hash Per Generator
By default, Kustomize adds a hash suffix to generated ConfigMaps. You can disable it for a specific generator entry:
configMapGenerator:
- name: feature-flags-config
literals:
- USE_DB=true
- EXPOSE_METRICS=true
options:
disableNameSuffixHash: true
The generated resource name becomes stable:
metadata:
name: dev-feature-flags-config-alpha
This can be useful when an external system expects a fixed object name, but it removes one of the strongest rollout benefits of Kustomize generators.
When the hash is enabled, changes in generated data change the generated name. When that name is referenced from a Deployment, the Deployment output changes too. With disableNameSuffixHash: true, the generated name remains the same, so a Deployment that references it may not get a new pod template automatically.
That matters especially for environment variables. If a Pod consumes a ConfigMap through environment variables, those values are read when the container starts. Changing the ConfigMap does not update already-running environment variables. You usually need a rollout restart or a pod replacement.
Disabling the Hash Globally with generatorOptions
You can also configure generator behavior globally with generatorOptions:
generatorOptions:
disableNameSuffixHash: true
This applies to all generated ConfigMaps in the same kustomization.yaml.
You can also add labels and annotations only to generated resources:
generatorOptions:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/component: generated-configuration
annotations:
generated-resource: "true"
This is different from the top-level labels field. Top-level labels can apply across all resources in the build. generatorOptions.labels only applies to resources produced by generators such as configMapGenerator.
Full ConfigMap Generator Example
Here is a complete dev overlay example:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
namePrefix: dev-
nameSuffix: -alpha
resources:
- ../../base
labels:
- pairs:
app.kubernetes.io/part-of: color-api
environment: dev
includeTemplates: true
includeSelectors: false
generatorOptions:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/component: generated-configuration
configMapGenerator:
- name: feature-flags-config
literals:
- USE_DB=true
- EXPOSE_METRICS=true
- ENABLE_NEW_UI=true
- name: db-init-config
files:
- init-script.js=db-init.js
- name: local-config
envs:
- .env.local
This single overlay generates three ConfigMaps:
feature-flags-configfrom literal key-value pairs.db-init-configfrom a JavaScript file.local-configfrom an env file.
Using a Generated ConfigMap in a Deployment
In your base Deployment, reference the generated ConfigMap by the generator name, without the hash:
apiVersion: apps/v1
kind: Deployment
metadata:
name: color-api
spec:
template:
spec:
containers:
- name: color-api
image: color-api:1.0.0
envFrom:
- configMapRef:
name: feature-flags-config
volumeMounts:
- name: db-init
mountPath: /docker-entrypoint-initdb.d
volumes:
- name: db-init
configMap:
name: db-init-config
You do not need to manually write the hash in the Deployment. Kustomize rewrites the reference in the final output.
For example, the rendered Deployment may contain:
envFrom:
- configMapRef:
name: dev-feature-flags-config-alpha-7m2k9g5h8b
volumes:
- name: db-init
configMap:
name: dev-db-init-config-alpha-4kgfh9k8hb
This is one of the best reasons to keep the hash enabled. The generated object name and the consuming workload stay in sync.
Applying the Overlay
To inspect the generated YAML without applying it:
kubectl kustomize k8s/overlays/dev
To apply the overlay:
kubectl apply -k k8s/overlays/dev
This is often the best workflow:
- Build locally with
kubectl kustomize. - Inspect the generated resources.
- Commit the overlay changes.
- Let your GitOps or CI/CD system apply the overlay.
Common Mistakes
Using files When You Wanted envs
If you want each key in .env.local to become a separate ConfigMap entry, use this:
envs:
- .env.local
Not this:
files:
- .env.local
The second version stores the complete file as one value.
Disabling the Hash Too Quickly
It can be tempting to disable the name suffix hash because stable names look cleaner. Be careful. The hash is useful because it makes configuration changes visible in generated resource names.
For workloads that consume generated ConfigMaps, that name change can help trigger a rollout.
Forgetting That Env Vars Do Not Update in Running Containers
If a container reads a ConfigMap as environment variables, the values are loaded when the container starts. Updating the ConfigMap does not magically update the process environment inside an already-running container.
Mounted volumes behave differently: Kubernetes can eventually update projected ConfigMap volumes, although applications still need to reload the files if they cache the values.
Using ConfigMaps for Sensitive Data
ConfigMaps are for non-sensitive configuration. Do not store passwords, tokens, private keys, or certificates in a ConfigMap. Those belong in Kubernetes Secrets or an external secret-management system.
Best Practices
- Use
literalsfor small, simple key-value pairs. - Use
filesfor scripts, configuration files, and structured content. - Use
envsfor env-style files where each line should become an individual key. - Keep the hash suffix enabled unless you have a strong reason to disable it.
- Use
generatorOptionsfor labels and annotations that should apply only to generated resources. - Use top-level
labelsfor labels that should apply across the full rendered output. - Avoid
commonLabelsin modern Kustomize examples. - Do not put sensitive values in ConfigMaps.
- Inspect generated YAML with
kubectl kustomizebefore applying it.
Conclusion
configMapGenerator is a very practical way to create ConfigMaps from real configuration sources. It lets you keep scripts as scripts, env files as env files, and simple feature flags as readable key-value pairs.
The most important distinction is how each source type is processed. literals create direct key-value pairs. files embed entire files. envs parse env-style files into separate keys.
The hash suffix is also important. It may look like random noise at first, but it helps Kustomize connect configuration changes to new Kubernetes object names and workload updates. Disable it only when you fully understand the rollout consequences.
Used carefully, configMapGenerator and generatorOptions make environment-specific Kubernetes configuration cleaner, more maintainable, and easier to reason about.
References
- Kubernetes: Declarative Management of Kubernetes Objects Using Kustomize - kubernetes[.]io/docs/tasks/manage-kubernetes-objects/kustomization/
- Kubernetes: ConfigMaps - kubernetes[.]io/docs/concepts/configuration/configmap/
- Kubernetes: Configure a Pod to Use a ConfigMap - kubernetes[.]io/docs/tasks/configure-pod-container/configure-pod-configmap/
- Kustomize: Kubernetes native configuration management - kustomize[.]io/
- Kustomize: Generator Options - github[.]com/kubernetes-sigs/kustomize/blob/master/examples/generatorOptions.md
- Kustomize: commonLabels deprecation warning discussion - github[.]com/kubernetes-sigs/kustomize/issues/5653