ConfigMaps + Secrets cheatsheet.
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata: { name: app-config }
data:
DATABASE_URL: postgres://...
LOG_LEVEL: info
config.yaml: |
server:
port: 8000
kubectl create configmap app-config \
--from-literal=LOG_LEVEL=info \
--from-literal=PORT=8000
kubectl create configmap app-config --from-file=config.yaml
kubectl create configmap app-config --from-env-file=.env
Secret
apiVersion: v1
kind: Secret
metadata: { name: app-secrets }
type: Opaque
stringData: # plaintext (auto-encoded)
DB_PASSWORD: supersecret
API_KEY: sk-abc
# OR
data: # base64 encoded
DB_PASSWORD: c3VwZXJzZWNyZXQ=
kubectl create secret generic app-secrets \
--from-literal=DB_PASSWORD=supersecret
kubectl create secret tls web-tls --cert=cert.pem --key=key.pem
kubectl create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username=USER \
--docker-password=TOKEN
Use as env vars
spec:
containers:
- name: app
env:
- name: LOG_LEVEL
valueFrom: { configMapKeyRef: { name: app-config, key: LOG_LEVEL } }
- name: DB_PASSWORD
valueFrom: { secretKeyRef: { name: app-secrets, key: DB_PASSWORD } }
envFrom
spec:
containers:
- name: app
envFrom:
- configMapRef: { name: app-config }
- secretRef: { name: app-secrets }
All keys become env vars.
Use as mounted files
spec:
containers:
- name: app
volumeMounts:
- name: config
mountPath: /etc/app
readOnly: true
- name: secrets
mountPath: /etc/app/secrets
readOnly: true
volumes:
- name: config
configMap: { name: app-config }
- name: secrets
secret: { secretName: app-secrets }
Each key becomes a file.
Subpath
volumeMounts:
- name: config
mountPath: /etc/app/config.yaml
subPath: config.yaml
Mount single file (doesn’t auto-update like dir mount).
Specific items
volumes:
- name: config
configMap:
name: app-config
items:
- key: config.yaml
path: app.yaml # rename
Immutable
apiVersion: v1
kind: ConfigMap
metadata: { name: app-config }
immutable: true
data: { ... }
Can’t update. Force redeploy to change. Better for prod (prevents accidental modification).
Reload on change
Volume-mounted configs update in-place (with ~minute delay). Apps must re-read files.
For env vars: pod must restart. Use:
- Manually
kubectl rollout restart deploy/web. - Tools: stakater/reloader.
reloader
helm install reloader stakater/reloader
metadata:
annotations:
reloader.stakater.com/auto: "true"
Auto-restarts deploy on ConfigMap / Secret change.
Generic mount permissions
volumes:
- name: secrets
secret:
secretName: app-secrets
defaultMode: 0400
DockerConfigJson
kubectl create secret docker-registry ghcr \
--docker-server=ghcr.io \
--docker-username=USER \
--docker-password=TOKEN \
--docker-email=[email protected]
spec:
imagePullSecrets:
- name: ghcr
TLS
apiVersion: v1
kind: Secret
metadata: { name: web-tls }
type: kubernetes.io/tls
data:
tls.crt: ...
tls.key: ...
External Secrets Operator
For prod, store secrets in Vault / AWS Secrets Manager / GCP Secret Manager:
helm install external-secrets external-secrets/external-secrets
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata: { name: aws-secrets }
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth: { jwt: { serviceAccountRef: { name: external-secrets } } }
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: { name: app-secrets }
spec:
refreshInterval: 1m
secretStoreRef: { name: aws-secrets, kind: SecretStore }
target: { name: app-secrets }
data:
- secretKey: DB_PASSWORD
remoteRef: { key: prod/db, property: password }
Auto-syncs from AWS to K8s Secret.
sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets
kubeseal < secret.yaml > sealed-secret.yaml
Sealed secrets safe to commit to git. Controller decrypts in-cluster.
SOPS
Encrypt YAML files with age/PGP/KMS. Decrypt in CI before apply.
sops -e -i secret.yaml
Secrets at runtime (in-app)
Don’t bake secrets into images. Either:
- Mounted secrets.
- Env vars from secret.
- Pulled from external manager at startup.
Common mistakes
- Plaintext secrets in git (Secrets are base64, not encrypted).
- ConfigMap with binary file > 1MB — limit exceeded.
- Forgetting to rotate Secrets after deploy.
- env vs file mount confusion (env doesn’t update without restart).
- Same ConfigMap mounted but pod uses cached env values.
Read this next
If you want my external-secrets + reloader setup, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .