Skip to content

Commit 4939083

Browse files
committed
Chapters: nest failure bullets under each symptom
1 parent ab959bb commit 4939083

11 files changed

Lines changed: 378 additions & 126 deletions

File tree

chapters/ch01.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,18 @@ sequenceDiagram
8686

8787
**Where this can fail**
8888

89-
- **Symptom:** 403 Forbidden. **Cause:** RBAC denies the verb/resource pair. **Where to look:** `kubectl auth can-i`, audit log.
90-
- **Symptom:** create hangs, fails after ~10–30s. **Cause:** a matching webhook is down with `failurePolicy: Fail` (Flow 4). **Where to look:** API server logs, webhook configurations.
91-
- **Symptom:** all writes fail cluster-wide; reads may still work. **Cause:** etcd lost quorum — no raft leader, no commits. **Where to look:** etcd member health.
92-
- **Symptom:** object persisted but nothing happens. **Cause:** the write succeeded; a downstream controller is broken — the API cannot tell you that. **Where to look:** object events and status, controller logs.
89+
- **Symptom:** 403 Forbidden.
90+
- **Cause:** RBAC denies the verb/resource pair.
91+
- **Where to look:** `kubectl auth can-i`, audit log.
92+
- **Symptom:** create hangs, fails after ~10–30s.
93+
- **Cause:** a matching webhook is down with `failurePolicy: Fail` (Flow 4).
94+
- **Where to look:** API server logs, webhook configurations.
95+
- **Symptom:** all writes fail cluster-wide; reads may still work.
96+
- **Cause:** etcd lost quorum — no raft leader, no commits.
97+
- **Where to look:** etcd member health.
98+
- **Symptom:** object persisted but nothing happens.
99+
- **Cause:** the write succeeded; a downstream controller is broken — the API cannot tell you that.
100+
- **Where to look:** object events and status, controller logs.
93101

94102
## Questions
95103

chapters/ch02.md

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,18 @@ sequenceDiagram
7575

7676
**Where this can fail**
7777

78-
- **Symptom:** endless stream of 409s in controller logs. **Cause:** hot object plus retry without jitter, or retrying from a stale cache. **Where to look:** controller logs; `managedFields` for who else writes.
79-
- **Symptom:** a field flips between two values. **Cause:** two controllers each believe they own it and "correct" the other. **Where to look:** `managedFields` managers and timestamps.
80-
- **Symptom:** SSA apply fails naming another manager. **Cause:** genuine shared-field ownership. **Where to look:** decide the rightful owner; only then consider `force`.
81-
- **Symptom:** update succeeds but changes vanish. **Cause:** a writer sent a full-object UPDATE with no resourceVersion — last-write-wins over changes it never saw. **Where to look:** audit log for the overwriting request.
78+
- **Symptom:** endless stream of 409s in controller logs.
79+
- **Cause:** hot object plus retry without jitter, or retrying from a stale cache.
80+
- **Where to look:** controller logs; `managedFields` for who else writes.
81+
- **Symptom:** a field flips between two values.
82+
- **Cause:** two controllers each believe they own it and "correct" the other.
83+
- **Where to look:** `managedFields` managers and timestamps.
84+
- **Symptom:** SSA apply fails naming another manager.
85+
- **Cause:** genuine shared-field ownership.
86+
- **Where to look:** decide the rightful owner; only then consider `force`.
87+
- **Symptom:** update succeeds but changes vanish.
88+
- **Cause:** a writer sent a full-object UPDATE with no resourceVersion — last-write-wins over changes it never saw.
89+
- **Where to look:** audit log for the overwriting request.
8290

8391
### Flow 3: What happens when a watch is established — and falls behind
8492

@@ -116,10 +124,18 @@ sequenceDiagram
116124

117125
**Where this can fail**
118126

119-
- **Symptom:** logs full of "too old resource version" and relists. **Cause:** handlers too slow for the event rate, or churn exceeding the cache window. **Where to look:** handler latency, object churn rate.
120-
- **Symptom:** controller acts on stale objects — 409s on every write. **Cause:** normal cache lag, or a wedged reflector. **Where to look:** informer HasSynced, reflector logs.
121-
- **Symptom:** API server memory spikes when a controller restarts. **Cause:** full relist of a huge resource, amplified across replicas. **Where to look:** APF metrics, list sizes; mitigate with pagination and scoped watches.
122-
- **Symptom:** events seemingly "missed". **Cause:** compacted away during disconnect; only final state is recoverable — by design. **Where to look:** nothing to recover; the controller must reconcile from current state.
127+
- **Symptom:** logs full of "too old resource version" and relists.
128+
- **Cause:** handlers too slow for the event rate, or churn exceeding the cache window.
129+
- **Where to look:** handler latency, object churn rate.
130+
- **Symptom:** controller acts on stale objects — 409s on every write.
131+
- **Cause:** normal cache lag, or a wedged reflector.
132+
- **Where to look:** informer HasSynced, reflector logs.
133+
- **Symptom:** API server memory spikes when a controller restarts.
134+
- **Cause:** full relist of a huge resource, amplified across replicas.
135+
- **Where to look:** APF metrics, list sizes; mitigate with pagination and scoped watches.
136+
- **Symptom:** events seemingly "missed".
137+
- **Cause:** compacted away during disconnect; only final state is recoverable — by design.
138+
- **Where to look:** nothing to recover; the controller must reconcile from current state.
123139

124140
### Flow 4: What happens when an admission webhook is down
125141

@@ -155,10 +171,18 @@ sequenceDiagram
155171

156172
**Where this can fail**
157173

158-
- **Symptom:** every deploy errors "failed calling webhook". **Cause:** dead backend, bad CA bundle, or Service/port mismatch, with `failurePolicy: Fail`. **Where to look:** webhook configuration, its Service endpoints, API server logs.
159-
- **Symptom:** all writes ~10s slower but succeeding. **Cause:** webhook timing out with `Ignore` — a silent latency and policy hole. **Where to look:** `apiserver_admission_webhook_*` metrics.
160-
- **Symptom:** cluster cannot recover after a full outage. **Cause:** webhook pods and the workloads they gate deadlock on startup. **Where to look:** namespace exclusions; break the loop by deleting the webhook configuration temporarily.
161-
- **Symptom:** policy violations exist despite the webhook. **Cause:** `Ignore` fired during an incident, or objects predate the webhook. **Where to look:** audit logs; add a scanning controller for existing objects.
174+
- **Symptom:** every deploy errors "failed calling webhook".
175+
- **Cause:** dead backend, bad CA bundle, or Service/port mismatch, with `failurePolicy: Fail`.
176+
- **Where to look:** webhook configuration, its Service endpoints, API server logs.
177+
- **Symptom:** all writes ~10s slower but succeeding.
178+
- **Cause:** webhook timing out with `Ignore` — a silent latency and policy hole.
179+
- **Where to look:** `apiserver_admission_webhook_*` metrics.
180+
- **Symptom:** cluster cannot recover after a full outage.
181+
- **Cause:** webhook pods and the workloads they gate deadlock on startup.
182+
- **Where to look:** namespace exclusions; break the loop by deleting the webhook configuration temporarily.
183+
- **Symptom:** policy violations exist despite the webhook.
184+
- **Cause:** `Ignore` fired during an incident, or objects predate the webhook.
185+
- **Where to look:** audit logs; add a scanning controller for existing objects.
162186

163187
## Questions
164188

chapters/ch03.md

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,18 @@ sequenceDiagram
7171

7272
**Where this can fail**
7373

74-
- **Symptom:** pod Pending with FailedScheduling event. **Cause:** no node passes Filter — resources, taints, affinity, volume topology. **Where to look:** `kubectl describe pod`; events enumerate filter failures per node.
75-
- **Symptom:** pod scheduled but kubelet rejects it with OutOfcpu. **Cause:** scheduler raced kubelet-reported allocatable; kubelet admission is the final check. **Where to look:** pod events, node allocatable vs summed requests.
76-
- **Symptom:** binding fails, pod re-queued. **Cause:** PreBind failure (volume provisioning error) or API conflict. **Where to look:** scheduler logs, PVC events.
77-
- **Symptom:** scheduling latency grows with cluster size. **Cause:** heavy pod affinity rules or scoring too many nodes. **Where to look:** per-plugin scheduler latency metrics.
74+
- **Symptom:** pod Pending with FailedScheduling event.
75+
- **Cause:** no node passes Filter — resources, taints, affinity, volume topology.
76+
- **Where to look:** `kubectl describe pod`; events enumerate filter failures per node.
77+
- **Symptom:** pod scheduled but kubelet rejects it with OutOfcpu.
78+
- **Cause:** scheduler raced kubelet-reported allocatable; kubelet admission is the final check.
79+
- **Where to look:** pod events, node allocatable vs summed requests.
80+
- **Symptom:** binding fails, pod re-queued.
81+
- **Cause:** PreBind failure (volume provisioning error) or API conflict.
82+
- **Where to look:** scheduler logs, PVC events.
83+
- **Symptom:** scheduling latency grows with cluster size.
84+
- **Cause:** heavy pod affinity rules or scoring too many nodes.
85+
- **Where to look:** per-plugin scheduler latency metrics.
7886

7987
### Flow 6: What happens when no node fits
8088

@@ -108,10 +116,18 @@ flowchart TD
108116

109117
**Where this can fail**
110118

111-
- **Symptom:** preemptor stays Pending after victims die. **Cause:** freed capacity taken by others, or a higher-priority pod claimed the node — nominatedNodeName is not binding. **Where to look:** scheduler logs, competing priorities.
112-
- **Symptom:** unexpected evictions of workload pods. **Cause:** someone deployed a high-priorityClass pod; preemption working as designed. **Where to look:** victim pod events (Preempted), priorityClass audit.
113-
- **Symptom:** no preemption despite a priority difference. **Cause:** `preemptionPolicy: Never` on the class, or victims' PDBs made every candidate worse. **Where to look:** PriorityClass spec, scheduler logs.
114-
- **Symptom:** cascading preemption churn. **Cause:** many similar priorities competing for scarce capacity. **Where to look:** priority distribution; fix with capacity or clearer tiers.
119+
- **Symptom:** preemptor stays Pending after victims die.
120+
- **Cause:** freed capacity taken by others, or a higher-priority pod claimed the node — nominatedNodeName is not binding.
121+
- **Where to look:** scheduler logs, competing priorities.
122+
- **Symptom:** unexpected evictions of workload pods.
123+
- **Cause:** someone deployed a high-priorityClass pod; preemption working as designed.
124+
- **Where to look:** victim pod events (Preempted), priorityClass audit.
125+
- **Symptom:** no preemption despite a priority difference.
126+
- **Cause:** `preemptionPolicy: Never` on the class, or victims' PDBs made every candidate worse.
127+
- **Where to look:** PriorityClass spec, scheduler logs.
128+
- **Symptom:** cascading preemption churn.
129+
- **Cause:** many similar priorities competing for scarce capacity.
130+
- **Where to look:** priority distribution; fix with capacity or clearer tiers.
115131

116132
### Flow 7: What happens when a taint is applied to a node
117133

@@ -146,10 +162,18 @@ sequenceDiagram
146162

147163
**Where this can fail**
148164

149-
- **Symptom:** DaemonSet pods survive the node-condition NoExecute taints (`node.kubernetes.io/*`). **Cause:** the DaemonSet controller adds tolerations for exactly those taints — intended. A custom NoExecute taint like this flow's *does* evict untolerated DaemonSet pods. **Where to look:** the pod's tolerations.
150-
- **Symptom:** pods evicted five minutes after a network blip that already healed. **Cause:** the 300s toleration expired before the taint was removed. **Where to look:** node lifecycle controller logs, taint history.
151-
- **Symptom:** new pods still land on a tainted node. **Cause:** a broad `operator: Exists` toleration copied from a template. **Where to look:** pod spec tolerations.
152-
- **Symptom:** taint added but evictions trickle slowly. **Cause:** the taint-eviction controller rate-limits to avoid stampedes on wide failures. **Where to look:** KCM eviction rate settings and logs.
165+
- **Symptom:** DaemonSet pods survive the node-condition NoExecute taints (`node.kubernetes.io/*`).
166+
- **Cause:** the DaemonSet controller adds tolerations for exactly those taints — intended. A custom NoExecute taint like this flow's *does* evict untolerated DaemonSet pods.
167+
- **Where to look:** the pod's tolerations.
168+
- **Symptom:** pods evicted five minutes after a network blip that already healed.
169+
- **Cause:** the 300s toleration expired before the taint was removed.
170+
- **Where to look:** node lifecycle controller logs, taint history.
171+
- **Symptom:** new pods still land on a tainted node.
172+
- **Cause:** a broad `operator: Exists` toleration copied from a template.
173+
- **Where to look:** pod spec tolerations.
174+
- **Symptom:** taint added but evictions trickle slowly.
175+
- **Cause:** the taint-eviction controller rate-limits to avoid stampedes on wide failures.
176+
- **Where to look:** KCM eviction rate settings and logs.
153177

154178
## Questions
155179

0 commit comments

Comments
 (0)