Premetheus Alertmanager告警

Premetheus好基友Alertmanager实现监控告警

1. 服务器相关数据查询(基于node_exporter)

1.1 磁盘空间使用率
1
node_filesystem_size_bytes{device="/dev/sda3",fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"}

其中node_filesystem_size_bytes为磁盘整体的空间情况. 这样写的话其实会有一个局限所在, 服务器的/挂载点并不一定是在磁盘sda3上面, 所以我们进行一些基础修改, 去掉device参数.

1
node_filesystem_size_bytes{fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"}

如果要查询磁盘的空闲情况, 使用node_filesystem_free_bytes来进行查询:

1
node_filesystem_free_bytes{fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"}

Prometheus中的query中执行上面两条语句, 可以得到如下结果.
Alt text

那么有了磁盘整体空间, 以及磁盘空闲情况, 自然就可以计算出当前磁盘空间的使用率了.

1
1 - node_filesystem_free_bytes{fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"} / node_filesystem_size_bytes{device="/dev/sda3",fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"}

该表达式将会得到一个浮点数, 表示当前查询的机器的磁盘使用情况.

1.2 内存使用情况查询

相比较于CPU使用率, 我们更加关心内存的使用情况, 毕竟当服务器内存溢出时带来的后果远比CPU满负载运行的后果恶劣的多.
在有了磁盘空间使用情况的查询基础后, 内存使用情况自然就是信手拈来.

查看整体内存情况, 即该机器共有多少内存, 使用node_memory_MemTotal_bytes, 返回的结果自然是bytes

1
node_memory_MemTotal_bytes{instance="172.17.0.1:19100",job="linux"}

查看内存空闲空间, 使用node_memory_MemFree_bytes或者是使用node_memory_MemAvailable_bytes, 两者有一些区别. node_memory_MemFree_bytes得出的数值要比node_memory_MemAvailable_bytes小很多, 具体的区别目前没有弄清楚, 带填坑吧.本着宁可错杀一千, 也不放过一个的心态, 尽量还是使用node_memory_MemFree_bytes这个较小的数值来进行计算.
此时即可进行计算目前已使用内存比率

1
2
1 - node_memory_MemFree_bytes / node_memory_MemTotal_bytes
# 结果为0.577

如果说误杀的次数比较多的话, 我们也可以使用node_memory_MemAvailable_bytes来进行代替

1
2
1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
# 结果为0.355

可以看出两种查询方式所得结果差异还是比较大的.

2. 使用Alertmanager进行企业微信告警

在上面我们写了一大堆查询语句, 具体能干什么?
其实Alertmanager的告警实现是这样的: 通过查询语句对node_exporter所获取的数据进行查询, 并对返回的结果进行判断, 如果达到告警触发条件, 向定义的数据接收方发送告警消息.

首先来看一个在网上的博客中大家纷纷’抄袭’的规则语句.不得不在此吐槽一下, 几乎所有的博客内容都是大同小异, 连规则都是一样的, 难道服务器监控就只有监控机器是否存活这一条?

1
2
3
4
5
6
7
8
groups:
- name: node
rules:
- alert: server_status
expr: up{job="node"} == 0
for: 15s
annotations:
summary: "机器 {{ $labels.instance }} 挂了"

其中的up{job="node"}就是一条查询语句.我们在Prometheus中的query框中敲一个up查看结果:
Alt text
那么up{instance="172.17.0.1:19100",job="linux"}呢?
Alt text

那么上面的规则我们就可以非常清晰的进行解释了:

1
2
3
4
5
6
7
8
groups:
- name: node
rules:
- alert: server_status
expr: up{job="node"} == 0 # 查询结果判断表达式
for: 15s
annotations:
summary: "机器 {{ $labels.instance }} 挂了" # 给出什么样儿的注释

结合上面儿的磁盘使用以及内存使用情况查询, 我们可以很简单的写出一系列的规则:

1
2
3
4
5
6
7
8
groups:
- name: linux
rules:
- alert: server_status
expr: 1 - node_filesystem_free_bytes{fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"} / node_filesystem_size_bytes{device="/dev/sda3",fstype="ext4",instance="172.17.0.1:19100",job="linux",mountpoint="/"} > 0.75 # 查询结果判断表达式
for: 15s
annotations:
summary: "机器 {{ $labels.instance }} 磁盘空间不足, 请及时清理" # 给出什么样儿的注释

当规则被触发时, Prometheus会发送请求到alertmanager, 然后由alertmanager中所定义的receiver来通知开发人员.receiver虽然可以使用第三方的组件, 比如企业微信, 钉钉等, 但是这些第三方的API可能会发生改变, 自己写一个也花不了什么时间, 比如Flask, 能够非常简单的写出来一个基本处理单元.

那么在进行Flask开发之前, 我们需要知道Alertmanager到底发送了什么类型的请求以及请求体是什么.
查看官方文档: https://prometheus.io/docs/alerting/configuration/#%3Cwebhook_config%3E
写的非常请求, 一个POST请求, Content-TypeJSON, 那么针对于此我们就可以写一个简易版本的报警网管儿了.