对于站点流量监控或日志状态的监控,之前通过elk+python+zabbix结合微信报警来实现,但是这种方式对于流量的阈值及监控间隔不太好确定,而且通过elk的dsl语句查询,实现起来比较麻烦。

因此我们希望借助grafana的多数据源特性,结合elk+alertmanager实现微信报警,并且能够报警到不同部门或不同告警人。

alertmanager

alertmanager是prometheus一个单独的报警模块,具有分组、抑制、静默等功能。在此我们借助alertmanager直接与grafana进行结合实现告警。

1.配置

cd /usr/local/alertmanager
vim grafana.yml
global:
  resolve_timeout: 5m

templates:
- '/usr/local/alertmanager/wechat.tmpl'

route:
  group_by: ['alertname']
  group_wait: 5s
  #同一组内警报,等待group_interval时间后,再继续等待repeat_interval时间
  group_interval: 1m
  #当group_interval时间到后,再等待repeat_interval时间后,才进行报警
  repeat_interval: 10m
  receiver: 'wechat'
receivers:
- name: 'wechat'
  wechat_configs:
  - corp_id: 'wwbba7dxe372e'
    agent_id: '1000005'
    api_secret: '-CJ9QLEFxsdfwvxLzx7wPgoK9Dt-NWYOLuy-RuX3I'
    to_user: 'test1'
    send_resolved: true

alertmanager默认情况下告警接收人为wechat,也就是默认对test1用户发送微信告警。

其中:

  1. corp_id、agent_id、api_secret为微信企业号的配置;
  2. to_user为企业号通讯录人员;
  3. 报警再次发送时间为group_interval+repeat_interval,也就是先等待group_interval,再等待repeat_interval。

注意:企业号新建应用的须设置相应的可见范围及人员,否则无法发送信息。

2.报警模板

cd /usr/local/alertmanager
vim wechat.tmpl
{{ define "grafana.default.message" }}{{ range .Alerts }}
{{ (.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{ range .Annotations.SortedPairs }}{{ .Name }} = {{ .Value }}
{{ end }}{{ end }}{{ end }}

{{ define "wechat.default.message" }}
{{ if eq .Status "firing"}}[Warning]:{{ template "grafana.default.message" . }}{{ end }}
{{ if eq .Status "resolved" }}[Resolved]:{{ template "grafana.default.message" . }}{{ end }}
{{ end }}

其中:

  1. Status 只有两个状态firing、resolved,通过这个参数是否发送warning和resolved报警信息。
  2. 模板的语法还需查官网进行深入学习。

注意:prometheus 默认时区为UTC且无法改变时区,因此我们的报警时间应该+8:00,因此需要在模板中重新调整时区。

 

3.设置启动服务

vim /lib/systemd/system/alertmanager.service
[Unit]
Description=Alertmanager for Prometheus
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/grafana.yml --storage.path=/usr/local/alertmanager/data/  --log.level=debug
Restart=on-failur
ExecStop=/bin/kill -9 $MAINPID

[Install]
WantedBy=multi-user.targe

启动后,可通过http://ip:9093 访问alertmanager界面。

grafana

1.添加报警渠道

 

注意:Disable Resolve Message 没有勾选,不发送报警取消信息;我是在alertmanager 模板中判断若Status没有firing(则为resolved),则发送报警解决信息。

2.设置Alert

Alert需要在相应的dashboard中进行设置

 

其中监控策略为每分钟计算一次,持续5分钟;当query A 在5分钟时间内的中位数 > 1500 时,报警会发送给alertmanager;alertmanager 会根据group_wait、group_interval、repeat_interval对报警进行分组合并、抑制,从而避免告警泛滥。


3.微信告警

 

从[Warning]告警得知,alertmanager将两条告警信息合并为一条后发送给报警人,从而避免发送多条告警通知,引起告警泛滥。

告警通知

上面只是实现了对test1用户微信告警通知,但是在生产环境中告警需要按照级别、业务发送给不同部门、负责人,此时我们就需要进行优化。

例如:我们对elk的index按业务分组并发给不同部门的接收人,如:web、api,怎么实现?

接下来我们继续分析。

1.alertmanager告警信息

alertname='xxx流量告警'
description='xxx每分钟访问量超过1500'
summary='xxx流量告警'
metric='Count'

通过访问alertmanager的web页面http://192.168.3.44:9093确认:

  • alertmanager中,对alertname进行分组;
  • description和summary是具体报警内容;
  • metric是标签,即label;

要想实现分组,alertmanager需要根据label进行设置路由,通过匹配label发送给不同的接收人。

2.设置子路由

通过routes设置子路由,子路由中设置不同的接收人。

vim grafana.yml
global:
  resolve_timeout: 5m

templates:
- '/usr/local/alertmanager/wechat.tmpl'

route:
  group_by: ['alertname']
  group_wait: 5m
  #group_wait: 1m
  #同一组内警报,等待group_interval时间后,再继续等待repeat_interval时间
  group_interval: 10m
  #group_interval: 1m
  #当group_interval时间到后,再等待repeat_interval时间后,才进行报警
  repeat_interval: 1h
  #repeat_interval: 1m
  receiver: 'wechat'
  #子路由
  routes:
  - receiver: 'wechat_web'
    match_re:
      department: 'web'
  - receiver: 'wechat_api'
    match_re:
      department: 'api'
receivers:
- name: 'wechat'
  wechat_configs:
  - corp_id: 'wwbba179b20d372e'
    agent_id: '1000005'
    api_secret: '-CJ9QLEFxLzxt-NWYOLuy-RuX3I'
    to_user: 'test1'
    send_resolved: true
- name: 'wechat_web'
  wechat_configs:
  - corp_id: 'wwbba179b20d372e'
    agent_id: '1000005'
    api_secret: '-CJ9QLEFxLzxt-NWYOLuy-RuX3I'
    to_user: 'test2'
    send_resolved: true
- name: 'wechat_api'
  wechat_configs:
  - corp_id: 'wwbba179b20d372e'
    agent_id: '1000005'
    api_secret: '-CJ9QLEFxLzxt-NWYOLuy-RuX3I'
    to_user: 'test3'
    send_resolved: true

我们将告警接受人按标签department分为wechat_web、wechat_api、wechat三组

3.amtool 调试

#触发web报警
./amtool --alertmanager.url=http://192.168.3.44:9093 alert add department=web alertname="xxx流量告警"        --annotation=description='xxx每分钟访问量超过1500'  --annotation=summary = "xxx流量告警"
#触发api报警
./amtool --alertmanager.url=http://192.168.3.44:9093 alert add department=api alertname="xxx流量告警"        --annotation=description='xxx每分钟访问量超过1500'  --annotation=summary = "xxx流量告警"

通过这种方式,我们可以在排除grafana的情况下,模拟测试alertmanager触发报警。

 

4.grafana匹配label

由于我们使用的是grafana5.4 ,查看官方文档进行确认。

 

从上图看出报警通道为prometheus+alertmanager 是支持发送图片和报警标签(对应alertmanager中的label),但是是从6.3+开始。

也就是说grafana5.4 是不支持报警标签,因此无法设置label;因此我们需要将grafana升级到6.3以上,升级过程需要测试,以免丢失数据。

两个版本的对比如下:

(1)grafana-5.4 告警信息配置:

 

(2)grafana-6.5 告警信息配置:

 

通过上图区别,可明显看出6.5 比 5.4 的多出了一个alert tag的功能,即对应alertmanger的label。如下:

 

使用grafana-5.4 默认展示一个label:metric

使用grafana-6.5 可以展示两个label:department和metric:

  • metric用于elk的相关指标的统计量;
  • department用于区分发送给不同部门和报警人

alertmanger正是通过这个手动添加的label来匹配不同的子路由,发给不同的报警人,我们只需要在grafana中通过department来指定不同的部门或业务负责人即可。

总结

grafana可以非常直观展示业务的近实时流量状态,因此可以很方便的设置指标的监控阈值,结合alertmanage对告警进行分组、合并、抑制,避免告警泛滥,可以准确的让运维定位问题。但是grafana指标发生告警时的实际值无法在告警通知时展示,这可能是一个比较遗憾的地方。