Routing Alerts To Specific SinksΒΆ
You can define routing-rules using a scope block.
A Basic ExampleΒΆ
To send high-severity alerts to Slack (and not other alerts), add a scope
to your slack sink:
sinksConfig:
- slack_sink:
name: test_sink
slack_channel: test-notifications
api_key: secret-key
scope:
include:
- severity: HIGH
See below for All Scope Options.
AND Between Two ConditionsΒΆ
More complex logic is possible. For example, we can match high-severity alerts from the prod
namespace:
sinksConfig:
- slack_sink:
name: test_sink
slack_channel: test-notifications
api_key: secret-key
scope:
include:
# AND between both conditions
- namespace: prod
severity: HIGH
Note that namespace and severity appear within a single YAML list element that starts with a dash (-
).
There is no dash (-
) character prior to severity
. (If this was written as - severity
then it would be treated as 2 separate conditions with an OR between them. See below.)
OR Between Two ConditionsΒΆ
If there are multiple list elements (each starting with -
) inside the include
block, they are combined with OR logic:
sinksConfig:
- slack_sink:
name: prod_slack_sink
slack_channel: prod-notifications
api_key: secret-key
scope:
# define 2 include elements, with an OR between them
include:
- namespace: default
- namespace: bla
You can combine AND syntax with OR syntax:
sinksConfig:
- slack_sink:
name: prod_slack_sink
slack_channel: prod-notifications
api_key: secret-key
scope:
# define 2 include elements, with an OR between them
include:
# this is a single include section. to match it, the alert's subject must be in namespace 'default' and have name 'foo'
- namespace: default
name: "foo"
# this is another include section. to match it, the alert's subject must be in namespace 'bla'
- namespace: bla
Exclusion RulesΒΆ
In addition to inclusion rules, you can add exclusion rules:
sinksConfig:
- slack_sink:
name: prod_slack_sink
slack_channel: prod-notifications
api_key: secret-key
scope:
# only include alerts from namespace default
include:
- namespace: default
exclude:
# regardless of the include sections, this will drop all alerts with name CrashLoopBackoff or ImagePullBackoff
- identifier: [CrashLoopBackoff, ImagePullBackoff]
The general rule is that an alert must match one of the include
sections, and must not match all the exclude
sections.
Special Syntax for Matching One of Many ValuesΒΆ
Each attribute can be a single value or a list of values:
sinksConfig:
- slack_sink:
name: test_sink
slack_channel: test-notifications
api_key: secret-key
scope:
include:
# here we use a list with a single value
- namespace: [prod]
# this is equivalent to the above
- namespace: prod
# this would match EITHER the namespace 'prod' OR the namespace 'default'
- namespace: [prod, default]
Using RegexesΒΆ
You can also use regexes:
sinksConfig:
- slack_sink:
name: test_sink
slack_channel: test-notifications
api_key: secret-key
scope:
include:
# this will match kube-system
- namespace: kube-.*
Using Kubernetes Label SelectorsΒΆ
You can match on Kubernetes label selectors with special syntax:
sinksConfig:
- slack_sink:
name: prod_slack_sink
slack_channel: prod-notifications
api_key: secret-key
scope:
include:
# label selectors are interpreted like Kubernetes - selectors separated by comma are ANDED together
- labels: "instance=1,foo!=x.*"
Tip
Using the Robusta UI, you can test alert routing by Simulating an alert.
All Scope OptionsΒΆ
Here is the complete list of attributes that can be used in include
/ exclude
sections:
title
: e.g.Crashing pod foo in namespace default
name
: the Kubernetes object namenamespace
: the Kubernetes object namespacenamespace_labels
: labels assigned to the namespace; matching these is done in the same way as matchinglabels
(see below)node
: the Kubernetes node nameseverity
: one ofINFO
,LOW
,MEDIUM
,HIGH
type
: one ofISSUE
,CONF_CHANGE
,HEALTH_CHECK
,REPORT
kind
: one ofdeployment
,node
,pod
,job
,daemonset
source
: one ofNONE
,KUBERNETES_API_SERVER
,PROMETHEUS
,MANUAL
,CALLBACK
identifier
: e.g.CrashLoopBackoff
labels
: A comma separated list ofkey=val
e.g.foo=bar,instance=123
annotations
: A comma separated list ofkey=val
e.g.app.kubernetes.io/name=prometheus
Note
labels
and annotations
are both the Kubernetes resource labels and annotations
(e.g. pod labels) and the Prometheus alert labels and annotations. If both contains the
same label/annotation, the value from the Prometheus alert is preferred.
Note
For performance reasons, the namespace information used for matching namespace_labels
is cached (with a default cache timeout of 30 minutes). If you change namespace labels
and want these changes to be immediately reflected in the sink scope
matching
mechanism, you will need to manually restart the Robusta runner.
How do I find the identifier
value to use in a match block? (deprecated)
For Prometheus alerts, it's always the alert name.
For custom playbooks, it's the value you set in create_finding under aggregation_key
.
Ask us in Slack if you need help.
When processing the scope
block, the following rules apply:
If the notification is excluded by any of the sink
scope
excludes - drop itIf the notification is included by any of the sink
scope
includes - accept itIf the notification is included by any of the sink
matchers
(deprecated) - accept it
Any of (but not both) of the include
and exclude
may be left undefined or empty.
An undefined/empty include
section will effectively allow all alerts, and an
undefined/empty exclude
section will not exclude anything.
Inside the include
and exclude
section, at the topmost level, the consecutive
items act with the OR logic, meaning that it's enough to match a single item in the
list in order to allow/reject a message. The same applies to the items listed under
each attribute name.
Within a specific labels
or annotations
expression, the logic is AND
....
scope:
include:
- labels: "instance=1,foo=x.*"
.....
The above requires that the instance
will have a value of 1
AND the foo
label values starts with x
Fall-through routingΒΆ
Sinks are matched in the order they are defined in generated_values.yaml
.
To prevent sending alerts to more sinks after the current one matches, you can specify stop: true
in the sink.
sinksConfig:
- slack_sink:
name: production_sink
slack_channel: production-notifications
api_key: secret-key
scope:
include:
- namespace: production
stop: true
# because the previous sink sets stop: true, this sink will only receive alerts not matched by the previous sink
- slack_sink:
name: non_production_sink
slack_channel: non-production-notifications
api_key: secret-key
Alternative Routing MethodsΒΆ
For customPlaybooks, there is another option for routing notifications.
Instead of using sink matchers, you can set the sinks attribute per playbook:
customPlaybooks:
- triggers:
- on_job_failure: {}
actions:
- create_finding:
aggregation_key: "JobFailure"
title: "Job Failed"
- job_info_enricher: {}
- job_events_enricher: {}
- job_pod_enricher: {}
sinks:
- "some_sink"
- "some_other_sink"
Notifications generated this way are sent exclusively to the specified sinks. They will still be filtered by matchers.
If you use this method, you can set default: false
in the sink definition and it will be ignored for all notifications except those from custom playbooks that explicitly name this sink.