Prometheus监控文档

1.SRE: Google运维解密

​ 为了让亿万用户使用到稳定可靠的服务,Google 组建了一支专业的团队负责运行这些后端服务,这些工程师有一个共同的名字:Site Reliability Engineer。了解 Google SRE 的人常说的一句话是:和你们相比,大部分公司还处于刀耕火种时代,什么时候你们这些最佳实践能够帮助帮助其他的公司呢?资深 Google SRE Chris Jones 等人联合撰写了《Google SRE: How Google runs production systems》(以下简称《Google SRE》),首次向外界解密了谷歌的生产环境。前 Google 资深 SRE ,现 Coding.net CTO 孙宇聪 先生担任了本书译者。

​ Prometheus受启发于Google的Brogmon监控系统(相似的Kubernetes是从Google的Brog系统演变而来)

康威定律 (康威法则 , Conway’s Law) 是马尔文·康威1967年提出的:

“设计系统的架构受制于产生这些设计的组织的沟通结构。”

即系统设计本质上反映了企业的组织机构。系统各个模块间的接口也反映了企业各个部门之间的信息流动和合作方式,系统架构是组织架构的副本。

1. 主旨

之前有人问我这本书的中心思想是什么?忘记了当时给出的答案了,但是让我现在在回答一次的话,应该是——漫步 Google 运维,讲述 Google 这个拥有海量数据、多数据中心的公司,是如果通过各种手段来保证它的可用性。接下来将会分为四部分对该书进行总结:

  • 概览——了解 SRE 的定义,以及该职位与传统运维的区别
  • 指导思想——讨论 SRE 的工作模式、行事方法,以及日常运维工作中关注的焦点
  • 具体实践——理解 SRE 日常工作背后的理念,讨论具体的构建与运维大型分布式系统的实践。
  • 管理——探索 Google 在培训,内部沟通,以及在会议方面的最佳实践。(ps 这篇笔记里针对这部分是没有描述的,感兴趣建议自己阅读

2. 概览

2.1 提出 SRE 的动力?

很多公司开发部(Dev)和运维部(Ops)是分属两个不同部门的,这种 Dev/Ops 分离的团队模型,无法避免的带来两类成本问题:

  • 直接成本:随着系统复杂度的增加,部署规模的扩大,团队的大小基本与系统负载成线性关系,共同增长。
  • 间接成本:研发团队和运维团队背景各异,技术能力和工具使用习惯上差距巨大,工作目标存在不可调和分歧点,而这些会严重影响产品的迭代。

但SRE 团队的作为解决上分歧点被提出来,在快速迭代与系统稳定性直接做了平衡。SRE 团队的出现也大大节省了公司的开支。

公司作为盈利性组织,任何能够节省公司开支的举措都会被大力支持的,这才是核心动力。

DevOps 这个名词的核心思想是尽早的将 IT 相关的技术与产品设计和开发过程结合起来,着重强调自动化而不是人工操作,以及利用软件工程手段执行运维任务等。可以认为 DevOps 是 SRE 核心理念的普适版,SER 是 DevOps 模型在 Google 的具体实践。

2.2 SRE 聚焦问题点

  • 确保长期关注研发工作:Google 将 SRE 团队的运维工作限制在 50% 以内,剩余的时间花在研发项目上。你需要拥有上帝视角,才能更好的解决问题。
  • 在保障服务 SLO 的前提下最大化迭代的速度:Dev 和 Ops 不可调和的矛盾点是 迭代创新的速度与产品稳定程度之间的矛盾迭代创新的速度与产品稳定程度之间的矛盾 。 但是请记住,任何软件都不应该一味地追求 100% 可靠,因为大多数情况下 99.999% 和 100% 的可靠性是没有实质区别的。所以你需要「错误预算」。

你需要思考的是,花费巨大的精力将系统变为 100% 可靠是否能为用户带来实质意义上的好处?
从用户终端到服务器之间有很多中间系统(用户终端、家庭 wifi、网络提供商和输电线路等)这些系统综合起来的可靠性要远远低于 99.999%。

  • 监控系统:一个监控系统应该只有三类输出:紧急警报、工单、日志

不论是如何优秀研发人员,过多的噪音,一定会影响你对事物的判断。狼来了的故事教育我们,你要在狼真的来的时候才去呼救。

2.监控的目标

在《SRE: Google运维解密》一书中指出,监控系统需要能够有效的支持白盒监控和黑盒监控。通过白盒能够了解其内部的实际运行状态,通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如HTTP探针,TCP探针等,可以在系统或者服务在发生故障时能够快速通知相关的人员进行处理。通过建立完善的监控体系,从而达到以下目的:

  • 长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。
  • 对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况下系统的并发和负载变化如何?通过监控能够方便的对系统进行跟踪和比较。
  • 告警:当系统出现或者即将出现故障时,监控系统需要迅速反应并通知管理员,从而能够对问题进行快速的处理或者提前预防问题的发生,避免出现对业务的影响。
  • 故障分析与定位:当问题发生后,需要对问题进行调查和处理。通过对不同监控监控以及历史数据的分析,能够找到并解决根源问题。
  • 数据可视化:通过可视化仪表盘能够直接获取系统的运行状态、资源使用情况、以及服务运行状态等直观的信息。

黑盒监控和白盒监控

img

黑盒监控:主要关注的现象,一般都是正在发生的东西,例如出现一个告警,业务接口不正常,那么这种监控就是站在用户的角度能看到的监控,重点在于能对正在发生的故障进行告警。

白盒监控:主要关注的是原因,也就是系统内部暴露的一些指标,例如redis的info中显示redis slave down,这个就是redis info显示的一个内部的指标,重点在于原因,可能是在黑盒监控中看到redis down,而查看内部信息的时候,显示redis port is refused connection。

3.Prometheus

Prometheus:不仅是一款时间序列数据库,在整个生态上还是一套完整的监控系统,可以用作对k8s的资源进行监控。

特点:

  • 通过PromQL实现多维度数据模型的灵活查询。

  • 定义了开放指标数据的标准,自定义探针(如Exporter等),编写简单方便。

  • PushGateway组件让这款监控系统可以接收监控数据。

  • 提供了VM和容器化的版本。

    尤其是第一点,这是很多监控系统望尘莫及的。多维度的数据模型和灵活的查询方式,使监控指标可以关联到多个标签,并对时间序列进行切片和切块,以支持各种图形、表格和告警场景。

1.官方架构图

img

2 组件介绍

2.1 Prometheus Server

用于收集和存储时间序列数据。Prometheus Server 是 Prometheus 组件中的核心部分,负责实现对监控数据的获取,存储以及查询。 Prometheus Server 可以通过静态配置管理监控目标,也可以配合使用 Service Discovery 的方式动态管理监控目标,并从这些监控目标中获取数据。其次 Prometheus Server 需要对采集到的监控数据进行存储,Prometheus Server 本身就是一个时序数据库,将采集到的监控数据按照时间序列的方式存储在本地磁盘当中。最后Prometheus Server 对外提供了自定义的 PromQL 语言,实现对数据的查询以及分析。

2.2 Exporter

用于暴露已有的第三方服务的 metrics 给 Prometheus。Exporter 将监控数据采集的端点通过 HTTP 服务的形式暴露给 Prometheus Server,Prometheus Server 通过访问该 Exporter 提供的 Endpoint 端点,即可获取到需要采集的监控数据。

2.3 Push Gateway

主要用于短期的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。为此,这些 jobs 可以直接向 Prometheus server 端推送它们的 metrics。

2.4 Grafana

第三方展示工具,可以编写 PromQL 查询语句,通过 http 协议与 prometheus 集成。

2.5 AlertManager

从 Prometheus Server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对方的接受方式,发出报警。常见的接收方式有:电子邮件,钉钉、企业微信,pagerduty等。

2.6 Client Library

客户端库,为需要监控的服务生成相应的 metrics 并暴露给 Prometheus Server。当 Prometheus Server 来 pull 时,直接返回实时状态的 metrics。

3 Prometheus工作流程

指标采集:prometheus server 通过 pull 形式采集监控指标,可以直接拉取监控指标,也可以通过 pushgateway 做中间环节,监控目标先 push 形式上报数据到 pushgateway;
指标处理:prometheus server 将采集的数据存储在自身 db 或者第三方 db;
指标展示:prometheus server 通过提供 http 接口,提供自带或者第三方展示系统;
指标告警:prometheus server 通过 push 告警信息到 alert-manager,alert-manager 通过”静默-抑制-整合-下发”4个阶段处理通知到观察者。

4 Prometheus四种指标分类

Counter

计数器类型,只增不减,如机器的启动时间,HTTP 访问量等。机器重启不会置零,在使用这种指标类型时,通常会结合rate()方法获取该指标在某个时间段的变化率。

Gauge

仪表盘,可增可减,如CPU使用率,大部分监控数据都是这种类型的。

Summary

客户端定义;Summary,Histogram 都属于高级指标,用于凸显数据的分布情况。

Histogram

服务端定义,相比 Summary 性能更好,反应了某个区间内的样本数。

5.prometheus修改数据保留时间

—storage.tsdb.retention

该参数决定何时删除旧数据,默认为15天。
在启动脚本里更改--storage.tsdb.retention=90d可以延长,或者启动时带上这个参数即可。

6.修改抓取信息周期

1
2
3
global:
scrape_interval: 60s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 60s # Evaluate rules every 15 seconds. The default is every 1 minute.

Prometheus以scrape_interval(默认为1m)规则周期,从监控目标上收集信息。其中scrape_interval可以基于全局或基于单个metric定义;然后将监控信息持久存储在其本地存储上。

Prometheus以evaluation_interval(默认为1m)另一个独立的规则周期,对告警规则做定期计算。其中evaluation_interval只有全局值;然后更新告警状态。

其中包含三种告警状态:

inactive:没有触发阈值

pending:已触发阈值但未满足告警持续时间

firing:已触发阈值且满足告警持续时间

举一个例子,阈值告警的配置如下:

img

收集到的mysql_uptime>=30,告警状态为inactive

收集到的mysql_uptime<30,且持续时间小于10s,告警状态为pending

收集到的mysql_uptime<30,且持续时间大于10s,告警状态为firing

⚠ 注意:配置中的for语法就是用来设置告警持续时间的;如果配置中不设置for或者设置为0,那么pending状态会被直接跳过。

那么怎么来计算告警阈值持续时间呢,需要回到上文的scrape_interval和evaluation_interval,假设scrape_interval为5s采集一次信息;evaluation_interval为10s;mysql_uptime告警阈值需要满足10s持续时间。

img

如上图所示:

Prometheus以5s(scrape_interval)一个采集周期采集状态;

然后根据采集到状态按照10s(evaluation_interval)一个计算周期,计算表达式;

表达式为真,告警状态切换到pending;

下个计算周期,表达式仍为真,且符合for持续10s,告警状态变更为active,并将告警从Prometheus发送给Altermanger;

下个计算周期,表达式仍为真,且符合for持续10s,持续告警给Altermanger;

直到某个计算周期,表达式为假,告警状态变更为inactive,发送一个resolve给Altermanger,说明此告警已解决。

4.监控kafka和redis

1.上传镜像

上传kafka_exporter.tar,redis_exporter.tar

arc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cd /tmp/prom
ls
docker load < kafka_exporter.tar
docker load < redis_exporter.tar
docker tag danielqsj/kafka-exporter:latest 172.31.10.118/monitor/kafka-exporter:v1.0

docker tag prom/grafana 172.31.70.135:8443/prom/grafana:v1.0
docker push 172.31.70.135:8443/prom/grafana:v1.0
docker tag prom/node-exporter:v0.15.2 172.31.70.135:8443/prom/node-exporter:v0.15.2
docker push 172.31.70.135:8443/prom/node-exporter:v0.15.2

docker tag prom/prometheus:v2.2.1 172.31.70.135:8443/prom/prometheus:v2.2.1
docker push 172.31.70.135:8443/prom/prometheus:v2.2.1

docker tag oliver006/redis_exporter:latest 172.31.10.118/monitor/redis_exporter:v1.0
docker login 172.31.10.118
docker push 172.31.10.118/monitor/kafka-exporter:v1.0
docker push 172.31.10.118/monitor/redis_exporter:v1.0

2.docker部署kafka_exporter

在172.31.10.127上

1
docker run -d --restart=always --net=host --name kafka_exporter 172.31.10.118/monitor/kafka-exporter:v1.0 --kafka.server=172.31.10.127:9092

3.docker部署redis_exporter

在172.31.10.123上

1
docker run -d --name redis_exporter -p 9121:9121 172.31.10.118/monitor/redis_exporter:v1.0 --redis.addr 172.31.10.123:6379 --redis.password 'redis密码'

4.修改Prometheus配置

1
kubectl edit cm -n monitoring monitor-prometheus-server

增加配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    - alert: RedisDown
expr: redis_up == 0
for: 5m
labels:
severity: error
annotations:
summary: "Redis down (instance {{ $labels.instance }})"
description: "Redis 挂了啊,mmp\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: MissingBackup
expr: time() - redis_rdb_last_save_timestamp_seconds > 60 * 60 * 24
for: 5m
labels:
severity: error
annotations:
summary: "Missing backup (instance {{ $labels.instance }})"
description: "Redis has not been backuped for 24 hours\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
- alert: OutOfMemory
expr: redis_memory_used_bytes / redis_total_system_memory_bytes * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "Out of memory (instance {{ $labels.instance }})"
description: "Redis is running out of memory (> 90%)\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"

- alert: 告警!Kafka Topics 副本数少于3
expr: sum(kafka_topic_partition_in_sync_replica) by (topic) < 3
for: 0m
labels:
severity: 严重告警
annotations:
summary: "{{ $labels.instance }} Kafka topics 副本数少于3"
description: "Kafka topic 分区不同步\n 当前值 = {{ $value }}"

- alert: 告警!KafkaConsumersGroup
expr: sum(kafka_consumergroup_lag) by (consumergroup) > 50
for: 1m
labels:
severity: 严重告警
annotations:
summary: "{{ $labels.instance }} Kafka consumers group"
description: "Kafka consumers group\n 当前值 = {{ $value }}"

- job_name: 'kafka'
scrape_interval: 30s
static_configs:
- targets: ['172.31.10.127:9308']
- job_name: 'redis'
scrape_interval: 30s
static_configs:
- targets: ['172.31.10.123:9121']

5.增加grafana仪表盘

kafka的模板id:12326

redis的模板id:11692

5.node_exporter和process_exporter

1.docker部署node_exporter和process_exporter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#登录harbor
docker login -u admin -p Harbor12345 172.31.10.118

# 启动node-exporter
docker run -d --name node-exporter --restart=always -p 9100:9100 -v "/proc:/host/proc:ro" -v "/sys:/host/sys:ro" -v "/:/rootfs:ro" 172.31.10.118/monitor/node-exporter:v0.18.1

# 启动process-exporter
docker run --restart=always -tid -p 9256:9256 --privileged -v /proc:/host/proc -v `pwd`:/config --name process-exporter 172.31.10.118/monitor/process-exporter:0.7.1 --procfs /host/proc -config.path /config/process-name.yaml

vi process.yml

process_names:
- name: "{{.Matches}}"
cmdline:
- 'mysqld'

process_names:
- name: "{{.Matches}}"
cmdline:
- 'nginx'

- name: "{{.Matches}}"
cmdline:
- 'keepalived'

2.prometheus添加对应配置

1
2
3
kubectl edit cm -n monitoring monitor-prometheus-server
#热部署Prometheus
curl -X POST http://172.31.10.113:41000/-/reload

6.自定义exporter

client_java是Prometheus针对JVM类开发语言的client library库,我们可以直接基于client_java用户可以快速实现独立运行的Exporter程序,也可以在我们的项目源码中集成client_java以支持Prometheus。

e.g. 检查安全隐患的level和flowStatus是否一致

1.添加依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/io.prometheus/simpleclient -->
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.16.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public List<MetricFamilySamples> collect() {
List<MetricFamilySamples> mfs = new ArrayList<>();

String metricName = "risk_level_error_num_guage";

// Your code to get metrics
String sql = "SELECT\n" +
"\tpotential_risk.flow_status, \n" +
"\tpotential_risk.`level`\n" +
"FROM\n" +
"\tpotential_risk\n" +
"WHERE\n" +
"\tpotential_risk.yn_agree = 1";
Conn c = new Conn();
try {
c.getConnection(); // 调用连接数据库的方法

Statement st = c.getCon().createStatement();
ResultSet rs = st.executeQuery(sql);
// 根据结果集进行遍历,id,door_name,tel字段是数据库对应的字段,需要注意字段对应的类型
Integer num = 0;
ArrayList<MetricFamilySamples.Sample> samples1 = new ArrayList<>();
while (rs.next()) {
String flowStatus = rs.getString(1);
String level = rs.getString(2);
if (StringUtils.isNotEmpty(level)) {
String levelNum = getLevelNum(level);
if (!flowStatus.equals(levelNum)){
num++;
}
} else {
num++;
}
}
rs.close();
st.close();
c.getCon().close();

MetricFamilySamples.Sample sample = new MetricFamilySamples.Sample(metricName, Collections.singletonList("l1"), Collections.singletonList("v1"), num);

MetricFamilySamples samples = new MetricFamilySamples(metricName, Type.GAUGE, "risk that level!=flowStatus", Collections.singletonList(sample));

mfs.add(samples);
} catch (SQLException e) {
e.printStackTrace();
}
return mfs;
}

/**
* 得到层级
*
* @param level level
* @return {@link String}
*/
private static String getLevelNum(String level) {
switch (level) {
case ROLE_CODE_LEVEL_GROUP:
return "15";
case ROLE_CODE_LEVEL_AIRPORT:
return "13";
case ROLE_CODE_LEVEL_DEPARTMENT:
return "7";
case ROLE_CODE_LEVEL_OFFICE:
return "3";
default:
break;
}
return null;
}

image-20230418094550731

和zabbix比较:

zabbix使用sql的结果告警,对于判断逻辑比较复杂,不好使用sql写出来,要用代码写的告警不容易实现,就可以用Prometheus的自定义exporter

image-20230418100340060

image-20230418100405064

7.相关资料链接

Introduction · Prometheus中文技术文档

概述 |普罗 米修斯 (prometheus.io)

Google 如何运行 |《Google SRE》中文版 - 知乎 (zhihu.com)

为什么说 Prometheus 是足以取代 Zabbix 的监控神器? - 知乎 (zhihu.com)

Prometheus监控系列三 | 架构详解prometheus架构程序猿Simon的博客-CSDN博客

Prometheus的架构和操作介绍+K8S的部署+HPA的创建+资源限制prometheus hpa迷雾总会解的博客-CSDN博客

Prometheus一条告警是怎么触发的_evaluation_interval_ActionTech的博客-CSDN博客