目录

什么是Prometheus?

Prometheus是继Kubernetes之后,第二个从云原生计算基金会(CNCF)GA的项目Prometheus是Google监控系统BorgMon类似实现的开源版,本系列文章是对Prometheus监控告警系统相关技术的总结。

Prometheus是一个开源的监控告警系统,泛义上包括监控,告警,时序数据库,各种指标收集器(Exporter)组成,是当下云原生监控告警系统的主流选项,Prometheus相比其他监控系统具有这些优势:

  • 开箱即用的各种服务发现机制,可以自动发现监控端点
  • 专为监控指标数据设计的高性能时序数据库TSDB
  • 强大易用的查询语言PromQL以及丰富的聚合函数
  • 配置灵活的告警规则,支持告警分组、抑制、静默、路由等等高级功能
  • 生态完善,有各种现成的开源Exporter实现,自定义的监控指标也非常简单

如果说缺点,比较有争议的两个点:通过HTTP拉取监控数据效率不够高;没有任何监控告警之外的功能(用户/角色/权限控制等等)也许算吧。不过第一个HTTP拉监控数据的效率问题对于绝大多数场景碰不到,第二个问题可以通过二次开发,或者把Prometheus完全作为后端内部应用,只暴露类似Grafana这样具有更强管理和可视化功能的前中端应用来解决。

为什么需要Prometheus?

Prometheus和Kubernetes有很多相通之处,Kubernetes其中一个功能是提供了弹性而动态的部署能力,而Prometheus则提供了动态的监控能力。举个例子:Kubernetes集群里新加了X台机器,Y个服务横向扩容了Z个新的实例,此时Prometheus监控系统的配置需要怎么修改?这个问题是多余的,不需要任何配置修改

Kubernetes集群在扩容物理节点和应用服务实例时是可以不需要任何人工操作的,因为所有的资源对象,调度策略都已经在标准化的编排文件中声明了。搭配云服务器的自适应扩缩容(如AWS的AutoScalingGroup)以及HorizontalPodAutoScaler的应用容器自适应扩缩容,可以获得恐怖的弹性能力和运维自动化水平。这对传统运维(手工执行命令,或工具批量执行脚本)是无法想象的冲击和变革。同样,传统的监控方案如Zabbix,批量执行的脚本在机器中安装agent、agent上传数据给监控服务器这种模式,也因为无法适应这种动态性而逐渐被淘汰,而Prometheus这种能支持动态部署结构的监控系统成为主流。

如何快速使用Prometheus?

安利完了,下面说一下基本使用。官方的Getting Started教程是从二进制文件直接运行开始的,我们来稍微Cloud Native一点的方式开始,直接用Docker启动容器运行。

首先,Prometheus Server和AlertManager两个容器都需要外挂两个Volume,一个存储持久化数据目录,另一个是配置文件,最简单的配置如下。

prometheus.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
global:
evaluation_interval: 30s
scrape_interval: 30s
rule_files:
- /etc/prometheus-data/rules/*.yaml
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['127.0.0.1:9090', '127.0.0.1:9100']
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers:
- path_prefix: /
scheme: http
static_configs:
- targets:
- 127.0.0.1:9093

alertmanager.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
global:
resolve_timeout: 5m
smtp_from: from@example.com
smtp_smarthost: smtp.example.com:587
smtp_auth_username: from@example.com
smtp_auth_password: your_email_password
smtp_require_tls: true
route:
group_by: ['job']
group_wait: 15s
group_interval: 5m
repeat_interval: 12h
receiver: webhook
routes:
- match_re:
severity: warning|error|critical
receiver: email
receivers:
- name: email
email_configs:
- to: your-email@example.com

然后,把配置文件放到对应路径(/opt/prometheus/prometheus.yml, /opt/prometheus/alertmanager.yml)、数据目录(/data/prometheus, /data/alertmanager, /data/grafana)确保读写权限没有问题之后,直接docker run启动如下几个容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Prometheus server & TSDB
docker run --net host \
-v /opt/prometheus/:/etc/prometheus:ro \
-v /data/prometheus:/etc/prometheus-data \
--name prometheus --restart always -d prom/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/etc/prometheus-data \
--storage.tsdb.retention.time=30d --web.enable-lifecycle \
--storage.tsdb.no-lockfile --web.route-prefix=/

# AlertManager
docker run --net host \
-v /opt/prometheus/:/etc/alertmanager/config:ro \
-v /data/alertmanager:/etc/alertmanager
--name alert --restart always -d prom/alertmanager \
--config.file=/etc/alertmanager/config/alertmanager.yml \
--storage.path=/etc/alertmanager \
--data.retention=168h --web.listen-address=:9093 --web.route-prefix=/

# Node Exporter
docker run --name node-exporter --restart always --net host -d prom/node-exporter

# Grafana
docker run -d --restart always --net host --name=grafana -e "GF_SECURITY_ADMIN_PASSWORD=your-admin-password" -v /data/grafana:/var/lib/grafana grafana/grafana

注:使用Host Network容器并不是一个好办法,这里只是方便入门使用,屏蔽了容器网络互通的复杂技术细节。一般直接跑Docker容器也比较少见,后面的文章会陆续讲解如何用Prometheus Operator在Kubernetes集群中搭建Production级别的监控告警系统,以及如何实现高可用架构。

运行成功之后,在localhost的9090端口是Prometheus Server,9093端口是AlertManager,9100端口是Node Exporter,3000端口是Grafana,浏览器打开即可自行探索。

Prometheus的相关概念

经过上面的部署运行,Prometheus的几个关键组件:Prometheus (TSDB + Server),AlertManager,Exporters已经有了直观的认知。在Prometheus的Web页面中输入指标,即可查询指标的当前值,数据是怎么来的呢?整个数据流是这样的:

  • Prometheus Server读取配置,解析静态监控端点(static_configs),以及服务发现规则(xxx_sd_configs)自动收集需要监控的端点
  • Prometheus Server 周期”刮取”(scrape_interval)监控端点的HTTP接口数据
  • Prometheus Server HTTP请求到达Node Exporter,Exporter返回一个文本响应,每个非注释行包含一条完整的时序数据:监控名称 + 一组标签键值对 + 样本数据。例如://todo
  • Prometheus Server收到响应,Relabel处理之后(relabel_configs),存储TSDB,建立倒排索引
  • Prometheus Server 另一个周期计算任务(evaluation_interval)开始执行,根据配置的Rules逐个计算,若结果超过阈值并持续时长超过临界点,发送Alert到AlertManager
  • AlertManager 收到告警请求,根据配置的策略决定是否需要触发告警,如需告警则根据配置的路由链路依次发送告警,比如邮件,企业微信,Slack,PagerDuty,通用的WebHook等等。
  • 当通过界面或HTTP调用查询时序数据时,传入一个PromQL表达式,Prometheus Server处理过滤完之后,返回瞬时向量区间向量 ,或标量数据

术语解释:

  • 样本数据(Sample):由一个浮点数和一个时间戳构成
  • 瞬时向量(Instant vector):某一时刻, N条只有一个Sample的时序数据
  • 区间向量(Range vector):一段时间中:N条包含M个不同时刻Sample的时序数据)
  • 标量数据(Scalar): 一个浮点数,可能是计算出来的单一结果,或是一个单纯的常量

// todo pic

整个流程的细节后面讲原理的时候再深入。其中最关键的点在于:Prometheus是主动发现需要监控的Endpoints,然后主动轮询拉取监控数据,Pull模型代替了传统的Push模型。这种颠覆性的设计,让中心化的Prometheus Server配置如何去发现需要监控的东西,而不是静态地配置有哪些东西需要监控

注:虽然Prometheus的组件还有一个Push Gateway,用来让传统的Agent Push监控数据,但最终也是收集并转换成HTTP端点让Prometheus刮取(Pull),不是普适使用场景所以不展开讨论。

PromQL语法简介及示例

在上面运行的Prometheus Server的Web页面中,直接输入指标名称就可以得到一条瞬时向量,那么我们要查询更复杂的数据怎么办呢?我们简单学习一下PromQL就知道了。相比于类似SQL语法的InfluxDB查询语言,PromQL是更加简单易用的。

常用聚合函数

todo

Alert配置和集成

通过上面对Prometheus数据流的简要理解,我们知道AlertManager只是对收到的Alert做处理,不管Alert是如何触发的。因此告警的配置分两块:

  • 一块在Prometheus中,配置Rules决定原始Alert如何触发
  • 另一块在AlertManager中,配置Alert处理策略

第一块决定原始告警是否触发,是需要经常维护的,而第二块在AlertManager中的配置几乎不用修改,让动态配置和静态配置分离,更易于维护。

Rules的典型的格式如下:

1
todo

开源社区对常用告警需求有整理在一个网站:https://awesome-prometheus-alerts.grep.to/rules,Copy-Paste即可避免重复造轮子了。

第二块告警处理策略一般配置好一次就不会再动了,上面的alertManager.yml是个典型的例子,这里不再赘述,如需了解分组、抑制、静默等高级用法自行查询官方文档。

告警的发送方式有很多,除了官方支持的这些常用的邮件、IM等方式(https://prometheus.io/docs/operating/integrations/),也可以自行开发集成WebHook。我业余时间做了一个集成Zoom的Webhook转换组件,可以将告警直接推送到Zoom群聊中,一键点击开启TroubleShooting Meeting,使用了大半年效果还不错。链接如下:

https://github.com/Code2Life/nodess-apps/tree/master/src/zoom-alert-2.0

//todo pic

常用的Exporter合集

Prometheus根据xxx_sd_config自动发现的监控端点,就是Exporter需要提供监控数据的HTTP接口,Exporter在收到HTTP请求时收集并回应各项监控指标在当前时刻的数据。

除了硬件指标收集的Node Exporter, Prometheus也提供了常用组件的Exporter,比如Mysql Exporter、Consul Exporter、JMX Exporter。在官方提供的Exporter之外,开源社区贡献了更多琳琅满目的组件和框架的各种Exporters,项目主页基本都有配置运行教程,绝大多数都是一行Docker命令或者一个Kubernetes Yaml文件,就可以轻松部署。可以在这里直接查询到需要的Exporter:
https://prometheus.io/docs/instrumenting/exporters

Grafana可视化

Grafana并不属于Prometheus系统,因为它经常搭配Prometheus使用,这里也简单讲解一下基本使用步骤。

  • 启动Grafana容器,创建用户分配权限等等
  • 添加数据源,Configuration->DataSources->Add DataSource填写Prometheus Server的URL
  • 导入Grafana Labs或开源社区的Dashboard,输入ID或者导入JSON文件即可,这里列一些常用的Dashboard以及ID数据:
  • 创建自定义的Dashboard,UI控制完全可视化操作,数据查询支持代码补全,掌握PromQL就可以熟能生巧

注:我在业余时间创建了两个Dashboard贡献到Grafana Labs了,下载量有好几百,还收到一些邮件询问如何集成,看来NodeJS服务监控面板SpringBoot Actuator中扩展Druid数据库连接池监控面板的需求还挺多。

//todo pic