feat(monitoring): probe and alert on Woodpecker and OpenBao #697

Merged
k.renner merged 1 commits from probe-ci-openbao into master 2026-08-28 08:59:10 +00:00
Member

Beide waren unüberwacht, und beide sind keine Blattdienste: Woodpecker fährt jeden Cron und jedes Deploy dieses Repos, und jedes ExternalSecret im Cluster löst über OpenBao auf.

OpenBao wird auf /v1/sys/health geprüft, nicht auf /

Eine versiegelte Instanz serviert ihre UI weiter. Die Wurzel antwortet 307 → /ui/ → 200, während jeder Secret-Lookup scheitert — exakt die Grün-obwohl-kaputt-Form, vor der probes-blackbox.yaml bei den gateten Monitoring-UIs bereits warnt.

standbyok=true ist nicht kosmetisch

Der Endpunkt liefert 200 nur auf dem aktiven Knoten und 429 auf einem Standby. Gemessen:

/v1/sys/health                  -> 429
/v1/sys/health?standbyok=true   -> 200

Die externe Route landet derzeit auf einem Standby. Ohne den Parameter wäre die Probe ab dem ersten Scrape rot gewesen. Mit ihm heißt 200: initialisiert, entsiegelt, ausliefernd — auf welchem Knoten auch immer. 503 (sealed) und 501 (uninitialized) bleiben rot.

Alarmregeln gleich mit

Alert Severity Warum
WoodpeckerDown warning Alertmanager ist unabhängig und meldet weiter — aber der alert-monitor-Cron, der Issues anlegt, läuft in Woodpecker. Ein Ausfall ist konstruktionsbedingt still.
OpenBaoUnavailable critical Bestehende Secrets laufen weiter, es bricht also nichts sofort. Der Schaden zeigt sich beim nächsten Refresh-Intervall oder beim nächsten Pod, der ein frisches Credential braucht.

Das OpenBao-Matching läuft über einen Instance-Präfix statt über den vollen String, weil das Ziel einen Query-Parameter trägt und ein exakter Match still brechen würde, falls das Label ihn je anders kodiert.

Nebenbefund, hier bewusst nicht behoben

Es gibt keine generische Blackbox-Down-Regel. Nur fsn1, netbird und die zwei Relays haben Alarme. gitea, immich, auth, home, prometheus, alerts und dash werden gemessen und geplottet — aber wenn sie ausfallen, feuert nichts.

Das ist dieselbe Klasse wie der 502 auf file.renner.uno, nur eine Ebene höher. Zu beheben wäre es mit einer generischen Regel über job="blackbox-http", was aber eine Entscheidung braucht: entweder die per-Instance-Regeln zurückziehen oder die generische Regel gegen sie abgrenzen, sonst feuert für fsn1 und netbird alles doppelt.

Geprüft

kubectl apply --dry-run=server -k kubernetes/apps/monitoring-rules sauber; die neue Regel wird als created gemeldet, die drei Probes als configured.

Was ich erst nach dem Merge sehen kann: ob das instance-Label die Query-String-Form so trägt, wie ich annehme. Deshalb der Präfix-Match. Ich prüfe nach dem Reconcile, ob beide Targets in Prometheus auftauchen und probe_success liefern — wenn nicht, melde ich das, statt es als erledigt zu verbuchen.

Beide waren unüberwacht, und beide sind keine Blattdienste: Woodpecker fährt jeden Cron und jedes Deploy dieses Repos, und jedes ExternalSecret im Cluster löst über OpenBao auf. ## OpenBao wird auf `/v1/sys/health` geprüft, nicht auf `/` Eine **versiegelte** Instanz serviert ihre UI weiter. Die Wurzel antwortet `307 → /ui/ → 200`, während jeder Secret-Lookup scheitert — exakt die Grün-obwohl-kaputt-Form, vor der `probes-blackbox.yaml` bei den gateten Monitoring-UIs bereits warnt. ## `standbyok=true` ist nicht kosmetisch Der Endpunkt liefert 200 nur auf dem **aktiven** Knoten und 429 auf einem Standby. Gemessen: ``` /v1/sys/health -> 429 /v1/sys/health?standbyok=true -> 200 ``` Die externe Route landet derzeit auf einem Standby. Ohne den Parameter wäre die Probe **ab dem ersten Scrape rot** gewesen. Mit ihm heißt 200: initialisiert, entsiegelt, ausliefernd — auf welchem Knoten auch immer. 503 (sealed) und 501 (uninitialized) bleiben rot. ## Alarmregeln gleich mit | Alert | Severity | Warum | |---|---|---| | `WoodpeckerDown` | warning | Alertmanager ist unabhängig und meldet weiter — aber der alert-monitor-Cron, der Issues anlegt, läuft in Woodpecker. Ein Ausfall ist konstruktionsbedingt still. | | `OpenBaoUnavailable` | critical | Bestehende Secrets laufen weiter, es bricht also nichts sofort. Der Schaden zeigt sich beim nächsten Refresh-Intervall oder beim nächsten Pod, der ein frisches Credential braucht. | Das OpenBao-Matching läuft über einen **Instance-Präfix** statt über den vollen String, weil das Ziel einen Query-Parameter trägt und ein exakter Match still brechen würde, falls das Label ihn je anders kodiert. ## Nebenbefund, hier bewusst nicht behoben **Es gibt keine generische Blackbox-Down-Regel.** Nur `fsn1`, `netbird` und die zwei Relays haben Alarme. `gitea`, `immich`, `auth`, `home`, `prometheus`, `alerts` und `dash` werden gemessen und geplottet — aber wenn sie ausfallen, feuert **nichts**. Das ist dieselbe Klasse wie der 502 auf `file.renner.uno`, nur eine Ebene höher. Zu beheben wäre es mit einer generischen Regel über `job="blackbox-http"`, was aber eine Entscheidung braucht: entweder die per-Instance-Regeln zurückziehen oder die generische Regel gegen sie abgrenzen, sonst feuert für `fsn1` und `netbird` alles doppelt. ## Geprüft `kubectl apply --dry-run=server -k kubernetes/apps/monitoring-rules` sauber; die neue Regel wird als `created` gemeldet, die drei Probes als `configured`. **Was ich erst nach dem Merge sehen kann:** ob das `instance`-Label die Query-String-Form so trägt, wie ich annehme. Deshalb der Präfix-Match. Ich prüfe nach dem Reconcile, ob beide Targets in Prometheus auftauchen und `probe_success` liefern — wenn nicht, melde ich das, statt es als erledigt zu verbuchen.
claude-bot added 1 commit 2026-08-28 08:57:35 +00:00
feat(monitoring): probe and alert on Woodpecker and OpenBao
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
74b1bb242f
Both were unmonitored. Neither is a leaf service: Woodpecker runs every cron
and deploy in this repo, and every ExternalSecret in the cluster resolves
through OpenBao.

OpenBao is probed at /v1/sys/health rather than at the root, because a sealed
instance still serves its UI. Root would answer 307 -> /ui/ -> 200 while every
secret lookup failed — the exact green-while-broken shape probes-blackbox.yaml
already warns about for the gated monitoring UIs.

standbyok=true is required, not cosmetic: the endpoint returns 200 only on the
active node and 429 on a standby, and the external route currently lands on a
standby. Measured — the bare path returns 429 right now, so an http_2xx probe
without the parameter would have been red from the first scrape. With it, 200
means initialized, unsealed and serving; 503 sealed and 501 uninitialized stay
red.

The alert matches OpenBao by instance prefix instead of the full target string,
because that target carries a query parameter and an exact match would fail
silently if the label ever encodes it differently.

Both alerts are new rules rather than additions to an existing file. Worth
noting while here: there is no generic blackbox-down rule. Only fsn1, netbird
and the two relays have alerts, so gitea, immich, auth, home, prometheus,
alerts and dash are probed and graphed but nothing fires if they go down. Not
addressed here — it needs a decision about whether to write one generic rule
and retire the per-instance ones.
k.renner merged commit 541f3fcfe9 into master 2026-08-28 08:59:10 +00:00
review-bot left a comment
Member

🤖 Automated review — model claude-sonnet-5 (complexity: normal), commit 74b1bb242f77069965d5077287ad56a629040b45.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

Adds two blackbox HTTP probe targets (Woodpecker root, OpenBao /v1/sys/health?standbyok=true) and a new PrometheusRule (ci-openbao) with a WoodpeckerDown (warning) and OpenBaoUnavailable (critical) alert built on probe_success. No blocking issues found — the change is small, follows the repo's established conventions closely, and the reasoning in the comments/PR body is verifiably accurate against the checkout.

🟡 Suggestions

  • kubernetes/apps/monitoring-rules/prometheusrule-ci-openbao.yaml:1-92 — the two existing sibling files (prometheusrule-openbao.yaml, prometheusrule-woodpecker-rotation.yaml) are organized per-service. This PR instead bundles a Woodpecker alert and an OpenBao alert into one ci-openbao file/group organized by signal type (external blackbox probe) rather than by service. That's a defensible grouping (both are new probe-based reachability checks, distinct from the existing in-cluster readiness-based alerts for the same services), but it's a second organizing axis in a directory that was previously strictly per-service — worth a one-line note in the PR/commit if intentional, so a future reader doesn't wonder why OpenBaoUnavailable isn't in prometheusrule-openbao.yaml.
  • kubernetes/apps/monitoring-rules/prometheusrule-ci-openbao.yaml:39 (OpenBaoUnavailable) — the instance-prefix regex match is explicitly a hedge against not yet knowing how Prometheus renders the instance label for a target with a query string (the PR body says this directly). That's a reasonable mitigation, but as written the regex (https://openbao\.renner\.uno/v1/sys/health.*) would also match if the path ever changed in a way still starting with /v1/sys/health (e.g. a future /v1/sys/health-check), which is a very unlikely but silent widening. Not worth blocking on — just flagging that the follow-up verification the author already promised in the PR body (checking probe_success actually appears in Prometheus for both new targets) is the right way to close this out, and should also confirm the label looks like what the regex expects.

Tests

No automated tests exist for this class of change in the repo (PrometheusRule/Probe YAML), consistent with how the sibling alert files are handled — validation is kubectl apply --dry-run=server -k kubernetes/apps/monitoring-rules, which the PR description says was run cleanly. That's the appropriate level of verification here; I did not have a live cluster/CRDs available in this checkout to re-run the dry-run myself, but the PromQL expressions, label selectors, and YAML structure all match the patterns used by the other rules in this directory (e.g. probe_success{job="blackbox-http", instance="..."} mirrors prometheusrule-netbird-availability.yaml), and the release: kube-prometheus-stack label required for the rule to be picked up is present.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `claude-sonnet-5` (complexity: normal), commit `74b1bb242f77069965d5077287ad56a629040b45`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary Adds two blackbox HTTP probe targets (Woodpecker root, OpenBao `/v1/sys/health?standbyok=true`) and a new `PrometheusRule` (`ci-openbao`) with a `WoodpeckerDown` (warning) and `OpenBaoUnavailable` (critical) alert built on `probe_success`. No blocking issues found — the change is small, follows the repo's established conventions closely, and the reasoning in the comments/PR body is verifiably accurate against the checkout. ## 🟡 Suggestions - `kubernetes/apps/monitoring-rules/prometheusrule-ci-openbao.yaml:1-92` — the two existing sibling files (`prometheusrule-openbao.yaml`, `prometheusrule-woodpecker-rotation.yaml`) are organized per-service. This PR instead bundles a Woodpecker alert and an OpenBao alert into one `ci-openbao` file/group organized by *signal type* (external blackbox probe) rather than by service. That's a defensible grouping (both are new probe-based reachability checks, distinct from the existing in-cluster readiness-based alerts for the same services), but it's a second organizing axis in a directory that was previously strictly per-service — worth a one-line note in the PR/commit if intentional, so a future reader doesn't wonder why `OpenBaoUnavailable` isn't in `prometheusrule-openbao.yaml`. - `kubernetes/apps/monitoring-rules/prometheusrule-ci-openbao.yaml:39` (`OpenBaoUnavailable`) — the instance-prefix regex match is explicitly a hedge against not yet knowing how Prometheus renders the `instance` label for a target with a query string (the PR body says this directly). That's a reasonable mitigation, but as written the regex (`https://openbao\.renner\.uno/v1/sys/health.*`) would also match if the path ever changed in a way still starting with `/v1/sys/health` (e.g. a future `/v1/sys/health-check`), which is a very unlikely but silent widening. Not worth blocking on — just flagging that the follow-up verification the author already promised in the PR body (checking `probe_success` actually appears in Prometheus for both new targets) is the right way to close this out, and should also confirm the label looks like what the regex expects. ## Tests No automated tests exist for this class of change in the repo (PrometheusRule/Probe YAML), consistent with how the sibling alert files are handled — validation is `kubectl apply --dry-run=server -k kubernetes/apps/monitoring-rules`, which the PR description says was run cleanly. That's the appropriate level of verification here; I did not have a live cluster/CRDs available in this checkout to re-run the dry-run myself, but the PromQL expressions, label selectors, and YAML structure all match the patterns used by the other rules in this directory (e.g. `probe_success{job="blackbox-http", instance="..."}` mirrors `prometheusrule-netbird-availability.yaml`), and the `release: kube-prometheus-stack` label required for the rule to be picked up is present. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=74b1bb242f77069965d5077287ad56a629040b45 -->
Sign in to join this conversation.