ConfigMaps, Secrets and probes
Keep configuration out of the image, handle credentials honestly, and let Kubernetes decide when a container is healthy.
ConfigMaps
Configuration belongs in a ConfigMap rather than in the image, so the same image can run in every environment.
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
data:
LOG_LEVEL: info
nginx.conf: |
server {
listen 80;
location / { return 200 "ok"; }
}spec:
containers:
- name: web
image: nginx:1.27-alpine
envFrom:
- configMapRef:
name: web-config # every key becomes an environment variable
volumeMounts:
- name: conf
mountPath: /etc/nginx/conf.d
volumes:
- name: conf
configMap:
name: web-config
items:
- key: nginx.conf
path: default.conf| Method | Pick it when |
|---|---|
envFrom | All keys as environment variables, read once at container start |
valueFrom | One key into one named variable, mixed with literals |
| Mounted volume | Config files; the file updates in place within a minute or so |
immutable: true | You want any change to force a new rollout |
Secrets
kubectl create secret generic db-creds \
--from-literal=username=app \
--from-literal=password='s3cr3t'
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d- A Secret is base64-encoded, not encrypted. Anyone who can read the object through the API can read the value.
- Turn on encryption at rest and restrict access with RBAC: treat the cluster as part of the secret's trust boundary.
- Environment variables leak into crash dumps and
kubectl describeoutput, so prefer mounting secrets as files when the application supports it. - Never commit Secret manifests to Git. Use Sealed Secrets, External Secrets or your cloud secret manager.
⚠️
Changing a Secret or ConfigMap consumed as environment variables does not update running pods. Restart the workload with
kubectl rollout restart deployment/web so the new values are read.Probes
Probes let Kubernetes decide when a container is alive and when it is ready for traffic. Getting them right is the difference between self-healing and a self-inflicted outage.
readinessProbe: # not ready = removed from the Service, pod keeps running
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe: # failing = container restarted
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
failureThreshold: 3
startupProbe: # gives a slow starter room before liveness counts
tcpSocket:
port: 8080
failureThreshold: 30
periodSeconds: 5| Probe | Question it answers | Consequence of failure |
|---|---|---|
startupProbe | Has it finished booting? | Keep waiting; liveness is disabled until it passes |
readinessProbe | Should it receive traffic? | Removed from the Service endpoints |
livenessProbe | Is it wedged? | The container is restarted |
A liveness probe should test only whether the process itself is stuck, never its dependencies. If the database is down and liveness fails, every replica restarts at once and the outage gets worse.
FAQ
Why does my pod restart in a loop?
The liveness probe keeps failing. Read
kubectl describe pod for the probe result, loosen the timeout or initialDelaySeconds, and confirm the endpoint exists and returns 200.Are Secrets actually secret?
Only as much as RBAC and encryption at rest make them. They are not encrypted in etcd by default, and anyone with read access to the namespace can decode them.
Related
Pods, Deployments and Services Rollouts and debugging
Last refreshed 2026-09-18.