Use when generating ConfigMaps and Secrets with Kustomize for Kubernetes configuration management.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
Master ConfigMap and Secret generation using Kustomize generators for managing application configuration, credentials, and environment-specific settings without manual YAML creation.
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.
# 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"
# 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
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
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
configMapGenerator:
- name: app-config
literals:
- APP_NAME=MyApp
- APP_VERSION=1.0.0
files:
- application.properties
envs:
- .env
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=
secretGenerator:
- name: tls-secret
type: kubernetes.io/tls
files:
- tls.crt=certs/server.crt
- tls.key=certs/server.key
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="
}
}
}
secretGenerator:
- name: ssh-keys
type: Opaque
files:
- id_rsa=keys/id_rsa
- id_rsa.pub=keys/id_rsa.pub
configMapGenerator:
- name: app-config
behavior: create
literals:
- KEY=value
Creates a new ConfigMap. Fails if one already exists.
configMapGenerator:
- name: app-config
behavior: replace
literals:
- KEY=new-value
Replaces existing ConfigMap entirely. Fails if it doesn't exist.
# 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
# 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
configMapGenerator:
- name: nginx-config
files:
- nginx.conf
- mime.types
- conf.d/default.conf
- conf.d/ssl.conf
- conf.d/upstream.conf
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
}
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
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
configMapGenerator:
- name: app-config
options:
disableNameSuffixHash: true
literals:
- KEY=value
Generated ConfigMap name: app-config (no hash)
Use cases:
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
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
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
envFrom:
- configMapRef:
name: app-config
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: app-config
key: DATABASE_URL
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
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
envFrom:
- secretRef:
name: app-secrets
env:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: database-password
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
# 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
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
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
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
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
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"]
}
}
}
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
# 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
Use the kustomize-generators skill when you need to: