Phase 3: Configuration and State
Time: week 3. Goal: everything you currently do with environment:, .env, and volumes:.
ConfigMap
Non-secret configuration, consumed two ways:
- As environment variables (
envFrom/valueFrom). - As mounted files (a ConfigMap key becomes a file in the container).
Secret
Same mechanics as ConfigMap, different intent. Two things to know:
- Base64 is NOT encryption. It's encoding. Anyone with read access to the Secret reads the value.
- Real clusters layer something on top: encryption at rest, or external managers (Vault, cloud secret stores, External Secrets Operator). Awareness only for now.
Volumes
- emptyDir: scratch space, dies with the pod.
- hostPath: a directory on the node. Almost never in real clusters - pods move between nodes.
- The real model: PersistentVolume (the disk), PersistentVolumeClaim (a request for a disk), StorageClass (how disks get provisioned automatically). In practice you write a PVC, the StorageClass dynamically provisions the PV, and you mount the claim.
Probes
The feature compose barely has, and it matters enormously:
- Readiness probe: gates traffic. Failing readiness means the Service stops sending requests to this pod. Use it for "I'm up but my DB connection isn't ready yet".
- Liveness probe: restarts wedged containers. Use sparingly - a bad liveness probe causes restart storms.
- Startup probe: for slow-booting apps, disables the other probes until first success.
Resource requests and limits
- Requests drive scheduling: the scheduler places pods on nodes with enough unreserved capacity.
- Limits drive throttling (CPU) and OOM kills (memory).
Most production incidents trace back to getting these wrong. No requests means the scheduler packs blindly; too-low memory limits mean random OOMKilled pods.
StatefulSet
When Deployments aren't enough: stable network identity (db-0, db-1), ordered startup, one PVC per replica. Databases and queues live here - if you run them in-cluster at all.
The honest take: for production databases, a managed service outside the cluster is usually the boring, correct answer. Run Postgres in k8s for dev/test; think hard before doing it in prod.
Exercise
Full playbook with complete manifests (Postgres + Adminer): Lab 3.
Deploy an app + Postgres pair:
- App config via ConfigMap (env vars).
- DB password via Secret, referenced by both app and DB.
- Postgres data on a PVC.
- Readiness probe on the app so it only receives traffic once it can reach the DB.
- Kill the Postgres pod and verify data survives (the PVC reattaches).
Checkpoint
- You can explain the difference between readiness and liveness, and what happens when each fails.
- You can explain requests vs limits in one sentence each.
- You know why base64 secrets are not "secure" and what people do about it.