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
MethodPick it when
envFromAll keys as environment variables, read once at container start
valueFromOne key into one named variable, mixed with literals
Mounted volumeConfig files; the file updates in place within a minute or so
immutable: trueYou 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 describe output, 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
ProbeQuestion it answersConsequence of failure
startupProbeHas it finished booting?Keep waiting; liveness is disabled until it passes
readinessProbeShould it receive traffic?Removed from the Service endpoints
livenessProbeIs 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.

Pods, Deployments and Services Rollouts and debugging

Last refreshed 2026-09-18.