原文略有刪節
告警概述
Prometheus 的告警分爲兩部分。Prometheus server 內的告警規則將告警發送到 Alertmanager,後者處理這些告警,包括沉默、抑制、聚合以及通過郵件、在線通知系統和即時通訊工具等方法發送通知。
設置告警和通知的主要步驟如下:
- 設定和配置 Alertmanager
- 配置 Prometheus 與 Alertmanager 通信
- 在 Prometheus 中創建告警規則
ALERTMANAGER
Alertmanager 處理客戶端程序如 Prometheus server 發送來的告警。它負責將告警去重、分組和路由到正確的接收者例如郵件、網頁等。它也負責沉默和抑制告警。
下面介紹 Alertmanager 的核心概念。查閱配置文件以更詳細地瞭解其使用方法。
告警歸組(Grouping)
歸組將性質相似地告警歸爲一個通知。當發生大規模斷電導致很多系統同時掛掉從而引發海量告警的時候這個功能尤爲有效。
**示例:**你的集羣運行着一個服務的成百上千個實例,當發生網絡分區時,一半的服務實例連不上數據庫了。Prometheus 的告警規則設置爲每個服務實例發送一條告警。結果成百上千的告警發送至 Alertmanager。
作爲一個用戶,你希望只收到一條信息,裏面包含了受影響的具體的服務實例。這樣你可以配置 Alertmanager 將告警按照集羣名稱和告警名稱歸組,它就可以只發送一條通知了。
告警歸組,各告警組的通知時間以及各告警組的通知接收者都在配置文件的路由樹中進行配置。
告警抑制
告警抑制是指如果發生了某些告警,就將特定的告警壓制。
**示例:**一個告知整個集羣失聯的告警觸發了。可以配置 Alertmanager,將有關該集羣的所有告警都不報了。這樣可以防止觸發與實際問題無關的成百上千個告警通知。
告警抑制在 Alertmanager 的配置文件中進行配置。
告警沉默
告警沉默就是直接將告警停報一段時間。告警沉默的配置基於匹配器,類似路由樹。檢查傳入的告警是否與告警沉默設置的正則表達式匹配。如果匹配,就不發送告警通知。
告警沉默在 Alertmanager 的 web 界面進行配置。
客戶端行爲
Alertmanager 對客戶端的行爲有特殊的要求。這些僅與不使用Prometheus發送警報的高級用例有關。
高可用
Alertmanager 支持配置高可用集羣。可以通過使用 --cluster-* 參數進行配置。
不要在 Prometheus 和 Alertmanager 之間進行負載均衡,而是在 Prometheus 中指定全部 Alertmanager 的列表。
配置
Alertmanager 通過命令行參數和配置文件進行配置。命令行參數配置不變的系統參數,配置文件定義抑制規則、通知路由和通知接收者。
可視化編輯器可以協助構建路由樹。
運行 alertmanager -h
瀏覽可用的命令行參數。
Alertmanager 可以在運行時重新加載配置文件。如果新的配置文件格式不對,變更就不會被應用並且將錯誤記錄爲日誌。通過向進程發送 SIGHUP
或者發送 HTTP POST 請求到 /-/reload
端點。
配置文件
通過 --config.file
參數指定加載的配置文件。
./alertmanager --config.file=alertmanager.yml
文件爲 YAML 格式,由以下格式定義。括號代表參數時可選的。未列出的參數設爲默認值。
通用佔位符定義如下:
<duration>: 時長,匹配的正則表達式 [0-9]+(ms|[smhdwy])
<labelname>: 匹配 [a-zA-Z_][a-zA-Z0-9_]* 正則表達式的字符串
<labelvalue>: unicode 字符組成的字符串
<filepath>: 當前工作目錄中的有效路徑
<boolean>: 布爾值, true 或者 false
<string>: 標準字符串
<secret>: 一個密文的標準字符串,例如密碼
<tmpl_string>: 模板格式化的字符串
<tmpl_secret>: 模板格式化的密文字符串
其他佔位符單獨說明。
全局配置設置在整個配置中生效的參數。它們也作爲其他配置段的默認值。
global:
# 配置郵件接收者
# The default SMTP From header field.
[ smtp_from: <tmpl_string> ]
# The default SMTP smarthost used for sending emails, including port number.
# Port number usually is 25, or 587 for SMTP over TLS (sometimes referred to as STARTTLS).
# Example: smtp.example.org:587
[ smtp_smarthost: <string> ]
# The default hostname to identify to the SMTP server.
[ smtp_hello: <string> | default = "localhost" ]
# SMTP Auth using CRAM-MD5, LOGIN and PLAIN. If empty, Alertmanager doesn't authenticate to the SMTP server.
[ smtp_auth_username: <string> ]
# SMTP Auth using LOGIN and PLAIN.
[ smtp_auth_password: <secret> ]
# SMTP Auth using PLAIN.
[ smtp_auth_identity: <string> ]
# SMTP Auth using CRAM-MD5.
[ smtp_auth_secret: <secret> ]
# The default SMTP TLS requirement.
# Note that Go does not support unencrypted connections to remote SMTP endpoints.
[ smtp_require_tls: <bool> | default = true ]
# 配置微信等 api 接收者
# The API URL to use for Slack notifications.
[ slack_api_url: <secret> ]
[ victorops_api_key: <secret> ]
[ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ]
[ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ]
[ opsgenie_api_key: <secret> ]
[ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ]
[ hipchat_api_url: <string> | default = "https://api.hipchat.com/" ]
[ hipchat_auth_token: <secret> ]
[ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ]
[ wechat_api_secret: <secret> ]
[ wechat_api_corp_id: <string> ]
# 配置網頁接收者
# The default HTTP client configuration
[ http_config: <http_config> ]
# 如果告警沒有設置結束時間,ResolveTimeout 是 alertmanager 的默認值,
# 過了這段時間,如果告警沒有更新,就被聲明未恢復了。
# 這和 Prometheus 的告警不衝突,因爲它們都設置了結束時間。
[ resolve_timeout: <duration> | default = 5m ]
# Files from which custom notification template definitions are read.
# The last component may use a wildcard matcher, e.g. 'templates/*.tmpl'.
templates:
[ - <filepath> ... ]
# 路由樹的根節點。
route: <route>
# 接收者列表。
receivers:
- <receiver> ...
# 抑制規則列表。
inhibit_rules:
[ - <inhibit_rule> ... ]
一個路由塊定義了路由樹中的一個結點和它的子節點。它的可選配置如果沒設就默認繼承它的父節點的配置。
每個告警從配置的頂層路由進入路由樹,頂層路由匹配所有告警。然後遍歷子結點。如果 continue
設置未 false,它就終結在第一個匹配的結點,如果一個匹配的結點的 continue
是 ture,告警就繼續匹配隨後的兄弟結點。如果一個告警不匹配一個結點的任何子節點,告警就基於當前結點的配置參數進行處理。
[ receiver: <string> ]
# 對告警進行歸組的標籤。例如 cluster=A 和 alertname=LatencyHigh
# 的多個告警被歸爲一組。
# 要按所有標籤聚合,使用 “...”作爲標籤,例如:
# group_by: ['...']
# 這樣就禁用了歸組功能。
[ group_by: '[' <labelname>, ... ']' ]
# 告警是否繼續匹配兄弟結點。
[ continue: <boolean> | default = false ]
# 一個告警要匹配結點所要匹配的相等匹配器集合。
match:
[ <labelname>: <labelvalue>, ... ]
# 一個告警要匹配結點所要匹配的正則匹配器集合。
match_re:
[ <labelname>: <regex>, ... ]
# 一組告警在發送通知前等待的時間,這段時間用於等待抑制告警到達
# 或者收集更多的同組告警。(通常是0s~數分鐘)
[ group_wait: <duration> | default = 30s ]
# 發送一次告警後,等待多久再發送同組新增的告警。(通常 5m 或更久)
[ group_interval: <duration> | default = 5m ]
# 一個告警發送後等待多久再次發送。(通常 3h 或更久)
[ repeat_interval: <duration> | default = 4h ]
# 0 或多個子路由。
routes:
[ - <route> ... ]
示例
# 包含全部參數的根路由,如果子路由沒設置相應參數就繼承自此。
route:
receiver: 'default-receiver'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
group_by: [cluster, alertname]
# 不匹配下面子路由的所有告警將終止在根節點併發送到 'default-receiver'。
routes:
# 所有 service=mysql 或 service=cassandra 的告警
# 發送到 database-pager。
- receiver: 'database-pager'
group_wait: 10s
match_re:
service: mysql|cassandra
# 具有 team=frontend 標籤的告警匹配這個子路由。
# 它們根據 product 和 environment 歸組而不根據 cluster
# 和 alertname。
- receiver: 'frontend-pager'
group_by: [product, environment]
match:
team: frontend
<inhibit_rule>
告警抑制規則設置當匹配一組匹配器的源告警發出後,停止發送匹配某些匹配器的目標告警。源告警和目標告警必須具有 equal
列表中列出的相同的標籤值。
語義上,缺失的標籤和空值標籤是一個意思。因此,如果源告警和目標告警確實 equal
列表中列舉的所有標籤的話,告警抑制規則就會被應用。
爲了防止一個告警抑制它自己,同時匹配一條規則的源和目標的告警不能被任何告警抑制(包括它自己)。儘管如此,建議在設置源和目標匹配器時確保沒有同時匹配的可能性。
# 告警被抑制所必須滿足的匹配器。
target_match:
[ <labelname>: <labelvalue>, ... ]
target_match_re:
[ <labelname>: <regex>, ... ]
# 存在滿足如下匹配器的一個或多個告警的話,
# 告警抑制就生效。
source_match:
[ <labelname>: <labelvalue>, ... ]
source_match_re:
[ <labelname>: <regex>, ... ]
# 源和目標告警的如下標籤值中至少有一個相等
# 告警抑制才能生效。
[ equal: '[' <labelname>, ... ']' ]
<http_config>
http_config
配置接收者與基於 HTTP API 的服務進行通信的 HTTP 客戶端。
# 注意 `basic_auth`, `bearer_token` 和 `bearer_token_file` 選項時互斥的。
# Sets the `Authorization` header with the configured username and password.
# password and password_file are mutually exclusive.
basic_auth:
[ username: <string> ]
[ password: <secret> ]
[ password_file: <string> ]
# 用 bare token 配置 `Authorization` 請求頭。
# password 和 password_file 是互斥的。
[ bearer_token: <secret> ]
# 從配置文件讀取 bare token 配置 `Authorization`。請求頭
[ bearer_token_file: <filepath> ]
# 配置 TLS 設置。
tls_config:
[ <tls_config> ]
# 可選的代理 URL。
[ proxy_url: <string> ]
<tls_config>
配置 TLS 連接
# CA certificate to validate the server certificate with.
[ ca_file: <filepath> ]
# Certificate and key files for client cert authentication to the server.
[ cert_file: <filepath> ]
[ key_file: <filepath> ]
# ServerName 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]
接收器是一個或多個通知集成的命名配置。
我們沒有積極添加新的接收器,我們建議通過 webhook 接收器實現自定義通知集成。
# 全局唯一的接收器名稱。
name: <string>
# 配置各種接收集成。
email_configs:
[ - <email_config>, ... ]
hipchat_configs:
[ - <hipchat_config>, ... ]
pagerduty_configs:
[ - <pagerduty_config>, ... ]
pushover_configs:
[ - <pushover_config>, ... ]
slack_configs:
[ - <slack_config>, ... ]
opsgenie_configs:
[ - <opsgenie_config>, ... ]
webhook_configs:
[ - <webhook_config>, ... ]
victorops_configs:
[ - <victorops_config>, ... ]
wechat_configs:
[ - <wechat_config>, ... ]
<email_config>
# 是否通知故障恢復。
[ send_resolved: <boolean> | default = false ]
# 通知發送的郵件地址。
to: <tmpl_string>
# 發送者地址。
[ from: <tmpl_string> | default = global.smtp_from ]
# 郵件發送的 SMTP host。
[ smarthost: <string> | default = global.smtp_smarthost ]
# 鑑定 SMTP 服務器的主機名。
[ hello: <string> | default = global.smtp_hello ]
# SMTP 認證信息。
[ auth_username: <string> | default = global.smtp_auth_username ]
[ auth_password: <secret> | default = global.smtp_auth_password ]
[ auth_secret: <secret> | default = global.smtp_auth_secret ]
[ auth_identity: <string> | default = global.smtp_auth_identity ]
# SMTP TLS 要求。
# 注意 Go 不支持與遠程SMTP端點的未加密連接。
[ require_tls: <bool> | default = global.smtp_require_tls ]
# TLS 配置。
tls_config:
[ <tls_config> ]
# 郵件通知的 HTML body。
[ html: <tmpl_string> | default = '{{ template "email.default.html" . }}' ]
# The text body of the email notification.
[ text: <tmpl_string> ]
# 額外的 email 頭 鍵值對。
[ headers: { <string>: <tmpl_string>, ... } ]
<webhook_config>
配置通用接收器
# 是否通知故障恢復。
[ send_resolved: <boolean> | default = true ]
# 發送 HTTP POST 請求的目的端點url。
url: <string>
# HTTP 客戶端的配置。
[ http_config: <http_config> | default = global.http_config ]
Alertmanager 向配置的端點發送 HTTP POST 請求的 JSON 格式:
{
"version": "4",
"groupKey": <string>, // key identifying the group of alerts (e.g. to deduplicate)
"status": "<resolved|firing>",
"receiver": <string>,
"groupLabels": <object>,
"commonLabels": <object>,
"commonAnnotations": <object>,
"externalURL": <string>, // backlink to the Alertmanager.
"alerts": [
{
"status": "<resolved|firing>",
"labels": <object>,
"annotations": <object>,
"startsAt": "<rfc3339>",
"endsAt": "<rfc3339>",
"generatorURL": <string> // identifies the entity that caused the alert
},
...
]
}
<wechat_config>
通過微信 API 發送通知。
# 是否通知故障恢復。
[ send_resolved: <boolean> | default = false ]
# 調用微信 API 用的 key。
[ api_secret: <secret> | default = global.wechat_api_secret ]
# 微信 API URL.
[ api_url: <string> | default = global.wechat_api_url ]
# 用於認證的 corp id。
[ corp_id: <string> | default = global.wechat_api_corp_id ]
# 微信 API 定義的 API 請求數據。
[ message: <tmpl_string> | default = '{{ template "wechat.default.message" . }}' ]
[ agent_id: <string> | default = '{{ template "wechat.default.agent_id" . }}' ]
[ to_user: <string> | default = '{{ template "wechat.default.to_user" . }}' ]
[ to_party: <string> | default = '{{ template "wechat.default.to_party" . }}' ]
[ to_tag: <string> | default = '{{ template "wechat.default.to_tag" . }}' ]
發送告警
免責聲明: Prometheus 自動處理髮送由其配置的告警規則生成的告警。強烈建議根據時間序列數據在 Prometheus 中配置告警規則,而不要實現客戶端。
Alertmanager 有 V1 和 V2 兩個 API,都監聽告警。V1 的告警格式在如下的代碼片段中描述。V2 被指定爲 OpenAPI 規範,可以在Alertmanager 代碼庫中找到該規範。客戶端只要活着就可以不斷重發告警(通常間隔爲30秒到3分鐘)。客戶端可以通過 POST 請求推送一個告警列表。
每個告警的 label 用於標識告警的相同實例以實現去重。annotations 始終設置爲最近收到的註釋,並且不能標識告警。
startsAt
和 endsAt
時間戳是可選的。如果 startsAt
省略了,就自動設爲當前時間。僅當知道告警的結束時間時才設置 endsAt
。否則,它將被設置爲自上次收到警報以來的時長。
generatorURL
字段是唯一的反向鏈接,用於標識客戶端中此告警的來源。
[
{
"labels": {
"alertname": "<requiredAlertName>",
"<labelname>": "<labelvalue>",
...
},
"annotations": {
"<labelname>": "<labelvalue>",
},
"startsAt": "<rfc3339>",
"endsAt": "<rfc3339>",
"generatorURL": "<generator_url>"
},
...
]
通知模板參考
Prometheus 創建併發送告警到 Alertmanager,後者根據告警的標籤將它們發送通知到不同的接收器。接收器可以是許多集成中的一種,包括:Slack、 PagerDuty、email、或通過通用 webhook 接口定製的集成。
通知通過模板發送給接收器。Alertmanager 自帶默認接收器,當然它們也可以定製化。爲了避免混淆,Alertmanager 模板和 Prometheus 中的模板是不同的,儘管 Prometheus 模板也包含告警規則 labels/annotations 中的模板。
Alertmanager 的通知模板基於 Go 語言的模板系統。請注意,某些字段被定義爲文本,而其他字段則被定義爲 HTML,這會影響轉義。
數據結構
數據
Data
是傳遞給通知模板和 Webhook 推送的數據結構。
名稱 | 類型 | 釋義 |
---|---|---|
Receiver | string | 通知發送的接收器名稱(slack, email 等). |
Status | string | 如果至少有一個告警正在發送就是 firing,否則是 resolved。 |
Alerts | Alert | 列舉該組中的所有告警對象 (見下)。 |
GroupLabels | KV | 這些告警歸組的組標籤。 |
CommonLabels | KV | 所有告警共有的標籤。 |
CommonAnnotations | KV | 所有告警共有的 annotations 集合。用於獲取有關警報的更多信息的字符串。 |
ExternalURL | string | 發送通知的反向鏈接。 |
Alerts
類型暴露過濾告警的函數:
Alerts.Firing
返回該組當前發送的告警對象列表Alerts.Resolved
返回該組已恢復的告警對象列表
告警
Alert
持有告警的通知模板。
名稱 | 類型 | 釋義 |
---|---|---|
Status | string | 告警當前狀態是發送還是恢復。 |
Labels | KV | 附在告警上的 label 集合。 |
Annotations | KV | 附在告警上的 annotations 集合。 |
StartsAt | time.Time | 告警觸發的時間,如果省略,Alertmanager 就將其設爲當前時間。 |
EndsAt | time.Time | 僅當知道告警的結束時間時才設置 endsAt 。否則,它將被設置爲自上次收到警報以來的時長。 |
GeneratorURL | string | 標識告警源的反向鏈接。 |
鍵值對(KV)
KV
是一組用於標識 label 和 annotation 的鍵值對。
type KV map[string]string
Annotation 示例包含兩個 Annotation:
{
summary: "alert summary",
description: "alert description",
}
除了直接訪問存儲爲KV的數據(標籤和註釋)外,還有一些用於排序,刪除和查看標籤集的方法:
KV methods
名稱 | 參數 | 返回值 | 釋義 |
---|---|---|---|
SortedPairs | - | 鍵/值字符串對的列表 | 返回一個排序後的鍵值對列表。 |
Remove | []string | KV | 返回不包含指定鍵的鍵值對列表的拷貝。 |
Names | - | []string | 返回標籤集中的鍵。 |
Values | - | []string | 返回標籤集中的值。 |
函數
注意默認函數由 Go 語言模板提供。
字符串
名稱 | 參數 | 返回值 | 釋義 |
---|---|---|---|
title | string | strings.Title, 每個單詞的第一個字符大寫。 | |
toUpper | string | strings.ToUpper, 將所有字符轉換爲大寫。 | |
toLower | string | strings.ToLower, 將所有字符轉換爲小寫。 | |
match | pattern, string | Regexp.MatchString. 使用Regexp匹配字符串。 | |
reReplaceAll | pattern, replacement, text | 正則表達式替換,不固定。 | |
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。
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: 'https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}'
常見註解(annotation)中的訪問註解
在此示例中,我們再次自定義發送到 Slack 接收器的文本,以訪問 Alertmanager 發送的數據中的常見註釋CommonAnnotations中存儲的 summary
和 description
。
Alert
groups:
- name: Instances
rules:
- alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: page
# 此處 Prometheus 模板應用告警的 annotation 和 label 字段。
annotations:
description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.'
summary: 'Instance {{ $labels.instance }} down'
Receiver
- name: 'team-x'
slack_configs:
- channel: '#alerts'
# 此處應用 Alertmanager 模板。
text: "<!channel> \nsummary: {{ .CommonAnnotations.summary }}\ndescription: {{ .CommonAnnotations.description }}"
遍歷所有收到的告警
最後,假設警報與前面的示例相同,我們將接收器自定義爲覆蓋從 Alertmanager 收到的所有警報,並在新行上打印它們各自的註釋摘要和描述。
Receiver
- name: 'default-receiver'
slack_configs:
- channel: '#alerts'
title: "{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}"
text: "{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}"
定義可複用的模板
回到第一個示例,我們還可以提供一個包含命名模板的文件,然後由 Alertmanager 加載該文件,以避免跨越多行的複雜模板。在下面創建文件
{{ define "slack.myorg.text" }}https://internal.myorg.net/wiki/alerts/{{ .GroupLabels.app }}/{{ .GroupLabels.alertname }}{{ end}}
現在,配置將使用給定名稱的“text”字段加載模板,並且我們提供了自定義模板文件的路徑:
lobal:
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 以簡化自動化和集成。
健康檢查
GET /-/healthy
這個端點用於 Alertmanager 的健康檢查,正常返回 200。
就緒檢查
GET /-/ready
這個端點用於檢查 Alertmanager 是否可以提供服務(如相應請求),正常返回 200。
重加載
POST /-/reload
這個端點觸發 Alertmanager 重新加載配置文件。
觸發配置重新加載的另一種方法是向 Alertmanager 進程發送 SIGHUP 信號。