Kubernetes ConfigMaps and Secrets
The same image should run in development, staging and production. What changes between them (URLs, feature flags, credentials) belongs in ConfigMaps and Secrets.
ConfigMap for non-sensitive settings
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
data:
LOG_LEVEL: info
FEATURE_NEW_CHECKOUT: "true"
app.json: |
{ "pageSize": 20, "currency": "INR" }
Secret for credentials
kubectl create secret generic api-secrets \
--from-literal=DATABASE_URL='postgres://app:s3cret@db:5432/app' \
--from-literal=JWT_SECRET="$(openssl rand -hex 32)"
Use them in a Pod
spec:
containers:
- name: api
image: ghcr.io/acme/api:1.4.2
envFrom:
- configMapRef: { name: api-config } # every key becomes an env var
- secretRef: { name: api-secrets }
volumeMounts:
- name: config-files
mountPath: /etc/api
readOnly: true
volumes:
- name: config-files
configMap:
name: api-config
items: [{ key: app.json, path: app.json }]
Environment variables vs files
- Env vars are simple but only read at startup; changing the ConfigMap needs a Pod restart.
- Mounted files are updated in running Pods after a short delay (unless mounted with
subPath), so apps can reload them. - Trigger a rolling restart after config changes:
kubectl rollout restart deploy/api.
Secrets are not encrypted by default
- Secret values are only base64-encoded. Anyone who can read Secrets in the namespace can read them.
- Enable encryption at rest for etcd, and restrict access with RBAC.
- Never commit raw Secret manifests to Git. Use a secret manager (AWS Secrets Manager, Vault, Google Secret Manager) with the External Secrets Operator, or encrypt them with Sealed Secrets or SOPS.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.