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

  • configMapGenerator with default settings appends a content hash to the name, automatically triggering pod rolling updates when config changes
  • secretGenerator works the same way for Secrets — safer than committing plaintext and then sealing separately
  • Use disableNameSuffixHash: true only for resources that must have stable names (e.g., referenced by a HelmRelease valuesFrom)
  • envs: source is handy for .env files that already exist in the repo; files: works for arbitrary config files like vector.yaml
  • Test locally: kubectl kustomize . | grep -A 20 "kind: ConfigMap" to see the generated output before applying