文章目录
- 前言
- 一、promethesu告警
- 二、告警配置
- 编写rule文件
- prometheus配置
- prometheus产生告警
- 三、告警通知
- prometheus 配置 alertmanager
- alertmanager 配置 webhook通知
- 编写接口接收 webhook
- 总结
前言
如果没有学习过prometheus的基础和监控的同学,可以先过一遍这篇文章
https://blog.csdn.net/weixin_42132143/article/details/134772543?spm=1001.2014.3001.5501
一、promethesu告警
Prometheus 收集和存储监控数据,然后根据自定义的告警规则进行数据分析,从而触发报警。配置告警规则通常包括以下几个步骤:
-
定义告警规则:告警规则是在 Prometheus 的配置文件中定义的,通常位于 prometheus.yml 文件中的 rules 部分。你需要创建一个告警规则文件(例如 alert.rules.yml),在这个文件中定义你的告警逻辑。
-
配置告警规则文件:在 prometheus.yml 中指定告警规则文件的位置,例如:
rule_files: - "alert.rules.yml"
-
编写告警规则:在告警规则文件中编写具体的规则。每条规则包括以下几个部分:
-
alert: 告警名称。
-
expr: 告警表达式,当表达式的结果为 true 时触发告警。
-
for: 等待一段时间后才触发告警,用于防止短暂的数据波动导致的误报。
-
labels: 附加到告警上的标签,可以用来分类告警。
-
annotations: 告警的详细说明,如描述、摘要等。
例如:
groups: - name: example rules: - alert: HighRequestLatency expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5 for: 10m labels: severity: page annotations: summary: High request latency
- 配置报警通知:Prometheus 本身只是产生告警不直接发送告警,是通过 Alertmanager 来管理告警通知。你需要配置 Alertmanager 的配置文件 alertmanager.yml 来定义通知的接收者和方式,如webhook、邮件、Slack、PagerDuty 等。
二、告警配置
编写rule文件
我们自定义一个告警规则,这里针对 node_exporter 的内存使用率,超过80%触发告警:
新建一个 rule 文件,
vi /etc/prometheus/rules/node_rule.yml
groups:
- name: node
rules:
- alert: MemoryCritical
expr: 100 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels:
severity: warning
object: "{{ $labels.instance }}"
content: 内存使用率高于90%
job: "{{ $labels.job }}"
annotations:
summary: "Low memory available (instance {{ $labels.instance }})"
description: "Memory usage rate above 90% for more than 5 minute"
如果是想新增一些自定义的标签,可以放在 groups.rules.labels 下面,上面的 object、content、job 就是我新增的自定义标签
prometheus配置
修改 prometheus 的配置文件
rule_files:
- "/etc/prometheus/rules/node_rule.yml"
重启 prometheus 服务,使之生效
prometheus产生告警
已经配置好告警规则了,这时候我们给安装 node_exporter 的被监控节点加压,使之内存使用率高于 80%
然后 prometheus 就会产生告警信息,可以在 prometheus 的页面看到产生的告警信息
http://localhost:9090/alerts
这个页面会看到诸如此类的告警规则,变成红色就是产生了告警
三、告警通知
prometheus 配置 alertmanager
prometheus 已经产生了告警了,我们需要将告警信息推送给 alertmanager
这里就不放 alertmanager 的安装教程了
修改 prometheus 的配置文件,配置上 alertmanager
alerting:
alertmanagers:
- static_configs:
- targets:
- 192.168.231.56:9093
重启 prometheus
这时候你就可以在 alertmanager 页面看到接收到的告警信息
prometheus 每次都会把当前所有已经产生的告警信息推送过去 alertmanager
alertmanager 配置 webhook通知
这时候只是 alertmanager 接收到了告警信息,而 alertmanager 它本身就是一个用于配置告警通知的工具
我们这里使用 webhook 的方式来通知
修改 alertmanager 的配置文件
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'content', 'object']
group_wait: 10s
group_interval: 10s
repeat_interval: 24h
receiver: 'web.hook'
receivers:
- name: 'web.hook'
webhook_configs:
- url: 'http://172.16.205.66:8122/notify/alert/send'
说明:
- 上面的配置中 group by 指定了多个字段,作用是根据这几个字段来区分同一条告警,防止重复告警。上面也说了 prometheus 每次都会把当前所有已经产生的告警信息推送过去 alertmanager,如果 group by 不做区分,或者只用了默认的 alertname 一个字段,很有可能会导致在多个告警触发的场景下,导致之前已经告警过的信息再次告警通知。
- 上面的配置中的 receiver 指定是 web.hook 方式推送,然后在 receivers 配置其地址。webhook方式其实说白了,他就是 由 alertmanager 往这个指定的地址,发送一个 POST 方式的 HTTP 请求而已,所以我们的接收端只需要编写一个普通的 web 项目,里面有一个 POST 接口,接口的地址对应上就可以了。
编写接口接收 webhook
直接新建一个空白的 springboot 项目,加上一个接口,接收来自 alertmanager 的推送,然后根据自己的业务处理就行了,下面放一点核心的代码:
@PostMapping("/send")
public R send(HttpServletRequest httpServletRequest) throws IOException {
CachedBodyHttpServletRequest request = new CachedBodyHttpServletRequest(httpServletRequest);
// alertmanager的webhook通知会有短时间内的超时重传,这里用异步
alertNotifyService.notify(request);
return R.success();
}
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
private final String cachedBody;
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
StringBuilder body = new StringBuilder();
try (BufferedReader bufferedReader = request.getReader()) {
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
body.append(charBuffer, 0, bytesRead);
}
}
this.cachedBody = body.toString();
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new StringReader(this.cachedBody));
}
}
@Async
public void notify(HttpServletRequest request) {
// 解析prometheus请求参数
AlertManagerBean msg = getRequestReaderMsg(request);
System.out.println(msg);
if(msg == null)
return;
// 通知发送逻辑
}
private AlertManagerBean getRequestReaderMsg(HttpServletRequest request){
AlertManagerBean alertManagerBean = null;
try (BufferedReader reader = request.getReader()) {
// 获取JSON请求参数
String jsonBody = reader.lines().reduce("", (accumulator, actual) -> accumulator + actual);
// log.info(jsonBody);
alertManagerBean = JSONUtil.toBean(jsonBody, AlertManagerBean.class);
} catch (Exception e) {
e.printStackTrace();
log.warn("解析prometheus请求参数失败");
}
return alertManagerBean;
}
@Data
public class AlertManagerBean {
private String status;
private List<AlertManagerAlert> alerts;
}
@Data
public class AlertManagerAlert {
private String status;
private AlertManagerLabel labels;
private AlertManagerAnnotation annotations;
}
@Data
public class AlertManagerLabel {
private String alertname;
private String instance;
private String device;
private String mountpoint;
private String fstype;
private String level;
private String job;
private String content;
private String object;
}
@Data
public class AlertManagerAnnotation {
private String summary;
private String description;
}
总结
欢迎指出我的错误!