前面的实战示例中,在 simple_demo.yml 的配置文件,配置内容如下:
groups: - name: simple_demo rules: - alert: test_alert expr: prometheus_http_requests_total{handler="/api/v1/targets"} > 5 for: 1m labels: level: critical annotations: description: "The node is Down more than 1 minute!" summary: "The node is down"
其中,"The node is Down more than 1 minute!" 和 "The node is down" 字符串将作为通知内容发送给警报接收器(如:短信,邮件、Webhook 等),当接收到通知后进行展示。我了让提示信息更友好和人性化,我们可以通过一个通知模板来定制更友好的通知信息。
在 Prometheus 创建并向 Alertmanager 发送警报,然后 Alertmanager 根据标签向不同的接收器发送通知,注意,接收器可以是 Slack、PagerDuty、email 或通过通用 Webhook 接口的自定义实现之一。
发送给接收方的通知是通过模板构建的,Alertmanager 自带默认模板,但也可以自定义。为避免混淆,需要注意的是 Alertmanager 模板与 Prometheus 中的模板不同,但 Prometheus 模板也包括警报规则标签/注释中的模板。
Alertmanager 的通知模板基于 Go 模板系统。请注意,有些字段以文本形式评估,有些则以 HTML 形式评估,这将影响转义。
data 是传递给通知模板和 webhook 推送的结构。如下表:
名称 | 类型 | 备注 |
Receiver | string | 定义发送通知的接收者名称(slack、电子邮件等)。 |
Status | string | 如果至少有一个警报正在触发,则定义为 firing,否则为 resolved。 |
Alerts | Alert | 该组中所有警报对象的列表。 |
GroupLabels | KV | 这些警报按标签分组。 |
CommonLabels | KV | 所有警报的共同标签。 |
CommonAnnotations | KV | 所有警报的通用注释集。用于更长的警报附加信息字符串。 |
ExternalURL | string | 发送通知的警报管理器的反向链接。 |
Alerts 类型提供了用于过滤警报的函数:
Alerts.Firing 返回该组中当前正在触发的警报对象列表
Alerts.Resolved 返回该组中已解决的警报对象列表
Alert 为通知模板保存一个警报。如下表:
名称 | 类型 | 备注 |
Status | string | 定义警报是否 resolved 或 firing。 |
Labels | KV | 一组附加到警报上的标签。 |
Annotations | KV | 一组警报注释。 |
StartsAt | time.Time | 警报开始发出的时间。如果省略,则由警报管理器指定当前时间。 |
EndsAt | time.Time | 仅在已知警报结束时间时设置。否则将设置为自上次收到警报起的可配置超时时间。 |
GeneratorURL | string | 一个反向链接,用于识别引起此警报的实体。 |
Fingerprint | string | 可用于识别警报的指纹。 |
KV 是一组键/值字符串对,用于表示标签和注释。如下:
type KV map[string]string
包含两个注释的注释示例:
{ summary: "alert summary", description: "alert description", }
除了直接访问存储为 KV 的数据(标签和注释)外,还有一些方法可以对 LabelSets 进行排序、删除和查看。
名称 | 参数 | 返回值 | 备足 |
SortedPairs | - | Pairs (键/值字符串对列表) | 返回键/值对的排序列表。 |
Remove | []string | KV | 返回不含给定键值的键/值映射的副本。 |
Names | - | []string | 返回 LabelSet 中的标签名称。 |
Values | - | []string | 返回 LabelSet 中值的列表。 |
请注意 Go 模板也提供了默认函数。
名称 | 参数 | 返回值 |
title | string | strings.Title,大写每个单词的第一个字符。 |
toUpper | string | strings.ToUpper, 将所有字符转换为大写字母。 |
toLower | string | strings.ToLower, 将所有字符转换为小写。 |
trimSpace | string | strings.TrimSpace, 删除前导空格和尾部空格。 |
match | pattern, string | Regexp.MatchString 使用 Regexp 匹配字符串。 |
reReplaceAll | pattern, replacement, text | Regexp.ReplaceAllString,Regexp 替换,未锚定。 |
join | sep string, s []string | strings.Join, 将 s 的元素连接成一个字符串。分隔符字符串 sep 放在生成字符串的元素之间。(注:参数顺序颠倒是为了便于在模板中流水线操作)。 |
safeHtml | text string | html/template.HTML, 将字符串标记为无需自动换码的 HTML 字符串。 |
stringSlice | ...string | 以字符串片段的形式返回传递的字符串。 |
以下是警报的所有不同示例,以及相应的 Alertmanager 配置文件设置 (alertmanager.yml)。每个示例都使用 Go 模板系统。
在本例中,我们自定义了 Slack 通知,以发送一个 URL 到我们组织的维基站点,说明如何处理已发送的特定警报。如下:
global: # 也可以将此URL放在文件中。 # 例如: `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 }}'
上述配置中的 “text”中的模板中的“{{ .GroupLabels.app }}”和“{{ .GroupLabels.alertname }}”将会进行动态替换,类似 Spring 中 ${},起到占位符的作用,这样就可以构建一套动态模板,而不是将模板的内容写死。
在本例中,我们再次通过访问 Alertmanager 发送的数据的 CommonAnnotations 中存储的摘要和描述,自定义发送到 Slack 接收者的文本。
Alert(告警)
groups: - name: Instances rules: - alert: InstanceDown expr: up == 0 for: 5m labels: severity: page # Prometheus 模板适用于警报的注释和标签字段。 annotations: description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes." summary: "Instance {{ $labels.instance }} down"
修改配置后,报警示例如下图:
其中的 “{{ $labels.instance }}” 和 “{{ $labels.job }}”已经成功使用 Prometheus 向量的 instance 和 job 标签值替换了。
Receiver(接收器)
- name: 'team-x' slack_configs: - channel: '#alerts' # Alertmanager 模板适用于此处。 text: "<!channel> \nsummary: {{ .CommonAnnotations.summary }}\ndescription: {{ .CommonAnnotations.description }}"
最后,假定警报与上一个例子相同,我们自定义接收器,以覆盖从警报管理器收到的所有警报,并在新行中打印各自的注释摘要和说明。
Receiver(接收器)
- 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.text "的模板,内容如下:
{{ define "slack.myorg.text" }}https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}{{ end}}
注意,名为“slack.myorg.text”的模版将返回一个 URL 地址,该 URL 地址是一个 wiki 文档的 URL 地址,用来帮助用户解决产生的报警。
现在,配置会为 "text" 字段加载带有指定名称的模板,我们还提供了自定义模板文件的路径:
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'
配置完成后,重启 AlertManager 服务。