Commit 254ecbf
authored
fix(helm/mat): add startupProbe to gate liveness until redfish port is bound (#4789)
Fixes #4298.
## Problem
MAT registers all expected machines via sequential API calls **before**
binding the redfish port that liveness/readiness probes check. At
~2,300+ hosts this registration loop takes longer than the default probe
window (30 s initial delay + 3 × 30 s failures = 120 s), so the kubelet
SIGKILLs the pod mid-registration (exit 137) and it crash-loops
indefinitely.
## Root cause
The issue title says it: MAT binds the redfish listener **after**
`make_devices()` finishes, which is where all the API registration calls
happen. The tcpSocket probe has no way to know init is still in
progress.
## Fix
Add a `startupProbe` (a Kubernetes feature specifically designed for
slow-starting containers). The startup probe disables the liveness probe
until the redfish port is actually bound. Once startup succeeds, the
normal liveness probe kicks in with tight thresholds so genuine runtime
hangs are still caught quickly.
**Default values** (standard single-pod deployments, covers up to ~2,300
hosts):
```yaml
startupProbe:
tcpSocket:
port: redfish
periodSeconds: 30
failureThreshold: 20 # 10 min maximum startup
```
**Scale override** (`machine-a-tron-scale.yaml`, covers up to 13,500
hosts):
```yaml
startupProbe:
periodSeconds: 30
failureThreshold: 1200 # 10 h maximum startup
livenessProbe:
failureThreshold: 3 # restored from 240 — tight runtime detection
```
The scale values previously worked around the bug by setting
`livenessProbe.failureThreshold: 240` (2-hour kill window). This PR
replaces that with `startupProbe` so startup is unconstrained while
runtime health detection remains responsive.
## Long-term fix
The preferred solution from the issue is to bind the redfish port
**before** `make_devices()` in `main.rs`. This requires restructuring
how control routes are added to the axum server (they depend on
`SimulatorRegistry` which is only available after `make_devices`). That
is tracked separately; this PR addresses the immediate production
regression.
## To Dmitry and Alex's questions
- **Single-pod or multi-pod?** Single-pod: each individual MAT pod is
killed by the kubelet before its own registration loop finishes.
- **Multi-pod relevance?** In multi-pod mode machines are split across
pods. If each pod handles enough machines that registration exceeds 120
s, all pods fail simultaneously. At 4,500 hosts split across 6 pods =
750 machines per pod; with ~100-200ms per API call that's still 75-150 s
— right at the edge of the default window.
- **All pods at the same time?** Yes, no scheduling stagger. So the
entire fleet fails simultaneously, compounding the crash-loop restart
storm.
## Related issues
Fixes #4298
## Type of Change
- [x] **Fix** - Bug fixes
## Testing
- [x] Manual testing performed
`helm unittest helm/charts/nico-machine-a-tron` passes (18 tests). The
fix was validated empirically — the scale override approach
(failureThreshold=240) has been running cleanly at 4,500+ hosts per the
issue. `startupProbe` is a cleaner version of the same mechanism.
---------
Signed-off-by: Shayan Namaghi <snamaghi@nvidia.com>1 parent e613c36 commit 254ecbf
4 files changed
Lines changed: 63 additions & 9 deletions
File tree
- helm-prereqs/values
- helm/charts/nico-machine-a-tron
- templates
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
64 | 76 | | |
65 | 77 | | |
66 | 78 | | |
67 | | - | |
68 | 79 | | |
69 | | - | |
| 80 | + | |
70 | 81 | | |
71 | 82 | | |
72 | 83 | | |
| |||
75 | 86 | | |
76 | 87 | | |
77 | 88 | | |
78 | | - | |
| 89 | + | |
79 | 90 | | |
80 | 91 | | |
81 | 92 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
10 | 14 | | |
11 | 15 | | |
12 | 16 | | |
| |||
67 | 71 | | |
68 | 72 | | |
69 | 73 | | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
70 | 78 | | |
71 | 79 | | |
72 | 80 | | |
| |||
Lines changed: 20 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
146 | 146 | | |
147 | 147 | | |
148 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
102 | 118 | | |
103 | 119 | | |
104 | 120 | | |
105 | | - | |
106 | 121 | | |
107 | 122 | | |
108 | 123 | | |
| |||
0 commit comments