告警概述

Prometheus的告警分为两部分。Prometheus服务器中的告警规则会将告警发送给一个Alertmanager。Altermanager管理这些告警,包括静默( silencing)、抑制(inhibition)、聚合(aggregation)以及通过电子邮件、呼叫通知系统和聊天平台等方式发送通知。

设置报警和通知的主要步骤如下:

  1. 设置和配置 Alertmanager
  2. 配置 Prometheus 与 Alertmanager 进行通信。
  3. 在 Prometheus 中创建告警规则

Alertmanager

Alertmanager通过客户端应用程序处理告警,例如Prometheus服务器。它负责去重,分组和路由他们到正确的接收方集成,例如email,PageDuty或者OpsGenie。它还负责告警的静默和抑制。

下面的内容描述了Alertmanager的实现。查阅配置文档获取学习如何使用它们的更多详情

分组(Grouping)

分组将享受性质的告警分类到同一个通知下。这在大规模停机的情况下尤为好用,因为在许多系统同时发生故障时,成百上千的告警可能会被同时触发。

示例:当一个网络分区发生时,一个服务的几十个或者上百个实例运行在你的集群上。半数你的服务实例不能连接到数据库。Prometheus上的告警规则被设置成如果存在一个实例不能连接数据就发送一个告警。结果,上百个告警被发送给Alertmanager。

作为一个用户,只想得到一个可以准确地看到哪些服务被影响的单独的页面。因此人们可以设置Alertmanager去根据他们的集群或者告警名分类告警,来发送一个紧凑的通知。

告警的分组、已分组的通知的定时以及这些通知的接收者由配置文件中的路由树进行配置。

抑制(Inhibition)

抑制是指某些已经触发的告警,禁止这些告警发出通知的概念。

示例:一个正在的触发,告警通知无法到达整个集群。Alertmanager可以设置为,如果有特定的告警正在触发,与这个集群有关的其他告警静音。这会阻止成百上千正在触发但与实际问题无关的告警通知。

抑制可以通过Alertmanager的配置文件进行配置。

静默(Silences)

静默就是在给定时间内简单地静音告警的一个直接方式。静默是基于匹配器配置的,就像路由树一样。传入的告警会被检查他们是否与启用的静默(规则)的所有相等符或者正则表达式匹配器相匹配。如果它们匹配上,这个告警就不会有发出通知。

静默在Alertmanger的web界面中设置。

客户端行为

Alertmanager对其客户端行为有一些特殊依赖。这些仅与Prometheus不用于发送告警的高级用例相关。

高可用性

Alertmanager支持通过配置去创建一个高可用集群。这可以使用 —cluster-* 标签来配置。

重要的是不要在Prometheus及其Alertmanager之间进行流量负载平衡,而是将Prometheus指向所有Alertmanager的列表。

配置

Alertmanager 是通过命令行标志和配置文件进行配置的。命令行标志配置不可变的系统参数,而配置文件定义了抑制规则(inhibition rules)、通知路由notification routing)和通知接收器(notification receivers)。

可视化编辑器 可以帮助构建路由树(routing trees)。

要查看所有可用的命令行标志,请运行alertmanager -h

Alertmanager 可以在运行时重新加载其配置。如果新配置的格式不正确,则不会应用更改并记录错误。通过向进程发送 SIGHUP 或者向 /-/reload 端点发送 HTTP POST 请求可以触发重新加载配置。

配置文件

官方文档有详细介绍,自行按需查阅Configuration | Prometheus

客户端

官方的免责声明强烈建议大家基于时间序列数据配置告警规则,而不是基于客户端。

Disclaimer: Prometheus automatically takes care of sending alerts generated by its configured alerting rules. It is highly recommended to configure alerting rules in Prometheus based on time series data rather than implementing a direct client.

所以这部分内容,大家感兴趣的话,可以自行查阅Clients | Prometheus

通知模板参考

Prometheus 创建告警并将其发送到Alertmanager,然后Alertmanager根据其标签(label)将通知发送到不同的接收者。 接收器可以是许多集成之一,包括:Slack,PagerDuty,电子邮件或通过通用Webhook界面的自定义集成。

发送给接收方的通知是通过模板构建的。Alertmanager附带默认模板,但也可以自定义它们。 为避免混淆,请务必注意,Alertmanager模板与 Prometheus的模板 不同,但 Prometheus 模板同样包括告警规则中的标签/注释(labels/annotations)中的模板。

Alertmanager的通知模板基于 Go 模板系统。 请注意,某些字段被评估为文本,而另一些字段则被评估为 HTML,这将影响转义。

日期结构

Data

Data是传递给通知模板和webhook推送的结构

Name Type Notes
Receiver(接收者) string 定义了会收到通知的接收者名称(slack, email等等)。
Status(状态) string 如果至少有一个告警正在触发,则定义为触发(firing),否则定义为已解决(resolved)
Alerts(告警) Alert 此组中所有告警对象的列表 (见下文).
GroupLabels(分组标签) KV 用于告警分组的分组标签
CommonLabels(通用标签) KV 所有告警都适用的通用标签
CommonAnnotations(通用注解) KV 所有告警的通用注释集。用于为告警携带更长的信息字符串。
ExternalURL(外部URL) string 发送通知的Alertmanager的反向链接。

用于筛选告警的函数:Alerts

  • Alerts.Firing返回此组中当前触发的告警对象的列表
  • Alerts.Resolved返回此组中已解决的告警对象的列表

Alert

Alert 为通知模板保留了一个告警

Name Type Notes
Status(状态) string 定义一个告警
Labels(标签) KV 要附加到告警的一组标签。
Annotations(注解) KV 告警的一组注解。
StartsAt(开始时间) time.Time 告警开始触发的时间。如果省略,则当前时间由Alertmanager分配。
EndsAt(结束时间) time.Time 仅当告警的结束时间已知时设置。否则,设置为自上次收到告警以来的可配置超时时间。
GeneratorURL(生成者URL) string 一个反向链接,用于识别引起该告警的实体。
Fingerprint(指纹) string 可用于识别告警的指纹。

KV

KV是一组键/值字符串对,用于表示标签和注解。

1
type KV map[string]string

包含两个注解的注解示例:

1
2
3
4
{
summary: "alert summary",
description: "alert description",
}

除了直接访问存储为 KV 的数据(标签和注解)之外,还有排序、删除和查看标签集的方法:

KV 方法

Name Arguments Returns Notes
SortedPairs - Pairs (list of key/value string pairs.) 返回键值对的排序列表。
Remove []string KV 返回不包含指定键的键值对的映射副本
Names - []string 返回标签集中标签名称的名称。
Values - []string 返回标签集中的值的列表。

函数

注意 默认函数 同样由Go templating提供

Strings

Name Arguments Returns Notes
title string strings.Title, capitalises first character of each word.
toUpper string strings.ToUpper, 将所有字符转换为大写。
toLower string strings.ToLower, 将所有字符转换为小写。
match pattern, string Regexp.MatchString.使用正则表达式匹配一个字符串。
reReplaceAll pattern, replacement, text Regexp.ReplaceAllString 未锚定的正则表达式替换。
join sep string, s []string strings.Join, 函数用于将字符串切片s中的每个元素拼接为一个字符串,并使用分隔符sep将它们分隔开来。最终生成的字符串就是每个元素拼接后的结果,其中每个元素之间被分隔符分隔。 注意:参数顺序颠倒是为了在模板中更方便地使用管道。
safeHtml text string html/template.HTML, 将字符串标记为不需要自动转义的 HTML。
stringSlice …string 以字符串切片的形式返回传递的字符串。

通知模板示例

以下是告警和相应的alertmanager配置文件设置(alertmanager.yml)的所有不同示例。 每个都使用 Go 模板系统。

自定Slack通知

在此示例中,我们自定义了 Slack 通知,以向组织的 wiki 发送一个 URL,说明如何处理已发送的特定告警。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
global:
# Also possible to place this URL in a file.
# Ex: `slack_api_url_file: '/etc/alertmanager/slack_url'`
slack_api_url: '<slack_webhook_url>'

route:
receiver: 'slack-notifications'
group_by: [alertname, datacenter, app]

receivers:
- name: 'slack-notifications'
slack_configs:
- channel: '#alerts'
text: 'https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}'

访问CommonAnnotations的注释

在此示例中,我们再次自定义发送到 Slack 的文本,访问CommonAnnotations中存储的alertmanager发送的数据的summarydescription

Alert

1
2
3
4
5
6
7
8
9
10
11
12
groups:
- name: Instances
rules:
- alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: page
# Prometheus templates apply here in the annotation and label fields of the alert.
annotations:
description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.'
summary: 'Instance {{ $labels.instance }} down'

Receiver

1
2
3
4
5
- name: 'team-x'
slack_configs:
- channel: '#alerts'
# Alertmanager templates apply here.
text: "<!channel> \nsummary: {{ .CommonAnnotations.summary }}\ndescription: {{ .CommonAnnotations.description }}"

遍历所有接收到的警报

最后,假设与前一个示例相同的警报,我们自定义接收器以遍历从Alertmanager接收到的所有警报,并在新行上打印其各自的注解摘要和描述。

Receiver

1
2
3
4
5
- name: 'default-receiver'
slack_configs:
- channel: '#alerts'
title: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}"
text: "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}"

定义可重用模板

回到我们的第一个示例,我们还可以提供一个包含命名模板的文件,然后由 Alertmanager 加载这些模板,以避免跨越多行的复杂模板。 在/alertmanager/template/myorg.tmpl下面创建一个文件,并在其中创建一个名为“slack.myorg.txt”的模板:

1
{{ define "slack.myorg.text" }}https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}{{ end}}

配置现在使用“text”字段的给定名称加载模板,并提供自定义模板文件的路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
global:
slack_api_url: '<slack_webhook_url>'

route:
receiver: 'slack-notifications'
group_by: [alertname, datacenter, app]

receivers:
- name: 'slack-notifications'
slack_configs:
- channel: '#alerts'
text: '{{ template "slack.myorg.text" . }}'

templates:
- '/etc/alertmanager/templates/myorg.tmpl'

此示例将在此博客文章中进一步详细解释。

管理 API

Alertmanager 提供了一系列管理API(management API )来简化自动化和集成。

健康检查

1
2
GET /-/healthy
HEAD /-/healthy

此端点(endpoint)始终返回 200,应用于检查警报管理器运行状况。

准备情况检查

1
2
GET /-/ready
HEAD /-/ready

当警报管理器准备好提供流量(即响应查询)时,此端点返回 200。

重新加载

1
POST /-/reload

此端点触发警报管理器配置文件的重新加载。

触发配置重新加载的另一种方法是向警报管理器进程发送 。SIGHUP

HTTPS和身份验证

Alertmanager支持基本身份验证和TLS。 这是实验性的,并可能在未来发生变化。

目前,TLS支持HTTP流量和gossip流量。

HTTP 流量

要指定要加载的 Web 配置文件,请使用--web.config.file标签。

该文件以 YAML 格式编写, 由下面描述的方案定义。括号表示参数是可选的。对于非列表参数,该值设置为指定的默认值。

每次http请求都会读取该文件,例如配置中的任何更改和证书立即获取。

通用占位符的定义如下:

  • <boolean>: 可以取值的布尔值truefalse
  • <filename>: 当前工作中的目录的合法路径
  • <secret>: 作为Secret的常规字符串,例如密码
  • <string>: 常规字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
tls_server_config:
# Certificate and key files for server to use to authenticate to client.
cert_file: <filename>
key_file: <filename>

# Server policy for client authentication. Maps to ClientAuth Policies.
# For more detail on clientAuth options:
# https://golang.org/pkg/crypto/tls/#ClientAuthType
#
# NOTE: If you want to enable client authentication, you need to use
# RequireAndVerifyClientCert. Other values are insecure.
[ client_auth_type: <string> | default = "NoClientCert" ]

# CA certificate for client certificate authentication to the server.
[ client_ca_file: <filename> ]

# Minimum TLS version that is acceptable.
[ min_version: <string> | default = "TLS12" ]

# Maximum TLS version that is acceptable.
[ max_version: <string> | default = "TLS13" ]

# List of supported cipher suites for TLS versions up to TLS 1.2. If empty,
# Go default cipher suites are used. Available cipher suites are documented
# in the go documentation:
# https://golang.org/pkg/crypto/tls/#pkg-constants
#
# Note that only the cipher returned by the following function are supported:
# https://pkg.go.dev/crypto/tls#CipherSuites
[ cipher_suites:
[ - <string> ] ]

# prefer_server_cipher_suites controls whether the server selects the
# client's most preferred ciphersuite, or the server's most preferred
# ciphersuite. If true then the server's preference, as expressed in
# the order of elements in cipher_suites, is used.
[ prefer_server_cipher_suites: <bool> | default = true ]

# Elliptic curves that will be used in an ECDHE handshake, in preference
# order. Available curves are documented in the go documentation:
# https://golang.org/pkg/crypto/tls/#CurveID
[ curve_preferences:
[ - <string> ] ]

http_server_config:
# Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS.
# This can not be changed on the fly.
[ http2: <boolean> | default = true ]
# List of headers that can be added to HTTP responses.
[ headers:
# Set the Content-Security-Policy header to HTTP responses.
# Unset if blank.
[ Content-Security-Policy: <string> ]
# Set the X-Frame-Options header to HTTP responses.
# Unset if blank. Accepted values are deny and sameorigin.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
[ X-Frame-Options: <string> ]
# Set the X-Content-Type-Options header to HTTP responses.
# Unset if blank. Accepted value is nosniff.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
[ X-Content-Type-Options: <string> ]
# Set the X-XSS-Protection header to all responses.
# Unset if blank.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
[ X-XSS-Protection: <string> ]
# Set the Strict-Transport-Security header to HTTP responses.
# Unset if blank.
# Please make sure that you use this with care as this header might force
# browsers to load Prometheus and the other applications hosted on the same
# domain and subdomains over HTTPS.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
[ Strict-Transport-Security: <string> ] ]

# Usernames and hashed passwords that have full access to the web
# server via basic authentication. If empty, no basic authentication is
# required. Passwords are hashed with bcrypt.
basic_auth_users:
[ <string>: <secret> ... ]

Gossip 流量

要指定是否对 gossip使用双向 TLS,请使用--cluster.tls-config标签。

gossip服务器端和客户端是可配置的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
tls_server_config:
# Certificate and key files for server to use to authenticate to client.
cert_file: <filename>
key_file: <filename>

# Server policy for client authentication. Maps to ClientAuth Policies.
# For more detail on clientAuth options:
# https://golang.org/pkg/crypto/tls/#ClientAuthType
[ client_auth_type: <string> | default = "NoClientCert" ]

# CA certificate for client certificate authentication to the server.
[ client_ca_file: <filename> ]

# Minimum TLS version that is acceptable.
[ min_version: <string> | default = "TLS12" ]

# Maximum TLS version that is acceptable.
[ max_version: <string> | default = "TLS13" ]

# List of supported cipher suites for TLS versions up to TLS 1.2. If empty,
# Go default cipher suites are used. Available cipher suites are documented
# in the go documentation:
# https://golang.org/pkg/crypto/tls/#pkg-constants
[ cipher_suites:
[ - <string> ] ]

# prefer_server_cipher_suites controls whether the server selects the
# client's most preferred ciphersuite, or the server's most preferred
# ciphersuite. If true then the server's preference, as expressed in
# the order of elements in cipher_suites, is used.
[ prefer_server_cipher_suites: <bool> | default = true ]

# Elliptic curves that will be used in an ECDHE handshake, in preference
# order. Available curves are documented in the go documentation:
# https://golang.org/pkg/crypto/tls/#CurveID
[ curve_preferences:
[ - <string> ] ]

tls_client_config:
# Path to the CA certificate with which to validate the server certificate.
[ ca_file: <filepath> ]

# Certificate and key files for client cert authentication to the server.
[ cert_file: <filepath> ]
[ key_file: <filepath> ]

# Server name extension to indicate the name of the server.
# http://tools.ietf.org/html/rfc4366#section-3.1
[ server_name: <string> ]

# Disable validation of the server certificate.
[ insecure_skip_verify: <boolean> | default = false]