Docs
/
Docker Kubernetes
Chapter 12
12 — Configuration & Secrets
ConfigMap
Store non-sensitive configuration data.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
NODE_ENV: "production"
LOG_LEVEL: "info"
DATABASE_HOST: "db-svc"
config.json: |
{
"maxRetries": 3,
"timeout": 5000
}
Using ConfigMaps
# As environment variables
spec:
containers:
- name: api
image: my-app:1.0.0
envFrom:
- configMapRef:
name: app-config # All keys as env vars
# Or specific keys
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
# As mounted file
volumeMounts:
- name: config
mountPath: /app/config
volumes:
- name: config
configMap:
name: app-config
items:
- key: config.json
path: config.json # Mounted at /app/config/config.json
Secrets
Store sensitive data (base64-encoded, not encrypted by default).
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
DATABASE_PASSWORD: cGFzc3dvcmQxMjM= # base64 of "password123"
JWT_SECRET: bXktand0LXNlY3JldA==
# Create from command line
kubectl create secret generic app-secrets \
--from-literal=DATABASE_PASSWORD=password123 \
--from-literal=JWT_SECRET=my-jwt-secret
# Create from file
kubectl create secret generic tls-cert \
--from-file=cert.pem --from-file=key.pem
Using Secrets
spec:
containers:
- name: api
env:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: DATABASE_PASSWORD
# Or mount as files
volumeMounts:
- name: secrets
mountPath: /run/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets
Sealed Secrets (GitOps-Safe)
Regular Secrets can't be stored in Git (base64 ≠ encryption). SealedSecrets encrypt them.
# Install kubeseal CLI
# Encrypt secret (only cluster can decrypt)
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# sealed-secret.yaml is safe to commit to Git ✅
kubectl apply -f sealed-secret.yaml
# Controller decrypts → creates regular Secret in cluster
Full Example
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
data:
NODE_ENV: production
PORT: "3000"
DB_HOST: postgres-svc
---
apiVersion: v1
kind: Secret
metadata:
name: api-secrets
type: Opaque
stringData: # stringData = plain text (auto-encoded)
DB_PASSWORD: supersecret
JWT_SECRET: my-jwt-key
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: my-app:1.0.0
envFrom:
- configMapRef:
name: api-config
- secretRef:
name: api-secrets
ports:
- containerPort: 3000
Key Takeaways
- ConfigMap for non-sensitive config; Secret for sensitive data
- Use
envFromto inject all keys as env vars, orvalueFromfor specific keys - Mount as files when config is a file format (JSON, YAML, .env)
- Use
stringDatain Secrets for plain text (Kubernetes auto-encodes to base64) - K8s Secrets are base64, not encrypted — use SealedSecrets or external secret managers (Vault, AWS Secrets Manager) for production
- Never commit plain Secrets to Git