Kustomize configMapGenerator and secretGenerator
Published: 2026-04-18
configMapGenerator and secretGenerator create ConfigMaps and Secrets from files, literals, or env files. The key feature: by default they append a content hash to the name, triggering a rolling update whenever the content changes.
configMapGenerator basics
yaml# kustomization.yaml
configMapGenerator:
- name: vector-config
namespace: observability
files:
- vector.yaml=configs/vector.yaml
options:
labels:
app.kubernetes.io/component: vector
Generates a ConfigMap named vector-config-<hash>. Any Deployment referencing this ConfigMap will roll automatically when configs/vector.yaml changes — no manual annotations needed.
The vector.yaml=configs/vector.yaml syntax maps: the key inside the ConfigMap will be vector.yaml, loaded from configs/vector.yaml. Without the =, the filename is used as both key and source path.
Disabling the hash suffix
When the ConfigMap name is hardcoded in a Helm chart's values, the hash suffix breaks the reference. Disable it:
yamlconfigMapGenerator:
- name: grafana-dashboards
namespace: observability
options:
disableNameSuffixHash: true
files:
- dashboards/cluster-overview.json
- dashboards/apisix.json
- dashboards/nodes.json
With disableNameSuffixHash: true, the name stays grafana-dashboards. Grafana's sidecar finds it by label and loads dashboards dynamically.
secretGenerator
Same API but for Secrets:
yamlsecretGenerator:
- name: vector-tls
namespace: observability
files:
- tls.crt=certs/vector-tls.crt
- tls.key=certs/vector-tls.key
type: kubernetes.io/tls
options:
disableNameSuffixHash: true
For credentials from literals:
yamlsecretGenerator:
- name: app-db-credentials
namespace: dev
literals:
- username=appuser
- password=changeme
Don't put real secrets here. Use SealedSecrets or ExternalSecrets for sensitive values.
env file source
For multiple key=value pairs from a .env file:
yamlconfigMapGenerator:
- name: app-config
namespace: dev
envs:
- configs/app.env
Where configs/app.env:
LOG_LEVEL=info
METRICS_PORT=9090
FEATURE_FLAG_X=true
DB_HOST=postgres.dev.svc.cluster.local
Each line becomes a separate key in the ConfigMap. This is cleaner than a literals: list for many key-value pairs.
valuesFrom in HelmRelease
ConfigMaps generated by Kustomize can feed HelmRelease values:
yaml# HelmRelease
spec:
valuesFrom:
- kind: ConfigMap
name: vector-helm-values
valuesKey: values.yaml
yaml# kustomization.yaml
configMapGenerator:
- name: vector-helm-values
namespace: observability
options:
disableNameSuffixHash: true
files:
- values.yaml=helm-values/vector-values.yaml
Useful when the values file is large or changes frequently — avoids embedding the whole YAML inline in the HelmRelease manifest.
patches + generators together
Patches can reference the generated ConfigMap by original name (before hash). Kustomize rewrites it automatically:
yamlpatches:
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: vector
spec:
template:
spec:
volumes:
- name: config
configMap:
name: vector-config # rewritten to vector-config-<hash>
target:
kind: Deployment
name: vector
Kustomize rewrites ConfigMap name references across the entire output — Deployments, StatefulSets, Pods.
Multiple files, multiple generators
yamlconfigMapGenerator:
- name: prometheus-rules
namespace: monitoring
files:
- alerting-rules/k8s.yaml
- alerting-rules/apps.yaml
- alerting-rules/infra.yaml
options:
disableNameSuffixHash: true
annotations:
prometheus-operator: "true"
- name: grafana-provisioning
namespace: monitoring
files:
- provisioning/datasources.yaml
- provisioning/dashboards.yaml
options:
disableNameSuffixHash: true
Generating from multiple directories
You can't glob directories in Kustomize generators directly, but you can list files explicitly or use a separate kustomization:
yamlconfigMapGenerator:
- name: all-rules
namespace: monitoring
files:
- rules/node.yaml
- rules/kubernetes.yaml
- rules/applications.yaml
For a large number of files, manage them in a separate kustomization.yaml that builds the ConfigMap, then reference it from the parent.
Debugging
Check what Kustomize generates before applying:
bashkubectl kustomize . | grep -A 20 "kind: ConfigMap"
Check the hash suffix that was generated:
bashkubectl get configmap -n observability | grep vector-config
What can go wrong
Rolling update doesn't trigger after ConfigMap content changes.
If you use a manually named ConfigMap (not generated), Kubernetes won't detect the content change and won't restart pods. Switch to configMapGenerator with hash suffix, or add a checksum/config annotation on the Deployment.
Hash suffix breaks HelmRelease references.
If a HelmRelease valuesFrom references a ConfigMap by exact name, the hash suffix will break the reference after any content change. Use disableNameSuffixHash: true for ConfigMaps that must have stable names.
kustomize build fails with "duplicate configmap name".
Two generators produce a ConfigMap with the same base name in the same namespace. Rename one or use different namespace settings.
Summary
configMapGeneratorwith default settings appends a content hash to the name, automatically triggering pod rolling updates when config changessecretGeneratorworks the same way for Secrets — safer than committing plaintext and then sealing separately- Use
disableNameSuffixHash: trueonly for resources that must have stable names (e.g., referenced by a HelmReleasevaluesFrom) envs:source is handy for.envfiles that already exist in the repo;files:works for arbitrary config files likevector.yaml- Test locally:
kubectl kustomize . | grep -A 20 "kind: ConfigMap"to see the generated output before applying