fix: stop controller error-ratio alerts flapping - #333
Open
aflor024 wants to merge 1 commit into
Open
Conversation
ControllerReconcileErrorRatio{High,Critical} fired and resolved on a loop
instead of latching, paging on-call roughly a hundred times a night for a
single unchanged fault. There are two independent causes, both measured on
prod.
A controller reconciling only a handful of objects leaves short windows with
no increments at all, so the denominator goes to zero, the ratio series
disappears and the alert resolves; the next reconcile restarts `for` and it
fires again. A 30-minute range keeps the series continuous at low volume.
A constant error rate against a variable success rate crosses the threshold in
both directions as unrelated healthy traffic rises and falls, with the
controller no healthier either way. `keep_firing_for` holds the alert through
those dilutions.
Key changes:
- Widen the ratio range to 30m and add `keep_firing_for: 30m`
- Group by cluster and namespace so the notification says where the failing
controller runs, not only which reconciler it was
- Cover both flap mechanisms in the promtool fixtures; each case fails
without its corresponding change
- Run `task test-prometheus-rules` in CI, which no workflow did before
- Record the orphaned-object error class in the runbook
Related to #326
|
|
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.
Summary
ControllerReconcileErrorRatioCriticalhas been firing and resolving on a loop rather than latching — roughly 100 fire/resolve pairs into#alerts-production-criticalin 14h for a single unchanged fault, and becauseseverity: criticalalso matches thegrafana-oncallroute, it pages on-call on every cycle. The underlying fault deserves one page, not a hundred.Measuring prod turned up two independent flap mechanisms, not one:
instance-projectorreconciles a median of 4 objects per 10 minutes. 28 of 85 windows contained no increments at all, so the denominator went to zero,0/0dropped the series, and Alertmanager resolved — then the next reconcile restartedfor: 10mand it fired again. It never once crossed back under the threshold (0 of 57 data-bearing windows), so this is not the ratio dipping. A 30-minute range keeps the series continuous at that volume.dnsrecordset-powerdnsand staginggatewaycase already described on ControllerReconcileErrorRatio flaps with unrelated traffic volume and omits the cluster #326.keep_firing_for: 30mholds the alert through those dips.Both changes are load-bearing and independently guarded: reverting the range fails the sparse fixture, and removing
keep_firing_forfails the dilution fixture.The sparse-series half is not only a noise fix. datum-cloud/infra#3742 diagnosed the same mechanism from the opposite end:
GrafanaAlertRuleGroup,GrafanaContactPoint,GrafanaFolderandGrafanaNotificationPolicyon prod reconcile about once every 15 minutes and have been failing 100% with zero successes for over 30 days, yetControllerReconcileErrorRatioCriticalsits permanently inpendingfor them and has never fired — a reconcile period longer than the evaluation window meansfor:resets on every reconcile and the rule cannot latch. Every alert-rule, contact-point and notification-routing change committed to Git in that window silently never reached Grafana. The 30-minute range is what makes that condition alertable at all, so the same change that quiets a flapping controller also surfaces a month-old silent failure.Warning
This raises the unalertable threshold from a 10-minute to a 30-minute reconcile period; it does not remove it. A controller reconciling less often than every 30 minutes is still invisible to this rule. The general class infra#3742 describes stays open.
Grouping now includes
clusterandnamespace, so a page says where the failing controller runs instead of only naming the reconciler — #326's second ask.Note
The rule still has no job or namespace selector, so it evaluates every controller-runtime binary scraped into the cluster. That is how an
nso-slo-owned alert ends up paging aboutinstance-projector, which runs incompute-system. Scoping it to NSO would strand the controllers above with no coverage at all, so that ownership question is left open on #326 rather than settled here.The fault behind the current pages is dead data, not an outage — 3 orphaned Instances in one project namespace, tracked as datum-cloud/compute#194. This PR stops the paging pattern; it does not clean those up.
task test-prometheus-ruleswas not referenced by any workflow, so the fixtures this issue asks for would not have guarded anything. Added a job that runs them.Test plan
task test-prometheus-rules— all three suites pass10mkeep_firing_foris removedpromtoolconfirms a held alert retains its last annotations, and that the hold is bounded (resolves oncekeep_firing_forlapses)Related to #326