fix: [alert] KubeJobFailed (openbao) (#510) #511

Merged
k.renner merged 1 commits from alert-fix/issue-510 into master 2026-08-19 04:46:26 +00:00
Member

What this PR does

KubeJobFailed fired for job/claude-oauth-secret-sync-29785100 in openbao because the
CronJob still pointed at woodpecker.apps.svc.cluster.local:8000, a Service that no longer
exists: the Woodpecker apps → woodpecker namespace migration
(kubernetes/apps/woodpecker/MIGRATION-namespace.md) completed its cutover, but the two
openbao rotators' WOODPECKER_URL env vars were left behind. The container fails DNS
resolution and exits 1 within a second, twice, hitting BackoffLimitExceeded. This changes
both rotators' WOODPECKER_URL to woodpecker.woodpecker.svc.cluster.local:8000 (plus the
now-stale header comments that documented the old address). The issue's diagnosis and both
suggested fix locations were correct and are confirmed by live evidence.

Changes

  • kubernetes/infrastructure/openbao/rotation/claude-oauth.yaml — WOODPECKER_URL →
    http://woodpecker.woodpecker.svc.cluster.local:8000; header comment updated to name the
    new address and point at the migration doc. This is the CronJob that alerted.
  • kubernetes/infrastructure/openbao/rotation/review-bot.yaml — identical one-line fix for
    the same stale URL. Not alerting yet only because it runs quarterly; it would fail the same
    way on its next run. The gitea.apps.svc:3000 hop in the same file is left alone — gitea
    really is still in apps (verified).

Verification

Verified live this run:

  • ./.ci-diag/kubectl -n apps get svc → 7 services (external-dns, gitea, gatus, file,
    ical-proxy, pve, external-dns-unifi); no woodpecker, so the old name cannot resolve.
  • ./.ci-diag/kubectl -n woodpecker get svc -o wide → woodpecker ClusterIP 10.99.97.9,
    ports 8000/TCP,9000/TCP, age 6h16m — the new target exists.
  • ./.ci-diag/kubectl -n openbao logs claude-oauth-secret-sync-29785100-qvcn2 --tail=20 →
    error: io: failed to lookup address information: Name does not resolve (read from the live
    pod, which still exists — not from the issue's quote). A DNS failure, not auth and not netpol.
  • ./.ci-diag/kubectl -n openbao get jobs → ...29783660 Complete (25h ago),
    ...29785100 Failed (81m ago). The last success predates the ~6h-old cutover and the first
    failure follows it — the timeline matches the migration, not a transient.
  • ./.ci-diag/kubectl -n woodpecker get cnp woodpecker-allow-rotators -o jsonpath='{.spec}' →
    already admits both review-bot and claude-oauth rotators from openbao to the server on
    :8000. The egress halves in network-policies/openbao-ns.yaml already target
    k8s:io.kubernetes.pod.namespace: woodpecker. So no policy change is needed — the URL was
    the only thing left pointing at apps.
  • ./.ci-diag/kubectl apply --dry-run=client -f <both files> → both CronJobs
    configured (dry run); the only errors are expected RBAC denials reading ServiceAccounts.

After Flux reconciles, confirm without waiting for 04:20 Europe/Berlin:

kubectl -n openbao get cronjob claude-oauth-secret-sync \
  -o jsonpath='{.spec.jobTemplate.spec.template.spec.containers[0].env[?(@.name=="WOODPECKER_URL")].value}'
kubectl -n openbao create job --from=cronjob/claude-oauth-secret-sync claude-oauth-sync-now
kubectl -n openbao logs job/claude-oauth-sync-now

Expect a clean exit, not the DNS error. KubeJobFailed for
claude-oauth-secret-sync-29785100 should resolve once the failed job is deleted (per the
CronJob's own runbook note) — the alert reflects the existing failed object and will not clear
on its own just because the manifest changed.

Notes

  • Not a silenced alert. The failing job is fixed at its cause; no rule, threshold, or
    inhibition was touched.
  • Follow-up, deliberately not fixed here (separate defect, different alert family, and
    larger than a surgical change): kubernetes/apps/monitoring-rules/prometheusrule-woodpecker-rotation.yaml
    has four alert expressions still selecting namespace="apps" (lines 24, 38, 53, 68), and
    line 32's description still cites woodpecker.apps.svc:9000. I confirmed these are now dead
    rather than merely cosmetic: a Prometheus query for
    kube_statefulset_status_replicas_ready{namespace="apps",statefulset="woodpecker-server"}
    returns an empty vector, and kubectl -n woodpecker get statefulset,deploy shows
    woodpecker-server is now a Deployment in woodpecker — so WoodpeckerServerNotReady
    is wrong on both namespace and resource kind and can never fire. That means Woodpecker being
    down is currently unalerted. Worth its own issue; fixing it means rewriting four exprs and
    their descriptions, and I'd rather that be reviewed on its own than smuggled into a
    one-line DNS fix.
  • Image tags, pinned versions, and CI config were not touched. The issue contained no
    instructions to act outside the edit scope.

Closes #510

## What this PR does `KubeJobFailed` fired for `job/claude-oauth-secret-sync-29785100` in `openbao` because the CronJob still pointed at `woodpecker.apps.svc.cluster.local:8000`, a Service that no longer exists: the Woodpecker `apps` → `woodpecker` namespace migration (`kubernetes/apps/woodpecker/MIGRATION-namespace.md`) completed its cutover, but the two openbao rotators' `WOODPECKER_URL` env vars were left behind. The container fails DNS resolution and exits 1 within a second, twice, hitting `BackoffLimitExceeded`. This changes both rotators' `WOODPECKER_URL` to `woodpecker.woodpecker.svc.cluster.local:8000` (plus the now-stale header comments that documented the old address). The issue's diagnosis and both suggested fix locations were correct and are confirmed by live evidence. ## Changes - `kubernetes/infrastructure/openbao/rotation/claude-oauth.yaml` — `WOODPECKER_URL` → `http://woodpecker.woodpecker.svc.cluster.local:8000`; header comment updated to name the new address and point at the migration doc. This is the CronJob that alerted. - `kubernetes/infrastructure/openbao/rotation/review-bot.yaml` — identical one-line fix for the same stale URL. Not alerting yet only because it runs quarterly; it would fail the same way on its next run. The `gitea.apps.svc:3000` hop in the same file is left alone — gitea really is still in `apps` (verified). ## Verification Verified live this run: - `./.ci-diag/kubectl -n apps get svc` → 7 services (`external-dns`, `gitea`, `gatus`, `file`, `ical-proxy`, `pve`, `external-dns-unifi`); **no `woodpecker`**, so the old name cannot resolve. - `./.ci-diag/kubectl -n woodpecker get svc -o wide` → `woodpecker` ClusterIP `10.99.97.9`, ports `8000/TCP,9000/TCP`, age `6h16m` — the new target exists. - `./.ci-diag/kubectl -n openbao logs claude-oauth-secret-sync-29785100-qvcn2 --tail=20` → `error: io: failed to lookup address information: Name does not resolve` (read from the live pod, which still exists — not from the issue's quote). A DNS failure, not auth and not netpol. - `./.ci-diag/kubectl -n openbao get jobs` → `...29783660 Complete` (25h ago), `...29785100 Failed` (81m ago). The last success predates the ~6h-old cutover and the first failure follows it — the timeline matches the migration, not a transient. - `./.ci-diag/kubectl -n woodpecker get cnp woodpecker-allow-rotators -o jsonpath='{.spec}'` → already admits both `review-bot` and `claude-oauth` rotators from `openbao` to the server on `:8000`. The egress halves in `network-policies/openbao-ns.yaml` already target `k8s:io.kubernetes.pod.namespace: woodpecker`. **So no policy change is needed — the URL was the only thing left pointing at `apps`.** - `./.ci-diag/kubectl apply --dry-run=client -f <both files>` → both CronJobs `configured (dry run)`; the only errors are expected RBAC denials reading ServiceAccounts. After Flux reconciles, confirm without waiting for 04:20 Europe/Berlin: ```sh kubectl -n openbao get cronjob claude-oauth-secret-sync \ -o jsonpath='{.spec.jobTemplate.spec.template.spec.containers[0].env[?(@.name=="WOODPECKER_URL")].value}' kubectl -n openbao create job --from=cronjob/claude-oauth-secret-sync claude-oauth-sync-now kubectl -n openbao logs job/claude-oauth-sync-now ``` Expect a clean exit, not the DNS error. `KubeJobFailed` for `claude-oauth-secret-sync-29785100` should resolve once the failed job is deleted (per the CronJob's own runbook note) — the alert reflects the existing failed object and will not clear on its own just because the manifest changed. ## Notes - **Not a silenced alert.** The failing job is fixed at its cause; no rule, threshold, or inhibition was touched. - **Follow-up, deliberately not fixed here** (separate defect, different alert family, and larger than a surgical change): `kubernetes/apps/monitoring-rules/prometheusrule-woodpecker-rotation.yaml` has four alert expressions still selecting `namespace="apps"` (lines 24, 38, 53, 68), and line 32's description still cites `woodpecker.apps.svc:9000`. I confirmed these are now dead rather than merely cosmetic: a Prometheus query for `kube_statefulset_status_replicas_ready{namespace="apps",statefulset="woodpecker-server"}` returns an empty vector, and `kubectl -n woodpecker get statefulset,deploy` shows `woodpecker-server` is now a **Deployment** in `woodpecker` — so `WoodpeckerServerNotReady` is wrong on both namespace and resource kind and can never fire. That means Woodpecker being down is currently unalerted. Worth its own issue; fixing it means rewriting four exprs and their descriptions, and I'd rather that be reviewed on its own than smuggled into a one-line DNS fix. - Image tags, pinned versions, and CI config were not touched. The issue contained no instructions to act outside the edit scope. Closes #510
issue-fix-bot added 1 commit 2026-08-19 03:44:14 +00:00
fix: [alert] KubeJobFailed (openbao) (#510)
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
d9f1d6cfc8
review-bot left a comment
Member

🤖 Automated review — model claude-haiku-4-5-20251001 (complexity: trivial), commit d9f1d6cfc896e043e5b17280dde985cf1bc89237.

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


Summary

This PR fixes a DNS resolution failure in two OpenBao secret rotation CronJobs by updating their WOODPECKER_URL environment variable from woodpecker.apps.svc.cluster.local:8000 to woodpecker.woodpecker.svc.cluster.local:8000, reflecting the Woodpecker namespace migration that was already completed. The fix is minimal, surgical, and thoroughly verified.

🔴 Blocking

None. The changes are correct and directly address the reported issue.

🟡 Suggestions

Comment clarity — in both files, the unchanged portions of comments still reference woodpecker-allow-rotators (apps/*) notation. While the PR author verified the NetworkPolicy is already correctly configured in the woodpecker namespace, this notation may be unclear to future readers. This could be clarified in a follow-up, but is not a correctness issue — the policy itself (in kubernetes/apps/woodpecker/networkpolicy.yaml) is correctly scoped to the woodpecker server pod and already admits both rotators from openbao on :8000. Consider a follow-up PR to clarify the comment notation if needed.

🟢 Nits

None.

Tests

This is infrastructure code (Kubernetes manifests). The PR includes thorough manual verification:

  • Confirmed the old service no longer exists in the apps namespace
  • Confirmed the new service exists and is healthy in the woodpecker namespace
  • Verified DNS resolution errors in live pod logs
  • Confirmed network policies are already correctly configured
  • Verified kubectl apply --dry-run=client succeeds

The verification approach is appropriate. After Flux reconciles, the suggested post-merge validation step (creating a job from the CronJob and checking logs for clean exit instead of DNS errors) is a solid way to confirm the fix works in production.

Recommendation

Looks reasonable — no blocking issues; the suggestion above is optional and can be addressed in a follow-up.

🤖 **Automated review** — model `claude-haiku-4-5-20251001` (complexity: trivial), commit `d9f1d6cfc896e043e5b17280dde985cf1bc89237`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary This PR fixes a DNS resolution failure in two OpenBao secret rotation CronJobs by updating their `WOODPECKER_URL` environment variable from `woodpecker.apps.svc.cluster.local:8000` to `woodpecker.woodpecker.svc.cluster.local:8000`, reflecting the Woodpecker namespace migration that was already completed. The fix is minimal, surgical, and thoroughly verified. ## 🔴 Blocking None. The changes are correct and directly address the reported issue. ## 🟡 Suggestions **Comment clarity** — in both files, the unchanged portions of comments still reference `woodpecker-allow-rotators (apps/*)` notation. While the PR author verified the NetworkPolicy is already correctly configured in the `woodpecker` namespace, this notation may be unclear to future readers. This could be clarified in a follow-up, but is not a correctness issue — the policy itself (in `kubernetes/apps/woodpecker/networkpolicy.yaml`) is correctly scoped to the woodpecker server pod and already admits both rotators from openbao on `:8000`. Consider a follow-up PR to clarify the comment notation if needed. ## 🟢 Nits None. ## Tests This is infrastructure code (Kubernetes manifests). The PR includes thorough manual verification: - Confirmed the old service no longer exists in the `apps` namespace - Confirmed the new service exists and is healthy in the `woodpecker` namespace - Verified DNS resolution errors in live pod logs - Confirmed network policies are already correctly configured - Verified `kubectl apply --dry-run=client` succeeds The verification approach is appropriate. After Flux reconciles, the suggested post-merge validation step (creating a job from the CronJob and checking logs for clean exit instead of DNS errors) is a solid way to confirm the fix works in production. ## Recommendation Looks reasonable — no blocking issues; the suggestion above is optional and can be addressed in a follow-up. <!-- pr-review:sha=d9f1d6cfc896e043e5b17280dde985cf1bc89237 -->
k.renner merged commit 05945545e8 into master 2026-08-19 04:46:26 +00:00
Sign in to join this conversation.