https://github.com/prometheus/alertmanager#install
二进制部署
./alertmanager --config.file=config.yml
k8s部署
alertmanager.yml配置文件格式:
$ cat alertmanager-config.ymlapiVersion: v1kind: ConfigMapmetadata:name: alertmanagernamespace: monitordata:config.yml: |global:# 当alertmanager持续多长时间未接收到告警后标记告警状态为 resolvedresolve_timeout: 5m# 配置邮件发送信息smtp_smarthost: 'smtp.163.com:25'smtp_from: '123321163@163.com'smtp_auth_username: '123321163@163.com'smtp_auth_password: 'qzpm10'smtp_require_tls: false# 所有报警信息进入后的根路由,用来设置报警的分发策略route:# 接收到的报警信息里面有许多alertname=NodeLoadHigh 这样的标签的报警信息将会批量被聚合到一个分组里面group_by: ['alertname']# 当一个新的报警分组被创建后,需要等待至少 group_wait 时间来初始化通知,如果在等待时间内当前group接收到了新的告警,这些告警将会合并为一个通知向receiver发送group_wait: 30s# 相同的group发送告警通知的时间间隔group_interval: 30s# 如果一个报警信息已经发送成功了,等待 repeat_interval 时间来重新发送repeat_interval: 10m# 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器receiver: default# 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。routes:- {}# 配置告警接收者的信息receivers:- name: 'default'email_configs:- to: '123456789@qq.com'send_resolved: true # 接受告警恢复的通知
主要配置的作用:
- global: 全局配置,包括报警解决后的超时时间、SMTP 相关配置、各种渠道通知的 API 地址等等。
- route: 用来设置报警的分发策略,它是一个树状结构,按照深度优先从左向右的顺序进行匹配。
- receivers: 配置告警消息接受者信息,例如常用的 email、wechat、slack、webhook 等消息通知方式。
配置文件:
$ kubectl create -f alertmanager-config.yml
其他资源清单文件:
apiVersion: apps/v1kind: Deploymentmetadata:name: alertmanagernamespace: monitorlabels:app: alertmanagerspec:selector:matchLabels:app: alertmanagertemplate:metadata:labels:app: alertmanagerspec:volumes:- name: configconfigMap:name: alertmanagercontainers:- name: alertmanagerimage: prom/alertmanager:v0.21.0imagePullPolicy: IfNotPresentargs:- "--config.file=/etc/alertmanager/config.yml"- "--log.level=debug"ports:- containerPort: 9093name: httpvolumeMounts:- mountPath: "/etc/alertmanager"name: configresources:requests:cpu: 100mmemory: 256Milimits:cpu: 100mmemory: 256Mi---apiVersion: v1kind: Servicemetadata:name: alertmanagernamespace: monitorspec:type: ClusterIPports:- port: 9093selector:app: alertmanager---apiVersion: extensions/v1beta1kind: Ingressmetadata:name: alertmanagernamespace: monitorspec:rules:- host: alertmanager.luffy.comhttp:paths:- path: /backend:serviceName: alertmanagerservicePort: 9093
配置Prometheus与Alertmanager对话

是否告警是由Prometheus进行判断的,若有告警产生,Prometheus会将告警push到Alertmanager,因此,需要在Prometheus端配置alertmanager的地址:
apiVersion: v1kind: ConfigMapmetadata:name: prometheus-confignamespace: monitordata:prometheus.yml: |global:scrape_interval: 30sevaluation_interval: 30salerting:alertmanagers:- static_configs:- targets:- alertmanager:9093...
更新configmap
$ kubectl apply -f prometheus-configmap.yaml
现在已经有监控数据了,因此使用prometheus提供的reload的接口,进行服务重启
# 查看配置文件是否已经自动加载到pod中
$ kubectl -n monitor get po -o wideprometheus-dcb499cbf-pljfn 1/1 Running 0 47h 10.244.1.167$ kubectl -n monitor exec -ti prometheus-dcb499cbf-pljfn cat /etc/prometheus/prometheus.yml |grep alertmanager# 使用软加载的方式,$ curl -X POST 10.244.1.167:9090/-/reload
配置报警规则
目前Prometheus与Alertmanager已经连通,接下来我们可以针对收集到的各类指标配置报警规则,一旦满足报警规则的设置,则Prometheus将报警信息推送给Alertmanager,进而转发到我们配置的邮件中。
在哪里配置?同样是在prometheus-configmap中:
apiVersion: v1kind: ConfigMapmetadata:name: prometheus-confignamespace: monitordata:prometheus.yml: |global:scrape_interval: 30sevaluation_interval: 30salerting:alertmanagers:- static_configs:- targets:- alertmanager:9093# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.rule_files:- /etc/prometheus/alert_rules.yml# - "first_rules.yml"# - "second_rules.yml"scrape_configs:- job_name: 'prometheus'static_configs:- targets: ['localhost:9090']...
rules.yml我们同样使用configmap的方式挂载到prometheus容器内部,因此只需要在已有的configmap中加一个数据项目
apiVersion: v1kind: ConfigMapmetadata:name: prometheus-confignamespace: monitordata:prometheus.yml: |global:scrape_interval: 30sevaluation_interval: 30salerting:alertmanagers:- static_configs:- targets:- alertmanager:9093# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.rule_files:- /etc/prometheus/alert_rules.yml# - "first_rules.yml"# - "second_rules.yml"scrape_configs:- job_name: 'prometheus'static_configs:- targets: ['localhost:9090']... # 省略中间部分alert_rules.yml: |groups:- name: node_metricsrules:- alert: NodeLoadexpr: node_load15 < 1for: 2mannotations:summary: "{{$labels.instance}}: Low node load detected"description: "{{$labels.instance}}: node load is below 1 (current value is: {{ $value }}"
告警规则的几个要素:
- group.name:告警分组的名称,一个组下可以配置一类告警规则,比如都是物理节点相关的告警
- alert:告警规则的名称
- expr:是用于进行报警规则 PromQL 查询语句,expr通常是布尔表达式,可以让Prometheus根据计算的指标值做 true or false 的判断
- for:评估等待时间(Pending Duration),用于表示只有当触发条件持续一段时间后才发送告警,在等待期间新产生的告警状态为pending,屏蔽掉瞬时的问题,把焦点放在真正有持续影响的问题上
- labels:自定义标签,允许用户指定额外的标签列表,把它们附加在告警上,可以用于后面做路由判断,通知到不同的终端,通常被用于添加告警级别的标签
- annotations:指定了另一组标签,它们不被当做告警实例的身份标识,它们经常用于存储一些额外的信息,用于报警信息的展示之类的
规则配置中,支持模板的方式,其中:
- {{$labels}}可以获取当前指标的所有标签,支持{{$labels.instance}}或者{{$labels.job}}这种形式
- {{ $value }}可以获取当前计算出的指标值
更新配置并软重启,并查看Prometheus报警规则。
一个报警信息在生命周期内有下面3种状态:
- inactive: 表示当前报警信息处于非活动状态,即不满足报警条件
- pending: 表示在设置的阈值时间范围内被激活了,即满足报警条件,但是还在观察期内
- firing: 表示超过设置的阈值时间被激活了,即满足报警条件,且报警触发时间超过了观察期,会发送到Alertmanager端
对于已经 pending 或者 firing 的告警,Prometheus 也会将它们存储到时间序列ALERTS{}中。当然我们也可以通过表达式去查询告警实例:
ALERTS{}

查看Alertmanager日志:
level=warn ts=2020-07-28T13:43:59.430Z caller=notify.go:674 component=dispatcher receiver=email integration=email[0] msg=”Notify attempt failed, will retry later” attempts=1 err=”*email.loginAuth auth: 550 User has no permission”
说明告警已经推送到Alertmanager端了,但是邮箱登录的时候报错,这是因为邮箱默认没有开启第三方客户端登录。因此需要登录163邮箱设置SMTP服务允许客户端登录。
自定义企业微信实现告警消息的推送
其他Label的动态告警处理,添加了gkwr: restart 键值对,用于匹配告警路由
alert_rules.yml: |groups:- name: node_metricsrules:- alert: PodRestartexpr: changes(kube_pod_container_status_restarts_total[30m])>0 #最近30分钟pod重启for: 3slabels:gkwr: restartannotations:summary: 'Container: {{ $labels.container }} pod重启'description: 'namespace: {{ $labels.namespace }}, pod: {{ $labels.pod }} restart {{ $value }} times'
添加告警路由
apiVersion: v1kind: ConfigMapmetadata:name: alertmanagernamespace: monitordata:config.yml: |global:# 当alertmanager持续多长时间未接收到告警后标记告警状态为 resolvedresolve_timeout: 5m# 配置邮件发送信息smtp_smarthost: 'smtp.qq.com:25'smtp_from: '1234464@qq.com'smtp_auth_username: '1234557@qq.com'smtp_auth_password: '123456'smtp_require_tls: false#告警模板templates:- '/etc/alertmanager/wechat.tmpl'# 所有报警信息进入后的根路由,用来设置报警的分发策略route:# 接收到的报警信息里面有许多alertname=NodeLoadHigh 这样的标签的报警信息将会批量被聚合到一个分组里面group_by: ['alertname']group_wait: 30s# 相同的group发送告警通知的时间间隔group_interval: 30s# 如果一个报警信息已经发送成功了,等待 repeat_interval 时间来重新发送repeat_interval: 10m# 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器receiver: default# 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。routes:- receiver: wechatgroup_wait: 2smatch:gkwr: restart# 配置告警接收者的信息#邮件告警receivers:- name: 'default'email_configs:- to: '123456@qq.com'send_resolved: true # 接受告警恢复的通知#企业微信告警- name: 'wechat'wechat_configs:- corp_id: 'ww11111111111da'agent_id: '1000000'api_secret: 'Kn123142345235235235234_pBa-chNVk-u4'to_user: 'OuBa'send_resolved: true
添加告警模版
还是通过configmap挂载到Alertmanager中
...wechat.tmpl: |{{ define "wechat.default.message" }}{{- if gt (len .Alerts.Firing) 0 -}}{{- range $index, $alert := .Alerts -}}======== 异常告警 ========告警名称:{{ $alert.Labels.alertname }}告警级别:{{ $alert.Labels.severity }}故障命名空间:{{ $alert.Labels.namespace }}故障POD名: {{ $alert.Labels.pod}}告警详情:{{ $alert.Annotations.summary }}告警时间:{{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}========== END =========={{- end }}{{- end }}{{- if gt (len .Alerts.Resolved) 0 -}}{{- range $index, $alert := .Alerts -}}======== 告警恢复 ========告警名称:{{ $alert.Labels.alertname }}告警级别:{{ $alert.Labels.severity }}故障命名空间:{{ $alert.Labels.namespace }}故障POD名: {{ $alert.Labels.pod}}告警详情:{{ $alert.Annotations.summary }}告警时间:{{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}恢复时间:{{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}========== END =========={{- end }}{{- end }}{{- end }}
重新加载alertmanager-config.yml 重启alertmanager pod
kubectl apply -f alertmanager-config.ymlkubectl exec alertmanager-796996c79f-f9w2g -n monitor kill 1
在alertmeanager 网页上可以看到
企业微信收到告警
配置钉钉机器人消息推送
添加钉钉机器人

测试消息推送
curl -X POST "Webhook" -H 'Content-Type:application/json' -d '{"msgtype" : "text", "text": {"content": "1"}}'
安装webhook-dingtalk
安装并配置webhook-dingtalk
wget https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v2.1.0/prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gztar -xf prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gzmv prometheus-webhook-dingtalk-2.1.0.linux-amd64 /data/dingtalk/cd /data/dingtalk/cp config.example.yml config.ymlvim config.yml...targets:webhook1:url: # 此处填写钉钉webhook...# 编写systemctl控制配置文件vim /etc/systemd/system/prometheus-webhook-dingtalk.service[Unit]Description=prometheus-webhook-dingtalkAfter=network-online.target[Service]Restart=on-failureExecStart=/data/dingtalk/prometheus-webhook-dingtalk --config.file=/data/dingtalk/config.yml[Install]WantedBy=multi-user.targetsystemctl daemon-reloadsystemctl start prometheus-webhook-dingtalk.servicesystemctl enable prometheus-webhook-dingtalk.service
配置alermanager
vim /data/alertmanager/alertmanager.ymlroute:group_by: ['alertname']group_wait: 10sgroup_interval: 30srepeat_interval: 30mreceiver: xc_onlineroutes:- match:alertname: XCOnlinereceiver: xc_onlinereceivers:- name: 'xc_online'webhook_configs:- url: 'http://localhost:8060/dingtalk/webhook1/send' # 填写webhook-dingtalk生成的urlinhibit_rules:- source_match:severity: 'critical'target_match:severity: 'warning'equal: ['alertname', 'dev', 'instance']systemctl restart alertmanager
检查报警
抑制和静默
前面我们知道,告警的group(分组)功能通过把多条告警数据聚合,有效的减少告警的频繁发送。除此之外,Alertmanager还支持Inhibition(抑制) 和 Silences(静默),帮助我们抑制或者屏蔽报警。
Inhibition 抑制
抑制是当出现其它告警的时候压制当前告警的通知,可以有效的防止告警风暴。
比如当机房出现网络故障时,所有服务都将不可用而产生大量服务不可用告警,但这些警告并不能反映真实问题在哪,真正需要发出的应该是网络故障告警。当出现网络故障告警的时候,应当抑制服务不可用告警的通知。
在Alertmanager配置文件中,使用inhibit_rules定义一组告警的抑制规则:
inhibit_rules:[ - <inhibit_rule> ... ]
每一条抑制规则的具体配置如下:
target_match:[ <labelname>: <labelvalue>, ... ]target_match_re:[ <labelname>: <regex>, ... ]source_match:[ <labelname>: <labelvalue>, ... ]source_match_re:[ <labelname>: <regex>, ... ][ equal: '[' <labelname>, ... ']' ]
当已经发送的告警通知匹配到target_match或者target_match_re规则,当有新的告警规则如果满足source_match或者定义的匹配规则,并且已发送的告警与新产生的告警中equal定义的标签完全相同,则启动抑制机制,新的告警不会发送。
例如,定义如下抑制规则:
- source_match:alertname: NodeDownseverity: criticaltarget_match:severity: criticalequal:- node
如当集群中的某一个主机节点异常宕机导致告警NodeDown被触发,同时在告警规则中定义了告警级别severity=critical。由于主机异常宕机,该主机上部署的所有服务,中间件会不可用并触发报警。根据抑制规则的定义,如果有新的告警级别为severity=critical,并且告警中标签node的值与NodeDown告警的相同,则说明新的告警是由NodeDown导致的,则启动抑制机制停止向接收器发送通知。<br />演示:实现如果 NodeMemoryUsage 报警触发,则抑制NodeLoad指标规则引起的报警。
inhibit_rules:- source_match:alertname: NodeMemoryUsageseverity: criticaltarget_match:severity: normalequal:- instance
Silences: 静默
简单直接的在指定时段关闭告警。静默通过匹配器(Matcher)来配置,类似于路由树。警告进入系统的时候会检查它是否匹配某条静默规则,如果是则该警告的通知将忽略。 静默规则在Alertmanager的 Web 界面里配置。<br /> 一条告警产生后,还要经过 Alertmanager 的分组、抑制处理、静默处理、去重处理和降噪处理最后再发送给接收者。这个过程中可能会因为各种原因会导致告警产生了却最终没有进行通知,可以通过下图了解整个告警的生命周期:<br />[https://github.com/liyongxin/prometheus-webhook-wechat](https://github.com/liyongxin/prometheus-webhook-wechat)<br />[<br />](https://github.com/liyongxin/prometheus-webhook-wechat)

。
