Kustomize Generators
Master ConfigMap and Secret generation using Kustomize generators for managing application configuration, credentials, and environment-specific settings without manual YAML creation.
Overview
Kustomize generators automatically create ConfigMaps and Secrets from literals, files, and environment files. Generated resources include content hashes in their names, enabling automatic rollouts when configuration changes.
ConfigMap Generator Basics
Literal Values
kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization
configMapGenerator:
- name: app-config
literals:
- DATABASE_URL=postgresql://localhost:5432/mydb
- LOG_LEVEL=info
- CACHE_ENABLED=true
- MAX_CONNECTIONS=100
- TIMEOUT_SECONDS=30
Generated ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: app-config-8g2h5m9k7t data: DATABASE_URL: postgresql://localhost:5432/mydb LOG_LEVEL: info CACHE_ENABLED: "true" MAX_CONNECTIONS: "100" TIMEOUT_SECONDS: "30"
File-Based Generation
kustomization.yaml
configMapGenerator:
- name: app-config
files:
- application.properties
- config/database.conf
- config/logging.yml
With files:
application.properties
server.port=8080 server.host=0.0.0.0 app.name=MyApplication app.version=1.0.0
config/database.conf
max_connections = 100 shared_buffers = 256MB effective_cache_size = 1GB
config/logging.yml
level: info format: json outputs:
- stdout
- file: /var/log/app.log
Named Files
configMapGenerator:
- name: app-config
files:
- config.properties=application.properties
- db.conf=config/database.conf
- log.yml=config/logging.yml
Generated ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: app-config-9m4k8h2f6d data: config.properties: | server.port=8080 server.host=0.0.0.0 app.name=MyApplication app.version=1.0.0 db.conf: | max_connections = 100 shared_buffers = 256MB effective_cache_size = 1GB log.yml: | level: info format: json outputs: - stdout - file: /var/log/app.log
Environment Files
configMapGenerator:
- name: app-config
envs:
- .env
- config/.env.production
With files:
.env
DATABASE_URL=postgresql://localhost:5432/mydb REDIS_URL=redis://localhost:6379 LOG_LEVEL=info
config/.env.production
DATABASE_URL=postgresql://prod-db:5432/mydb REDIS_URL=redis://prod-redis:6379 LOG_LEVEL=warn MONITORING_ENABLED=true
Mixed Sources
configMapGenerator:
- name: app-config
literals:
- APP_NAME=MyApp
- APP_VERSION=1.0.0 files:
- application.properties envs:
- .env
Secret Generator Basics
Literal Values
secretGenerator:
- name: app-secrets
type: Opaque
literals:
- database-password=super-secret-password
- api-key=1234567890abcdef
- jwt-secret=my-jwt-secret-key
Generated Secret:
apiVersion: v1 kind: Secret metadata: name: app-secrets-2f6h8k9m4t type: Opaque data: database-password: c3VwZXItc2VjcmV0LXBhc3N3b3Jk api-key: MTIzNDU2Nzg5MGFiY2RlZg== jwt-secret: bXktand0LXNlY3JldC1rZXk=
File-Based Secrets
secretGenerator:
- name: tls-secret
type: kubernetes.io/tls
files:
- tls.crt=certs/server.crt
- tls.key=certs/server.key
Docker Registry Secret
secretGenerator:
- name: docker-registry
type: kubernetes.io/dockerconfigjson
files:
- .dockerconfigjson=docker-config.json
With docker-config.json:
{ "auths": { "registry.example.com": { "username": "myuser", "password": "mypassword", "email": "myemail@example.com", "auth": "bXl1c2VyOm15cGFzc3dvcmQ=" } } }
SSH Key Secret
secretGenerator:
- name: ssh-keys
type: Opaque
files:
- id_rsa=keys/id_rsa
- id_rsa.pub=keys/id_rsa.pub
Generator Behaviors
Create Behavior (Default)
configMapGenerator:
- name: app-config
behavior: create
literals:
- KEY=value
Creates a new ConfigMap. Fails if one already exists.
Replace Behavior
configMapGenerator:
- name: app-config
behavior: replace
literals:
- KEY=new-value
Replaces existing ConfigMap entirely. Fails if it doesn't exist.
Merge Behavior
base/kustomization.yaml
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
- CACHE_ENABLED=true
- DATABASE_URL=localhost
overlays/production/kustomization.yaml
configMapGenerator:
- name: app-config
behavior: merge
literals:
- LOG_LEVEL=warn
- DATABASE_URL=prod-db.example.com
Resulting ConfigMap merges values:
data: LOG_LEVEL: warn # Overridden CACHE_ENABLED: "true" # From base DATABASE_URL: prod-db.example.com # Overridden
Advanced Generator Patterns
Multi-Environment Configuration
base/kustomization.yaml
configMapGenerator:
- name: app-config
literals:
- APP_NAME=MyApp
- CACHE_ENABLED=true
- TIMEOUT=30 files:
- application.properties
overlays/development/kustomization.yaml
configMapGenerator:
- name: app-config
behavior: merge
literals:
- LOG_LEVEL=debug
- DEBUG_MODE=true
- DATABASE_URL=postgresql://dev-db:5432/mydb
overlays/production/kustomization.yaml
configMapGenerator:
- name: app-config
behavior: merge
literals:
- LOG_LEVEL=error
- DEBUG_MODE=false
- DATABASE_URL=postgresql://prod-db:5432/mydb
- RATE_LIMIT_ENABLED=true
Configuration with Multiple Files
configMapGenerator:
- name: nginx-config
files:
- nginx.conf
- mime.types
- conf.d/default.conf
- conf.d/ssl.conf
- conf.d/upstream.conf
Application Configuration Bundle
configMapGenerator:
- name: app-bundle
literals:
- APP_NAME=MyApp
- APP_VERSION=1.0.0 files:
- app-config.json
- feature-flags.yml
- rate-limits.json envs:
- .env.production
With files:
// app-config.json { "server": { "port": 8080, "host": "0.0.0.0" }, "database": { "pool_size": 20, "timeout": 5000 } }
feature-flags.yml
features: new_ui: true beta_features: false metrics: true
// rate-limits.json { "global": 1000, "per_user": 100, "burst": 50 }
Secrets from External Files
secretGenerator:
-
name: database-credentials files:
- username=secrets/db-username.txt
- password=secrets/db-password.txt
-
name: api-keys files:
- stripe-key=secrets/stripe-api-key.txt
- sendgrid-key=secrets/sendgrid-api-key.txt
- twilio-key=secrets/twilio-api-key.txt
TLS Certificate Bundle
secretGenerator:
- name: tls-certificates
type: kubernetes.io/tls
files:
- tls.crt=certs/server.crt
- tls.key=certs/server.key
- ca.crt=certs/ca-bundle.crt
Generator Options
Disable Name Suffix Hash
configMapGenerator:
- name: app-config
options:
disableNameSuffixHash: true
literals:
- KEY=value
Generated ConfigMap name: app-config (no hash)
Use cases:
-
Static references that shouldn't trigger rollouts
-
Resources referenced by external systems
-
Stable endpoints for debugging
Immutable ConfigMaps
configMapGenerator:
- name: app-config
options:
immutable: true
literals:
- KEY=value
Generated ConfigMap:
apiVersion: v1 kind: ConfigMap metadata: name: app-config-8g2h5m9k7t immutable: true data: KEY: value
Labels and Annotations
configMapGenerator:
- name: app-config
options:
labels:
app: myapp
environment: production
version: v1.0.0
annotations:
config.kubernetes.io/description: "Application configuration"
config.kubernetes.io/owner: "platform-team"
literals:
- KEY=value
Consuming Generated Resources
Environment Variables from ConfigMap
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: template: spec: containers: - name: myapp envFrom: - configMapRef: name: app-config
Specific Keys as Environment Variables
env:
- name: DATABASE_URL valueFrom: configMapKeyRef: name: app-config key: DATABASE_URL
- name: LOG_LEVEL valueFrom: configMapKeyRef: name: app-config key: LOG_LEVEL
Volume Mounts from ConfigMap
volumes:
- name: config
configMap:
name: app-config
items:
- key: application.properties path: app.properties
- key: logging.yml path: logging.yml
containers:
- name: myapp
volumeMounts:
- name: config mountPath: /etc/config readOnly: true
Secrets as Environment Variables
envFrom:
- secretRef: name: app-secrets
env:
- name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: app-secrets key: database-password
Secrets as Volume Mounts
volumes:
- name: secrets
secret:
secretName: app-secrets
items:
- key: database-password path: db-password mode: 0400
containers:
- name: myapp
volumeMounts:
- name: secrets mountPath: /etc/secrets readOnly: true
Real-World Examples
Web Application Configuration
base/kustomization.yaml
configMapGenerator:
- name: webapp-config
literals:
- SESSION_TIMEOUT=3600
- CSRF_ENABLED=true
- CORS_ENABLED=false files:
- nginx.conf
- app.properties
secretGenerator:
- name: webapp-secrets
literals:
- session-secret=changeme
- csrf-token-secret=changeme
resources:
- deployment.yaml
- service.yaml
overlays/production/kustomization.yaml
resources:
- ../../base
configMapGenerator:
- name: webapp-config
behavior: merge
literals:
- SESSION_TIMEOUT=7200
- CORS_ENABLED=true
- CORS_ORIGINS=https://example.com,https://www.example.com
- RATE_LIMIT_ENABLED=true
- RATE_LIMIT_REQUESTS=1000 files:
- nginx.conf=nginx-production.conf
secretGenerator:
- name: webapp-secrets
behavior: replace
files:
- session-secret=secrets/session-secret.txt
- csrf-token-secret=secrets/csrf-secret.txt
Microservices Configuration
configMapGenerator:
User Service Config
- name: user-service-config
literals:
- SERVICE_NAME=user-service
- PORT=8080
- METRICS_PORT=9090 files:
- config/user-service.yml
Order Service Config
- name: order-service-config
literals:
- SERVICE_NAME=order-service
- PORT=8081
- METRICS_PORT=9091 files:
- config/order-service.yml
Payment Service Config
- name: payment-service-config
literals:
- SERVICE_NAME=payment-service
- PORT=8082
- METRICS_PORT=9092 files:
- config/payment-service.yml
secretGenerator:
-
name: user-service-secrets literals:
- jwt-secret=user-jwt-secret
- database-password=user-db-password
-
name: payment-service-secrets literals:
- stripe-api-key=sk_test_123
- webhook-secret=whsec_123
Database Configuration
configMapGenerator:
- name: postgres-config
files:
- postgresql.conf
- pg_hba.conf literals:
- POSTGRES_DB=myapp
- POSTGRES_MAX_CONNECTIONS=200
- POSTGRES_SHARED_BUFFERS=256MB
secretGenerator:
-
name: postgres-secrets literals:
- postgres-password=super-secret-password
- replication-password=repl-password
-
name: postgres-init-scripts files:
- init.sql=scripts/init-db.sql
- create-tables.sql=scripts/schema.sql
Redis Configuration
configMapGenerator:
- name: redis-config
files:
- redis.conf literals:
- REDIS_PORT=6379
- REDIS_MAXMEMORY=2gb
- REDIS_MAXMEMORY_POLICY=allkeys-lru
secretGenerator:
- name: redis-secrets
literals:
- redis-password=redis-secure-password
Monitoring Configuration
configMapGenerator:
-
name: prometheus-config files:
- prometheus.yml
- alerts/rules.yml
- alerts/recording-rules.yml
-
name: grafana-config files:
- grafana.ini
- datasources/prometheus.yml
- dashboards/app-dashboard.json
secretGenerator:
- name: grafana-secrets
literals:
- admin-password=grafana-admin-password
- smtp-password=smtp-password
Application Feature Flags
configMapGenerator:
- name: feature-flags
files:
- feature-flags.json literals:
- FEATURE_NEW_UI=true
- FEATURE_BETA_API=false
- FEATURE_DARK_MODE=true
- FEATURE_SOCIAL_LOGIN=true
With feature-flags.json:
{ "features": { "new_ui": { "enabled": true, "rollout_percentage": 100 }, "beta_api": { "enabled": false, "rollout_percentage": 0 }, "dark_mode": { "enabled": true, "rollout_percentage": 100 }, "social_login": { "enabled": true, "providers": ["google", "github"] } } }
Generator with Transformers
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
Apply transformers
commonLabels: app: myapp
namePrefix: prod-
namespace: production
Result: ConfigMap named prod-app-config-8g2h5m9k7t in namespace production with label app: myapp
Testing Generated Resources
Build and view generated ConfigMap
kustomize build . | grep -A 20 "kind: ConfigMap"
Build and save to file
kustomize build . > generated.yaml
Validate generated resources
kustomize build . | kubectl apply --dry-run=client -f -
Compare with cluster
kustomize build . | kubectl diff -f -
Apply generated resources
kubectl apply -k .
View generated ConfigMap
kubectl get configmap -l app=myapp
Describe generated ConfigMap
kubectl describe configmap app-config-8g2h5m9k7t
View ConfigMap data
kubectl get configmap app-config-8g2h5m9k7t -o yaml
When to Use This Skill
Use the kustomize-generators skill when you need to:
-
Generate ConfigMaps from literal values, files, or environment files
-
Generate Secrets for credentials, API keys, or certificates
-
Automatically trigger pod rollouts when configuration changes
-
Manage environment-specific configuration with merge behavior
-
Create immutable ConfigMaps for stable configuration
-
Generate configuration bundles from multiple sources
-
Create TLS secrets from certificate files
-
Generate Docker registry secrets for private registries
-
Manage application feature flags across environments
-
Create database connection configurations
-
Generate monitoring and observability configurations
-
Manage microservices configuration consistently
-
Create SSH key secrets for Git operations
-
Generate application property files dynamically
-
Manage rate limiting and throttling configurations
Best Practices
-
Use generators instead of static ConfigMap/Secret YAML files
-
Leverage hash suffixes for automatic pod rollouts on config changes
-
Use behavior: merge in overlays to override specific keys
-
Store sensitive files outside version control, reference in generators
-
Use disableNameSuffixHash only when necessary for stability
-
Combine literals, files, and envs in a single generator when logical
-
Use immutable: true for ConfigMaps that shouldn't change
-
Apply labels and annotations to generated resources for tracking
-
Use named files syntax for custom key names in ConfigMaps
-
Generate Secrets from files rather than literals in production
-
Use type: kubernetes.io/tls for TLS certificate secrets
-
Document generator behavior in comments within kustomization.yaml
-
Test generated output with kustomize build before applying
-
Use envFrom for loading entire ConfigMaps as environment variables
-
Mount ConfigMaps as volumes for file-based configuration
-
Use specific key references for sensitive environment variables
-
Apply readOnly: true when mounting secrets as volumes
-
Use mode: 0400 for sensitive files in secret volumes
-
Generate separate ConfigMaps for different configuration concerns
-
Use consistent naming conventions for generated resources
-
Validate generated resources with kubectl apply --dry-run
-
Use kustomize edit add configmap for CLI-based updates
-
Keep generator source files in the same directory as kustomization.yaml
-
Use .gitignore to exclude sensitive generator source files
-
Document required generator source files in README
Common Pitfalls
-
Hardcoding secrets in literals instead of using external files
-
Not using hash suffixes, missing automatic pod rollouts
-
Committing sensitive generator source files to version control
-
Using behavior: replace when merge would be more appropriate
-
Not testing generated output before applying to clusters
-
Forgetting to update generator source files when changing configuration
-
Using absolute paths in file references instead of relative paths
-
Not documenting which files are needed for generators
-
Mixing configuration concerns in a single generator
-
Not using labels to track generated resources
-
Forgetting to set immutable: true for stable ConfigMaps
-
Using disableNameSuffixHash unnecessarily
-
Not validating generated resource names in referencing resources
-
Hardcoding generated resource names in deployments
-
Not using envFrom for loading entire ConfigMaps
-
Mounting secrets without readOnly: true
-
Not setting restrictive file modes for sensitive volume mounts
-
Using create behavior in overlays, causing conflicts
-
Not using type field for specialized secrets (TLS, Docker)
-
Forgetting to update references when changing generator names
-
Not testing behavior: merge in lower environments first
-
Using literals for large configuration blocks instead of files
-
Not organizing generator source files logically
-
Forgetting to add new generator source files to version control
-
Not using consistent key naming conventions across generators
-
Applying generators without understanding hash suffix implications
-
Not documenting generator behavior for team members
-
Using plain text files for secrets instead of secure storage
-
Not rotating generated secrets regularly
-
Forgetting to clean up old generated ConfigMaps/Secrets
Resources
-
Kustomize ConfigMap Generator Documentation
-
Kustomize Secret Generator Documentation
-
Kustomize Generator Options
-
Kubernetes ConfigMap Documentation
-
Kubernetes Secret Documentation
-
Managing ConfigMaps and Secrets
-
Immutable ConfigMaps and Secrets
-
Kustomize Best Practices