目录

什么是Prometheus?

Prometheus是继Kubernetes之后,第二个从云原生计算基金会(CNCF)GA的项目。Kubernetes是Google容器编排引擎Borg的开源版本,而Prometheus则是Google监控系统BorgMon类似实现的开源版,二者都是云原生基础设施的基石,本系列就是对Prometheus监控告警系统相关技术做一次总结分享。

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

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

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

为什么需要Prometheus?

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

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

如何快速使用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
todo

然后,把配置文件放到对应路径(/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并不是一个好办法,这里只是方便入门使用,屏蔽了容器网络互通的复杂技术细节

运行成功之后,在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返回一个文本响应,每个非注释行包含一条完整的时序数据:Name + Labels + Samples,Samples由一个浮点数和一个时间戳构成
  • Prometheus Server收到响应,Relabel处理之后(relabel_configs),存储TSDB,建立倒排索引
  • Prometheus Server 另一个周期计算任务(evaluation_interval)开始执行,根据配置的Rules逐个计算,若结果超过阈值并持续时长超过临界点,发送Alert到AlertManager
  • AlertManager 收到告警请求,根据配置的策略决定是否需要触发告警,如需告警则根据配置的路由链路依次发送告警,比如邮件,微信,Slack,PagerDuty,WebHook等等。
  • 当通过界面或HTTP调用查询时序数据时,传入一个PromQL表达式,Prometheus Server处理过滤完之后,返回瞬时向量 (Instant vector, N条只有一个Sample的时序数据),区间向量 (Range vector,N条包含M个Sample的时序数据),或标量数据 (Scalar, 一个浮点数)

// todo pic

这么多概念,入门不需要完全理解,后面讲原理再深入。其实Prometheus的关键组件还有一个Push Gateway,用来将传统的Agent Push上传的监控数据、或短期Job的监控数据,收集并转换成HTTP端点让Prometheus刮取,因为不是普适场景,这里不展开讨论。

PromQL语法简介及示例

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

常用聚合函数

todo

Alert配置和集成

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

  • Prometheus中配置Rules决定原始Alert
  • AlertManager中配置Alert处理策略

第一块决定原始告警是否触发,是需要经常维护的。

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合集

除了硬件指标收集神器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