Skip to content

Ruler: retry notifications the Alertmanager failed to accept - #7909

Open
yeya24 wants to merge 1 commit into
cortexproject:masterfrom
yeya24:ruler-notification-retry
Open

yeya24 wants to merge 1 commit into
cortexproject:masterfrom
yeya24:ruler-notification-retry

Conversation

@yeya24

@yeya24 yeya24 commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does:

The Prometheus notifier the ruler embeds does not retry. sendOne calls the Do
option once, and the caller only logs the error and adds to the error counter
before moving on to the next batch, so a notification the Alertmanager fails to
accept is dropped: its alert is not delivered until the rule group is evaluated
again.

Two of those failures recover on a second attempt, and both are routine when the
ruler keeps connections alive to the Alertmanager:

  • The Alertmanager closes a connection it considers idle just as the ruler reuses
    it for a POST, and the ruler logs error occurred while sending alerts ... EOF.
    The notifier client's IdleConnTimeout is independent of the server's idle
    timeout, so the race repeats for as long as both are running. This is Ruler reports an error EOF when sending alert to alertmanager #4958,
    also reported in cortex ruler send alert to alertmanager ERROR EOF #3009 and asked about in Guidance on Ruler -> AlertManager intermittent reachability #4355.
  • A Cortex Alertmanager that received SIGTERM replies 503 for as long as its ring
    final_sleep lasts, because MultitenantAlertmanager.ServeHTTP returns early
    while the service is not Running (pkg/alertmanager/multitenant.go) and does
    not forward the alerts to another replica. A keep-alive connection pinned to
    that instance keeps getting 503 until it is replaced, even though healthy
    replicas are behind the same address.

This PR retries such a notification instead of dropping it:

  • A transport error, except one caused by the context being cancelled or its
    deadline being exceeded, and a 5xx response are retried. A 4xx response is not:
    the Alertmanager rejects the request however many times it is sent.
  • The idle connections of the tenant's client are closed before a retry, so the
    attempt opens a new connection. That is also how it reaches another instance
    when the Alertmanagers are behind a load balancer.
  • The request body is rebuilt from GetBody on every attempt. POST /api/v2/alerts
    is idempotent, the Alertmanager merges the alerts by fingerprint.
  • The retries are bounded by the context of the notification, which carries
    -ruler.notification-timeout, and they delay the other notifications of the same
    tenant, which is why the flag description asks for a small number.

Configuration

Disabled by default, so nothing changes unless it is configured:

Flag Default
-ruler.notification.backoff-retries 0, the retries are disabled
-ruler.notification.backoff-min-period 100ms
-ruler.notification.backoff-max-period 1s

A new per-user counter, cortex_ruler_notification_retries_total, counts the
retried notifications.

One thing worth a look in review: the config reuses backoff.Config, but
max_retries = 0 disables the retries here instead of making them infinite, so
that the default does not change the behaviour of the ruler. transport.Retry
reads a retry count the same way. That is why the three flags are registered with
their own descriptions instead of calling backoff.Config.RegisterFlagsWithPrefix,
which would default the count to 10 and document it as the generic backoff count.
Happy to move to a separate -ruler.notification-retry-enabled flag and leave
backoff.Config with its usual semantics if that reads better.

Which issue(s) this PR fixes:
Related to #4958

Checklist

  • Tests updated
  • Documentation added
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]
  • docs/configuration/v1-guarantees.md updated if this PR introduces experimental flags

@yeya24
yeya24 requested a review from a team as a code owner November 2, 2026 05:54
@yeya24
yeya24 requested a review from danielblando November 2, 2026 05:54
@yeya24 yeya24 changed the title Ruler: add experimental retries for failed notifications Ruler: retry notifications the Alertmanager failed to accept Nov 2, 2026
The Prometheus notifier does not retry: it logs the error returned by the
Do option and moves on to the next batch, so a notification the
Alertmanager failed to accept is dropped and its alert is not delivered
until the rule group is evaluated again. Two of those failures recover on
a second attempt: the Alertmanager closing a keep-alive connection it
considers idle just as the ruler reuses it, and an Alertmanager replying
503 while it shuts down with the connection still pinned to it.

Retry a notification that failed with a transport error or a 5xx
response, up to -ruler.notification.backoff-retries times, dropping the
idle connections of the tenant's client first so that the next attempt
opens a new connection. A 4xx response is not retried, the Alertmanager
rejects the request however many times it is sent.

The retries are disabled by default, so the behaviour does not change
unless they are configured, and they are always bounded by the context of
the notification, which carries -ruler.notification-timeout.

Signed-off-by: Ben Ye <benye@amazon.com>
@yeya24
yeya24 force-pushed the ruler-notification-retry branch from 18898aa to 67a4614 Compare November 2, 2026 06:39

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants