Repository navigation
fix: readiness waits for decdn_node_boot_ready, not a 200 - #205
Merged
Merged
Conversation
decdn/decdn#2821 serves /metrics from process start, with decdn_node_boot_ready 0 until boot finishes, so a 200 no longer means boot is done. One rule everywhere: ready is a 200 with the gauge at 1, or a 200 with no gauge (older releases bind /metrics only after boot). - Role: the readiness probe retries a 200 that says 0, and its advisory warning names which state it ended in. - decdn-compose health: reports boot from the gauge (boot_state). - Chart: the default startupProbe runs `decdn node health` (the admin RPC starts after boot), so the 5-minute budget restarts a stuck boot again and the pod goes Ready only after boot; the render refuses admin_port 0 with that probe and any probe with two handlers. - Molecule: the stub boots with the gauge at 0 then 1 (stuck, legacy and no-metrics modes); slow-readiness covers a stuck boot and, in a side effect, a daemon that never binds; host-env covers a release without the gauge. Closes #204 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The slow-readiness check can race the restarted daemon’s socket binding and fail spuriously, so it needs bounded retries until /metrics returns 200 before checking the gauge.
1 open issue
What changed in this PR
Updates boot-readiness checks across Ansible, Compose, and Helm for nodes that expose /metrics before startup finishes, while preserving compatibility with releases without the boot-ready gauge.
Changes:
- Check
decdn_node_boot_readyin Ansible and Compose, with clearer timeout diagnostics. - Use the admin RPC for Helm’s startup probe and reject conflicting probe handlers.
- Extend unit tests and Molecule scenarios for ready, stuck, legacy, and unavailable-metrics states.
| File | Description |
|---|---|
| compose/tests/test_decdn_compose.py | Tests boot-state parsing and legacy compatibility. |
| compose/README.md | Documents gauge-aware health checks. |
| compose/decdn-compose | Reports node boot readiness from metrics. |
| charts/decdn-node/values.yaml | Switches the default startup probe to admin RPC. |
| charts/decdn-node/tests/render-test.sh | Checks startup commands and invalid probe configurations. |
| charts/decdn-node/templates/_helpers.tpl | Validates probe handlers and admin RPC availability. |
| charts/decdn-node/README.md | Explains probe behavior and override migration. |
| ansible/roles/decdn_node/tasks/main.yml | Polls boot readiness and distinguishes timeout states. |
| ansible/roles/decdn_node/README.md | Documents readiness and compatibility behavior. |
| ansible/roles/decdn_node/defaults/main.yml | Updates readiness comments; defaults remain unchanged. |
| ansible/README.md | Updates the readiness scenario description. |
| ansible/molecule/slow-readiness/verify.yml | Verifies a running node remains booting. |
| ansible/molecule/slow-readiness/side_effect.yml | Exercises the unavailable-metrics timeout path. |
| ansible/molecule/slow-readiness/prepare.yml | Configures the stub for a stuck boot. |
| ansible/molecule/slow-readiness/molecule.yml | Shares inventory settings and adds side effects. |
| ansible/molecule/slow-readiness/converge.yml | Asserts retries continue during a stuck boot. |
| ansible/molecule/host-env/prepare.yml | Configures legacy gauge-less metrics. |
| ansible/molecule/host-env/converge.yml | Verifies acceptance of gauge-less responses. |
| ansible/molecule/default/files/decdn-node-stub | Models delayed readiness and alternate boot states. |
| ansible/molecule/default/converge.yml | Asserts the probe finishes with boot-ready set. |
| ansible/Makefile | Updates the readiness scenario comment. |
Review effort: Balanced
- Role: a decdn_node_boot_ready sample that is not exactly `1` (0.0, labelled, timestamped) counts as booting, so a format change upstream cannot pass as ready; uri gets timeout: 5, and the warning prints the sample it saw or the last error. The warning is registered. - decdn-compose: boot_state returns (ready, detail), reads labelled and timestamped samples, and no longer claims a gauge a release lacks. - Chart: startupProbe budget 10 min (upstream's boot-read retry budget); the admin_port guard matches `sh -c "decdn node health"` and refuses a string command; NOTES.txt and the README describe the new ordering (the first ContentBlacklist sync is part of boot). - Molecule: the stub's boot clock starts at the first scrape and gains an `error` mode; slow-readiness asserts the warning branch, that a never-binding daemon stayed up, and that a 500 fails the probe on its first attempt; default/host-env assert the probe stopped before its window with no warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

What
decdn/decdn#2821 serves
/metricsfrom process start and holdsdecdn_node_boot_readyat0until boot finishes. After that release, a 200 on/metricsno longer means the node has booted. Every path now uses one rule:v0.3.0 and v0.3.1 export no gauge and bind
/metricsonly after boot, so a 200 still means ready on them. That makes this safe to merge before the release that carries #2821. Hosts held on an exact v0.3.0 or v0.3.1 keep working.decdn_node§ Readiness): the probe keeps retrying a 200 that says0. A timeout is still advisory. The warning now says which state the node ended in: still booting (it namesDecdnNodeBootStuckanddecdn_chain_boot_read_retries_total), or/metricsnever answered. A non-200 answer still fails the run.decdn-compose health: thedecdn-node metricscheck becomesdecdn-node boot. It is read from the gauge by a newboot_state()helper, which has unit tests.startupProbeis nowexec decdn node health, the same check as the Compose healthcheck. The admin RPC starts only after boot, so the startup budget restarts a stuck boot again. That budget is now 10 minutes, matching upstream's own budget for retrying the boot chain reads. and the pod goes Ready only after boot. Readiness and liveness stayhttpGet /metrics, because they run only after startup passes. The render now fails in two cases:admin_port: 0while the default startupProbe is in use.httpGetinto the defaultexec. The README explains how to null the default handler.0, then sets it to1after 3 s. A marker file can switch it into one of three other modes:stuck,legacy(no gauge) orno-metrics.defaultasserts that the probe ended on1.slow-readinesscovers a stuck boot: the probe must retry the 200 for the whole window, and its warning must name the booting state. A newside_effectcovers two more cases. A daemon that never binds must stay advisory: it warns, the unit stays up and is never restarted. A/metricsthat answers 500 must fail the probe on its first attempt.host-envcovers a release without the gauge: one attempt, accepted.Closes #204
Notes
httpGetstartupProbe now fails the render (two handlers) until it setsstartupProbe.exec: null. This is in the chart README, so the release notes should mention it.After review (second commit)
Applied the four-agent review:
timeout: 5on the probe; the warning prints the sample it saw, or the last error.boot_statereads labelled and timestamped samples, and no longer claims a gauge on a release that has none.node healthcommand and refuses a string command.NOTES.txtand the README now describe the right ordering: the first ContentBlacklist sync is part of boot.Verification
make test-scripts,make lint-helm(new render checks and expect_fails),make lint,make lint-ansible: all pass.make molecule SCENARIOS='default slow-readiness host-env grafana-cloud': 4/4 pass. Both warning branches and the 500 rescue ran in slow-readiness.🤖 Generated with Claude Code