docs: rework StatefulSet chapter with hardened lab and deeper explanations#5
Merged
Conversation
AS IS: the scale-to-2 exercise showed the ordinal pattern appearing but never showed what happens to the PVC when scaling back down TO BE: adds a kubectl get pvc check and an explanation that pgdata-postgres-1 survives scale-down and gets reattached on scale-up, reinforcing the "PVCs outlive the Pod" lesson from the earlier delete/reattach test TASK # N/A
AS IS: the doc asserts ordered Pod creation "matters for clustered databases" without showing why TO BE: adds the pg_basebackup primary/replica pattern to show what breaks without OrderedReady — a replica bootstrapping before the primary's DNS is resolvable TASK # N/A
AS IS: the delete/reattach exercise only checked that postgres-0 came back and pvc stayed Bound, which doesn't actually prove data survived TO BE: adds readiness/pg_isready waits, a DNS lookup check, and a real insert-then-verify test so the exercise proves data persistence instead of just Pod identity TASK # N/A
…t lab AS IS: the postgres StatefulSet had no probes or resource requests/limits, so kubectl wait reported Ready before postgres could accept connections, requiring a manual pg_isready polling loop as a workaround TO BE: add pg_isready-based readinessProbe/livenessProbe and cpu/memory requests/limits so the Pod's Ready condition reflects real DB availability, plus comments noting production should pin the image version and choose an explicit StorageClass TASK # N/A
AS IS: the postgres container ran as root with no startup grace period, and probe commands hardcoded "appuser" instead of reading POSTGRES_USER TO BE: run as the image's non-root user via securityContext/fsGroup, add a startupProbe so initialization isn't cut short by liveness checks, and have probes read $POSTGRES_USER so they stay in sync with the Secret TASK # N/A
AS IS: exercises used kubectl wait --timeout=120s, shorter than the startupProbe's worst-case 150s window (failureThreshold 30 * periodSeconds 5), so a slow first-time initdb could time out the wait before the probe itself gave up TO BE: bump the wait timeout to 180s so it comfortably covers the startupProbe's worst case TASK # N/A
AS IS: the doc used "headless Service" and referenced per-Pod DNS names without ever defining what makes a headless Service different, leaving readers to infer it from the manifest alone TO BE: add a dedicated section defining clusterIP: None, a comparison table against a normal Service, and why StatefulSets need per-Pod DNS instead of load-balanced traffic TASK # N/A
AS IS: the DNS example postgres-0.postgres.default.svc.cluster.local was shown with no explanation, so "postgres" appearing twice and "default" could easily be misread as parts of the Service name TO BE: break down the <pod>.<service>.<namespace> format and note the manifests never set metadata.namespace, so default comes from the current kubectl context, not a hardcoded value TASK # N/A
AS IS: the single 84-line YAML mixed core StatefulSet mechanics with probes, securityContext, and resource limits, making it hard to see identity/PVC/ordering without wading through production-hardening noise TO BE: trim the walkthrough YAML to just the three core StatefulSet concepts, and move the hardening fields into a separate section with a field-by-field explanation table plus their own YAML snippet TASK # N/A
AS IS: the doc mentioned volumeClaimTemplates gives each replica its own PVC but never explained how that differs from a normal Pod's volumes: reference, or where the pgdata-postgres-N naming comes from TO BE: add a dedicated section contrasting shared-PVC volumes: against per-replica volumeClaimTemplates, with the naming convention and a comparison table, linking to the scaling exercise and reclaim-policy docs TASK # N/A
AS IS: the link to "Deployment replicas sharing one PVC" pointed at deployment.md, which never mentions PVCs at all — the actual content lives in volumes.md TO BE: point the link at volumes.md so readers land on the section that actually explains the shared-PVC footgun TASK # N/A
AS IS: the manifest listed Service before StatefulSet with no explanation, so readers could reasonably assume the order was arbitrary or even backwards (workload before its supporting Service) TO BE: note that serviceName references the Service by name, so listing it first mirrors creating a ConfigMap/Secret before the Pod that reads it, and avoids a DNS race if the order were reversed TASK # N/A
AS IS: the lab only mentioned k9s once, for the delete/reattach test, leaving readers to poll kubectl get/wait for everything else even though the ordered Pod creation and PVC binding are exactly the kind of live reconciliation k9s is meant to make visible TO BE: add k9s tips at first pod startup and at the scale-to-2 exercise, pointing at :sts/:pods/:pvc so readers can watch ordering and per-replica PVC binding happen instead of just reading kubectl output TASK # N/A
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
kubectl wait --for=condition=Readyreported Ready before Postgres could accept connections.:sts/:pods/:pvc) at Pod startup and the scale-to-2 exercise so readers can observe ordered creation and per-replica PVC binding live.deployment.md, which has no PVC content; corrected tovolumes.md).Test plan
docs/config-and-data/statefulset.mdfor flow and correctnesskubectl apply -f manifests/config-and-data/postgres-statefulset.yamlon a test cluster and walk through the exercises (apply → wait → DNS lookup → write/read data → delete/reattach → scale to 2 → scale to 1)🤖 Generated with Claude Code