使用Prometheus + Grafana 构建监控可视化系统

监控系统简介

业务监控系统通常包含以下一些组件:

  • 采集:信息源来自log、metrics等。
    • 可以通过定期外围探测、AOP手动织入、字节码自动织入
  • 上报:通过http或者tcp
  • 聚合
  • 存储
  • 可视化、告警

业务监控系统解决了什么问题?

  • 趋势分析:收集长期监控数据,对监控指标进行趋势分析,例如:分析磁盘空间增长率,预测何时进行磁盘扩容。

  • 对照分析:分析不同版本在运行时资源使用情况差异。

  • 告警:当服务出现故障时,监控可以迅速反应并告警。

  • 故障分析与定位:故障发生时,可以通过分析历史数据去定位问题。

  • 数据可视化:通过采集的数据,生成可视化仪表盘。

  • 对于运维:监控CPU、内存、硬盘等使用情况。

  • 对于研发:监控某个异常指标的变化情况,来保证业务的稳定性。

  • 对于产品或运营:关注产品层面:某个活动参加人数的增长情况等

监控系统分为以下五层:

  • 端监控:对网站、APP、小程序等进行端监控,采集页面打开速度、稳定性、外部服务调用成功率等参数。
  • 业务层监控:对业务模块进行监控,采集QPS、DAU、业务接口访问数量等。
  • 应用层监控:对分布式应用进行管理和监控
  • 中间件监控:对中间件进行监控,主要判断组件是否存活。
  • 系统层监控:对操作系统监控,主要包括:CPU、磁盘I/O、网络连接等参数。

Prometheus简介

当前监控系统主要有集中式日志解决方案(ELK)和时序数据库解决方案。监控三要素如下:

  • Metrics:可聚合,带有时间戳的数据。
  • Logging:离散日志,分为有结构和无结构。
  • Tracing:请求域内的调用链。

Prometheus架构

Prometheus的架构图如下所示:

其中各组件功能如下:

  • Prometheus Server:核心部分,负责实现对监控数据的获取,存储以及查询。
    • Retrieval:定时去配置文件中指定target抓取指标数据。(Pull)
    • TSDB:Prometheus内置了时序数据库,存储抓取的指标数据。
    • HTTP Server:提供了HTTP接口进行操作。
  • Jobs/exporters:exporter将监控数据通过HTTP服务的形式暴露给Prometheus Server,其定时进行Pull。
  • Pushgateway:临时性的Job可以将监控数据push到这,Prometheus从Pushgateway拉取数据。
  • AlertManager:告警处理中心。Prometheus支持基于PromQL创建告警规则。
  • Data Visualization:数据可视化,其中Prometheus自带的web UI可以通过PromQL进行查询,通过Grafana可以展示丰富的图表数据。

从上述组件可以看出:Prometheus提供了收集数据->存储数据->处理数据->展示数据这一系列功能,完全适用上述的应用场景。

获取监控数据的两种方式

  • Pull:从监控的target通过轮询获取监控信息。主要是HTTP API。
    • 告警可以按照策略分片,可以做到数据的冷热分离。

主要流程如下:

  1. Prometheus根据配置定期去targets拉取数据。
  2. 当拉取数据大于配置的内存缓冲区时,Prometheus会将数据持久化到磁盘或云端。
  3. Prometheus通过PromQL、API等方式获取数据,同时可以配置rules,当触发条件时,将alert推送到配置的alertmanager。
  4. alertmanager收到告警时,会执行相应的策略。
  • Push:程序主动将数据推送到监控系统中,Prometheus采用gateway实现该方式。
    • 实时性好
    • 由于推送时机的不可预知性,监控系统无法掌握主动性,可能会导致对监控进程产生影响。
    • 增加gateway组件,增加了系统的复杂度。

优缺点

优点:

  • Golang编写,支持云原生,二进制文件直接启动,也支持容器化部署。
  • 支持多种语言的客户端。
  • 支持本地存储和云端存储,单机性能强。
  • 可扩展,使用联邦集群启动多个Prometheus实例来分布式处理。
  • 支持静态文件配置和动态发现等机制。

缺点:

  • 不适用Logging、Tracing等监控。
  • Prometheus数据默认保留15天,适用于追踪近期数据。
  • 本地存储有限,需要考虑第三方存储。
  • 联邦集群没有提供统一的全局视图。

Grafana简介

Grafana是一个可以通过各种图形方式对数据进行可视化的一个开源软件,官网简介如下:

Query, visualize, alert on, and understand your data no matter where it’s stored. With Grafana you can create, explore and share all of your data through beautiful, flexible dashboards.

部署

安装Prometheus Server

1
2
3
4
cd /opt
wget https://github.com/prometheus/prometheus/releases/download/v2.36.1/prometheus-2.36.1.linux-amd64.tar.gz
# 解压后进入目录,运行时指定配置文件和data路径
./prometheus --config.file=prometheus.yml --storage.tsdb.path=/data/prometheus

运行成功后,浏览器访问http://localhost:9090可以看到Prometheus自带的Web UI。可以在此界面通过PormQL查询数据。

注意:在配置prometheus.yml的过程中,可能会出错,可以通过下面的指令检查配置文件的正确性。

./promtool check config prometheus.yml

配置web认证

安装bcryptapt install python3-bcrypt,创建gen-pass.py,文件内容如下:

1
2
3
4
5
6
import getpass
import bcrypt

password = getpass.getpass("password: ")
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed_password.decode())

执行python3 gen-pass.py生成加密的password,创建web.yml并填入下述配置。

1
2
basic_auth_users:
admin: xxx

可以使用./promtool check web-config web.yml对其进行验证。

最后,在运行时,指定web.yml即可。

1
./prometheus --config.file=prometheus.yml --storage.tsdb.path=/data/prometheus --web.config.file=web.yml

安装Node Exporter

Exporter主要是采集数据的组件,Node Exporter是Prometheus官方提供用于采集主机运行指标,例如CPU、内存、硬盘等信息。

1
2
3
4
wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz

# 解压后进入文件夹
./node_exporter

运行成功后,访问http://47.102.201.28:9100/metrics可以看到监控信息。

返回Prometheus,在prometheus.yml中加入如下配置,相当于将node exporter监控数据纳入Prometheus定时抓取任务中。

1
2
3
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

上面的metrics会符合一定的格式,可以通过curl -s http://localhost:9090/metrics | promtool check metrics来对metrics进行检查,这对于自定义Exporter时,检查报错十分有用。

1
2
3
4
5
6
7
8
9
# HELP node_filesystem_size_bytes Filesystem size in bytes.
# TYPE node_filesystem_size_bytes gauge
node_filesystem_size_bytes{device="/dev/vda1",fstype="ext4",mountpoint="/"} 4.2140479488e+10
node_filesystem_size_bytes{device="tmpfs",fstype="tmpfs",mountpoint="/run"} 2.07937536e+08
node_filesystem_size_bytes{device="tmpfs",fstype="tmpfs",mountpoint="/run/lock"} 5.24288e+06
node_filesystem_size_bytes{device="tmpfs",fstype="tmpfs",mountpoint="/run/user/0"} 2.0793344e+08
# HELP node_forks_total Total number of forks.
# TYPE node_forks_total counter
node_forks_total 279283

上面是一段metrics数据,下面简单解释一下:

  • HELP:解释当前指标的含义

  • TYPE:说明当前指标的数据类型。分别有以下几种类型(后续详细介绍)

  • node_filesystem_size_bytes:指标名称。

  • 大括号内部为label,负责对指标做进一步说明。

安装Grafana

  • DashBoard:看板,其中包含多个panel。
  • Panel:图表,每个图表展示
    • 预览区:预览设置的图表。
    • 数据设置区:设置数据源、数据指标等。
      • 查询:设置查询数据的数据源、指标等。
      • 转换:对查询出来的数据进行过滤。
      • 告警:对指标设置告警规则。
    • 图表设置区:设置图表等信息。

监控告警

Prometheus提供了AlertManager来管理告警,我在构建监控系统过程中,使用Grafana配置告警规则,Grafana中的告警,可以结合图表展示出来。

添加邮件配置

Grafana的默认配置文件为conf/default.ini,在其中添加如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
[smtp]
enabled = true
host = smtp.exmail.qq.com:465
user = xxx@qq.com
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
password = xxxx
cert_file =
key_file =
skip_verify = false
from_address = xxx@qq.com //必须与上面的 user 属性一致
from_name = Grafana
ehlo_identity =

配置完成后,重启Grafana。

Alerting-Notification channels添加告警频道填写后可以测试发送。

PormQL

基本概念

时间序列

时间序列(time series)通过metrics name和一组label set来命名的。

样本

Prometheus将所有采集的数据以时间序列保存在内存中的时序数据库(TSDB)中,并定时存储到磁盘上。存储单位是:时间序列(time-series),时间序列按照时间戳和值顺序排放,每条时间序列通过metrics namelabel set唯一指定。

时间序列中的值称为样本(sample),样本基于BigTable设计的格式存储,其由以下三部分组成:

  • 指标(metrics):metrics namelabel set组成。
    • 指标名和标签名必须符合正则[a-zA-Z_:][a-zA-Z0-9_:]*
  • 时间戳(timestamp):64bit
  • 样本值:64bit,float64格式。

数据类型

  • 瞬时向量:一组时间序列,每个序列包含单个样本,共享相同的时间戳。
  • 区间向量:一组时间序列,每个事件序列包含一段时间范围内的样本数据。
  • 标量:一个浮点型的数据值,没有时序。
  • 字符串

Metrics类型

  • Counter:计数器,只增不减,例如:HTTP请求量。
  • Gauge:可增可减的数据,例如:空闲内存情况。
  • Histogram:直方图,对监控指标进行抽样,展示数据分布频率情况。
  • Summary:和直方图类似,区别是summary在客户端完成聚合,Histogram在服务端完成。

基础语法

PormQL是Prometheus内置的数据查询语言,提供了对时间序列数据查询、聚合、运算等支持。

直接输入metrics name可以查询该指标的所有时间序列。

1
http_requests_total

匹配模式

  • =
  • !=
  • ~=

分别是完全匹配、完全不匹配、正则匹配。

1
2
http_requests_total{instance="localhost:9090"}
http_requests_total{environment=~"development",method!="GET"}

范围查询

上述查询的数据都被称为瞬时向量,如果查询过去一段时间范围内的数据,需要使用范围查询,使用时间范围选择器进行定义。

1
2
# 查询最近五分钟的指标数据
http_requests_total{}[5m]

时间选择器支持以下的时间单位:

  • s-秒
  • m-分
  • h-小时
  • d-天
  • w-周
  • y-年

使用offset可以实现时间偏移,如下:

1
2
# 查询昨天一天的数据
http_request_total{}[1d] offset 1d

运算

支持以下运算:

1
2
3
4
5
6
7
8
9
10
数学运算:
+ - * / % ^

布尔运算:
== != > < >= <=

# bool修饰符将结果返回true or false
# 判断http请求量是否超过1000
http_requests_total > bool 1000

集合运算:

  • vector1 and vector2:产生一个新向量,两者交集。
  • vector1 or vector2:两者并集。
  • vector1 unless vector2:vector1中没有vector2的元素。

聚合操作

提供了以下的聚合函数:

1
sum()、min()、max()、avg()、stddev(标准差)、stdvar(标准方差)、count()、count_values(对value进行计数)、bottomk(后n条时序)、topk(前n条时序)、quantile(分位数)

without用于从结果中移除指定标签,by则是只保留列出的标签,其他全部移除。

1
sum(http_requests_total) without (instance)

Exporter

Exporter是Prometheus中提供监控数据的程序,每个exporter的实例被称为target,Prometheus通过轮询的方式定期从target中获取数据。

Prometheus官方提供了主流产品的Exporter程序,同时可以基于其提供的Client Library创建自己的Exporter。官方支持语言有:Go、Java、Python、Ruby。

Java自定义Exporter

TODO

存储

Prometheus 2.x使用字定义的存储格式将数据存储在磁盘中,两小时内的数据存储在一个block中,每个block包含该时间段内所有chunks(样本数据)、metadata(元数据)、index(索引)。

收集的样本数据首先保存在内存,使用WAL机制防止丢失数据。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!