搭建基于 Prometheus、Grafana 和 Alertmanager 的监控告警系统

发布于:2025-06-16 ⋅ 阅读:(21) ⋅ 点赞:(0)

目录

文章笔记来自于视频 https://www.bilibili.com/video/BV1HT4y1Z7vR,相关资料可在该视频的评论区获取。

1.Prometheus 入门

(1)Prometheus 受启发于 Google 的 Brogmon 监控系统(相似的 Kubernetes 是从 Google的 Brog 系统演变而来),从 2012 年开始由前 Google 工程师在 Soundcloud 以开源软件的形式进行研发,并且于 2015 年早期对外发布早期版本。其官方网址为:https://prometheus.io/

(2)2016 年 5 月继 Kubernetes 之后成为第二个正式加入 CNCF 基金会的项目,同年 6 月正式发布 1.0 版本。2017 年底发布了基于全新存储层的 2.0 版本,能更好地与容器平台、
云平台配合。

(3)Prometheus 作为新一代的云原生监控系统,目前已经有超过 650+位贡献者参与到Prometheus 的研发工作上,并且超过 120+项的第三方集成。

1.1.Prometheus 的特点

Prometheus 是一个开源的完整监控解决方案,其对传统监控系统的测试和告警模型进行了彻底的颠覆,形成了基于中央化的规则计算、统一分析和告警的新模型。 相比于传统监控系统,Prometheus 具有以下优点:

1.1.1 易于管理

  • Prometheus 核心部分只有一个单独的二进制文件,不存在任何的第三方依赖(数据库,缓存等等)。唯一需要的就是本地磁盘,因此不会有潜在级联故障的风险。
  • Prometheus 基于 Pull 模型的架构方式,可以在任何地方(本地电脑,开发环境,测试环境)搭建我们的监控系统。
  • 对于一些复杂的情况,还可以使用 Prometheus 服务发现 (Service Discovery) 的能力动态管理监控目标。

1.1.2 监控服务的内部运行状态

Pometheus 鼓励用户监控服务的内部状态,基于 Prometheus 丰富的 Client 库,用户可以轻松的在应用程序中添加对 Prometheus 的支持,从而让用户可以获取服务和应用内部真正的运行状态。

在这里插入图片描述

1.1.3 强大的数据模型

所有采集的监控数据均以指标 (metric) 的形式保存在内置的时间序列数据库当中 (TSDB)。所有的样本除了基本的指标名称以外,还包含一组用于描述该样本特征的标签。如下所示:

http_request_status{code='200',content_path='/api/path',environment='produment'} => [value1@timestamp1,value2@timestamp2...]
http_request_status{code='200',content_path='/api/path2',environment='produment'} => [value1@timestamp1,value2@timestamp2...]

每一条时间序列由指标名称 (Metrics Name) 以及一组标签 (Labels) 唯一标识。每条时间序列按照时间的先后顺序存储一系列的样本值。

  • http_request_status:指标名称(Metrics Name)。
  • {code='200',content_path='/api/path',environment='produment'}:表示维度的标签,基于这些 Labels 我们可以方便地对监控数据进行聚合,过滤,裁剪。
  • [value1@timestamp1,value2@timestamp2...]:按照时间的先后顺序 存储的样本值。

TSDB (Time Series Database) 是专门用于存储、处理和查询时间序列数据的数据库系统,它相比传统关系型数据库在处理时间序列数据时通常能提供更好的性能和更高的存储效率。

1.1.4 强大的查询语言 PromQL

Prometheus 内置了一个强大的数据查询语言 PromQL。 通过 PromQL 可以实现对监控数据的查询、聚合。同时 PromQL 也被应用于数据可视化(如 Grafana)以及告警当中。通过 PromQL 可以轻松回答类似于以下问题:

  • 在过去一段时间中 95% 应用延迟时间的分布范围?
  • 预测在 4 小时后,磁盘空间占用大致会是什么情况?
  • CPU 占用率前 5 位的服务有哪些?(过滤)

1.1.5 高效

对于监控系统而言,大量的监控任务必然导致有大量的数据产生。而 Prometheus 可以高效地处理这些数据,对于单一 Prometheus Server 实例而言它可以处理:

  • 数以百万的监控指标;
  • 每秒处理数十万的数据点;

1.1.6.可扩展

可以在每个数据中心、每个团队运行独立的 Prometheus Sevrer。Prometheus 对于联邦集群的支持,可以让多个 Prometheus 实例产生一个逻辑集群,当单实例 Prometheus Server 处理的任务量过大时,通过使用功能分区 (sharding) + 联邦集群 (federation) 可以对其进行扩展。

1.1.7 易于集成

(1)使用 Prometheus 可以快速搭建监控服务,并且可以非常方便地在应用程序中进行集成。目前支持:Java,JMX,Python,Go,Ruby,.Net,Node.js 等等语言的客户端 SDK,基于这些 SDK 可以快速让应用程序纳入到 Prometheus 的监控当中,或者开发自己的监控
数据收集程序。

(2)同时这些客户端收集的监控数据,不仅仅支持 Prometheus,还能支持 Graphite 这些其他的监控工具。

(3)同时 Prometheus 还支持与其他的监控系统进行集成:Graphite,Statsd,Collected,Scollector, muini, Nagios 等。 Prometheus 社区还提供了大量第三方实现的监控数据采集支持:JMX,CloudWatch,EC2,MySQL,PostgresSQL,Haskell,Bash,SNMP,Consul,Haproxy,Mesos,Bind,CouchDB,Django,Memcached,RabbitMQ,Redis,RethinkDB,Rsyslog 等等。

1.1.8 可视化

  • Prometheus Server 中自带的 Prometheus UI,可以方便地直接对数据进行查询,并且支持直接以图形化的形式展示数据。同时 Prometheus 还提供了一个独立的基于 Ruby On Rails 的 Dashboard 解决方案 Promdash。
  • 最新的 Grafana 可视化工具也已经提供了完整的 Prometheus 支持,基于 Grafana 可以创建更加精美的监控图标。
  • 基于 Prometheus 提供的 API 还可以实现自己的监控可视化 UI。

1.1.9 开放性

(1)通常来说当我们需要监控一个应用程序时,一般需要该应用程序提供对相应监控系统协议的支持,因此应用程序会与所选择的监控系统进行绑定。为了减少这种绑定所带来的限制,对于决策者而言要么你就直接在应用中集成该监控系统的支持,要么就在外部创建单独的服
务来适配不同的监控系统。

(2)而对于 Prometheus 来说,使用 Prometheus 的 client library 的输出格式不止支持 Prometheus 的格式化数据,也可以输出支持其它监控系统的格式化数据,比如 Graphite。因此你甚至可以在不使用 Prometheus 的情况下,采用 Prometheus 的 client library 来让你的应用程序支持监控数据采集。

1.2 Prometheus 的架构

Prometheus 的架构如下图所示:

在这里插入图片描述

简化后的一个实例如下:

在这里插入图片描述

1.2.1.Prometheus 生态圈组件

  • Prometheus Server:主服务器,负责收集和存储时间序列数据;
  • client libraies:应用程序代码插桩,将监控指标嵌入到被监控应用程序中;
  • Pushgateway:推送网关,为支持 short-lived 作业提供一个推送网关;
  • exporter:专门为一些应用开发的数据摄取组件—exporter,例如:HAProxy、StatsD、Graphite 等等;
  • Alertmanager:专门用于处理 alert 的组件;

1.2.2.架构理解

Prometheus 既然设计为一个维度存储模型,可以把它理解为一个 OLAP 系统。

OLAP (Online Analytical Processing,联机分析处理) 是一种用于快速分析多维数据的计算机处理技术,专为复杂的分析查询和数据挖掘而设计。

1.2.2.1.存储计算层
  • Prometheus Server,里面包含了存储引擎和计算引擎。
  • Retrieval 组件:取数组件,它会主动从 Pushgateway 或者 Exporter 拉取指标数据。
  • Service discovery:可以动态发现要监控的目标。
  • TSDB:数据核心存储与查询。
  • HTTP Server:对外提供 HTTP 服务。
1.2.2.2.采集层

采集层分为两类,一类是生命周期较短的作业,还有一类是生命周期较长的作业。

  • 短作业:直接通过 API,在退出时间指标推送给 Pushgateway。
  • 长作业:Retrieval 组件直接从 Job 或者 Exporter 拉取数据。
1.2.2.3.应用层

应用层主要分为两种,一种是 AlertManager,另一种是数据可视化。

(1)AlertManager:对接 Pagerduty,是一套付费的监控报警系统。可实现短信报警、5 分钟无人 ack 打电话通知、仍然无人 ack,通知值班人员 Manager、发送邮件等;

(2)数据可视化:Prometheus build-in WebUI、Grafana、其他基于 API 开发的客户端;

2.Prometheus 安装

(1)下载 Prometheus 相关安装包的官方网址为:https://prometheus.io/download/

(2)这里我们将视频资料中的包上传至 /opt/software 目录下:

在这里插入图片描述

2.1.安装 Prometheus Server

Prometheus 基于 Golang 编写,编译后的软件包,不依赖于任何的第三方依赖。只需要下载对应平台的二进制包,解压并且添加基本的配置即可正常启动 Prometheus Server。

2.1.1.解压安装包

(1)在 /opt/software 目录下执行下面的解压命令:

# -C ../module 表示指定解压到的目标目录,即 /opt/module(需要提前创建好)
tar -zxvf prometheus-2.29.1.linux-amd64.tar.gz -C ../module
cd /opt/module

在这里插入图片描述

(2)修改目录名,具体命令如下:

mv prometheus-2.29.1.linux-amd64 prometheus-2.29.1

2.1.2.修改配置文件 prometheus.yml

进入到 prometheus-2.29.1 目录下:

在这里插入图片描述

vim /opt/module/prometheus-2.29.1/prometheus.yml

scrape_configs 配置项下添加配置:

scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["192.168.101.65:9090"]
  
  # 添加 PushGateway 监控配置
  - job_name: 'pushgateway'
    static_configs:
      - targets: ['192.168.101.65:9091']
    labels:
      instance: pushgateway

  # 添加 Node Exporter 监控配置
  - job_name: 'node exporter'
    static_configs:
      - targets: ['192.168.101.65:9100', '192.168.101.65:9100', '192.168.101.65:9100']

  # 添加 MySQLId Export 监控配置
  - job_name: 'mysqlId export'
    static_configs:
      - targets: ['192.168.101.65:9104']

配置说明如下(更加详细的配置说明见官方文档:https://prometheus.io/docs/prometheus/latest/configuration/configuration/):

  • global 配置块:控制 Prometheus 服务器的全局配置
    • scrape_interval:配置拉取数据的时间间隔,默认为 1 分钟
    • evaluation_interval:规则验证(生成 alert)的时间间隔,默认为 1 分钟
  • rule_files 配置块:规则配置文件
  • scrape_configs 配置块:配置采集目标相关, prometheus 监视的目标。Prometheus 自身的运行信息可以通过 HTTP 访问,所以 Prometheus 可以监控自己的运行数据
    • job_name:监控作业的名称
    • static_configs:表示静态目标配置,就是固定从某个 target 拉取数据
    • targets: 指定监控的目标, 其实就是从哪儿拉取数据。Prometheus 会 从 http://192.168.101.65:9090/metrics 上拉取数据。

Prometheus 是可以在运行时自动加载配置的,在启动命令中需要添加:–web.enable-lifecycle。

2.2.安装 Pushgateway

(1)Prometheus 在正常情况下是采用 Pull 模式从产生 metric 的作业或者 exporter(比如专门监控主机的 NodeExporter)拉取监控数据。但是我们要监控的是 Flink on YARN 作业,想要让 Prometheus 自动发现作业的提交、结束以及自动拉取数据显然是比较困难的。PushGateway 就是一个中转组件,通过配置 Flink on YARN 作业将 metric 推到 PushGateway,Prometheus 再从 PushGateway 拉取就可以了。

(2)将 pushgateway-1.4.1.linux-amd64.tar.gz 解压到 /opt/module 目录下,具体命令如下:

cd /opt/software
tar -zxvf pushgateway-1.4.1.linux-amd64.tar.gz -C /opt/module

(3)修改目录名:

cd /opt/module
mv pushgateway-1.4.1.linux-amd64 pushgateway-1.4.1

2.3.安装 Alertmanager

(1)将 alertmanager-0.23.0.linux-amd64.tar.gz 解压到 /opt/module 目录下,具体命令如下:

cd /opt/software
tar -zxvf alertmanager-0.23.0.linux-amd64.tar.gz -C /opt/module

(2)修改目录名:

cd /opt/module
mv alertmanager-0.23.0.linux-amd64 alertmanager-0.23.0

2.4.安装 Node Exporter

(1)在 Prometheus 的架构设计中,Prometheus Server 主要负责数据的收集,存储并且对外提供数据查询支持,而实际的监控样本数据的收集则是由 Exporter 完成。因此为了能够监控到某些东西,如主机的 CPU 使用率,我们需要使用到 Exporter。Prometheus 周期性的从 Exporter 暴露的 HTTP 服务地址(通常是 /metrics)拉取监控样本数据。

Exporter 可以是一个相对开放的概念,其可以是一个独立运行的程序独立于监控目标以外,也可以是直接内置在监控目标中。只要能够向 Prometheus 提供标准格式的监控样本数据即可。

为了能够采集到主机的运行指标如 CPU、内存、磁盘等信息。我们可以使用 Node Exporter。Node Exporter 同样采用 Golang 编写,并且不存在任何的第三方依赖,只需要下载,解压即可运行。可以从 https://prometheus.io/download/ 获取最新的 Node Exporter 版本的二进制包。

2.4.1.解压安装包

(1)将 node_exporter-1.2.2.linux-amd64.tar.gz 解压到 /opt/module 目录下,具体命令如下:

cd /opt/software
tar -zxvf node_exporter-1.2.2.linux-amd64.tar.gz -C /opt/module

(2)修改目录名:

cd /opt/module
mv node_exporter-1.2.2.linux-amd64 node_exporter-1.2.2

(3)启动并通过页面查看是否成功,执行命令:

cd /opt/module/node_exporter-1.2.2
./node_exporter

浏览器中输入 http://192.168.101.65:9100/metrics,可以看到当前 Node Exporter 获取到的当前主机的所有监控数据:

在这里插入图片描述

2.4.2.节点分发

(1)将解压后的目录分发到要监控的节点:

xsync node_exporter-1.2.2

(2)修改 Prometheus 配置文件 prometheus.yml,在 2.1.2 的时候已经添加过配置:

- targets: ['192.168.101.65:9100', '192.168.101.65:9100', '192.168.101.65:9100']

2.4.3.设置为开机自启

(1)创建 service 文件

sudo vim /usr/lib/systemd/system/node_exporter.service

[Unit]
Description=node_export
Documentation=https://github.com/prometheus/node_exporter
After=network.target
[Service]
Type=simple
User=root
ExecStart= /opt/module/node_exporter-1.2.2/node_exporter
Restart=on-failure
[Install]
WantedBy=multi-user.target

(2)分发文件

sudo /home/root/bin/xsync
/usr/lib/systemd/system/node_exporter.service

(3)设为开机自启动(所有机器都执行)

sudo systemctl enable node_exporter.service

(4)启动服务(所有机器都执行)

sudo systemctl start node_exporter.service

2.5.安装 MySQLId Exporter

2.5.1.解压安装包

(1)将 mysqld_exporter-0.13.0.linux-amd64.tar.gz 解压到 /opt/module 目录下,具体命令如下:

cd /opt/software
tar -zxvf mysqld_exporter-0.13.0.linux-amd64.tar.gz -C /opt/module

(2)修改目录名:

cd /opt/module
mv mysqld_exporter-0.13.0.linux-amd64 mysqld_exporter-0.13.0

选择版本的下载地址为:https://github.com/prometheus/mysqld_exporter/releases/tag/v0.13.0

2.5.2.创建监控用户并授权

(1)在 Linux 终端中,使用以下命令以 root 或具有管理员权限的用户登录 MySQL,输入密码后进入 MySQL 命令行界面(确保已经安装 MySQL):

mysql -u root -p

在这里插入图片描述

(2)创建一个专用于监控的用户(例如 monitor_user),并授予最小必要的权限(通常只需 PROCESSREPLICATION CLIENTSELECT 等权限):

-- 创建用户
CREATE USER 'monitor_user'@'localhost' IDENTIFIED BY '123456';
-- 授权
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'monitor_user'@'localhost';
-- 刷新权限
FLUSH PRIVILEGES;
-- 验证权限
SHOW GRANTS FOR 'monitor_user'@'localhost';

(2)命令说明:

  • 'monitor_user'@'localhost':限制用户只能从本地连接。如需远程监控,替换为 ‘%’(如 'monitor_user'@'%'),但需确保配置防火墙和 MySQL 的 bind-address。
  • 权限根据监控工具需求调整,例如:
    • PROCESS:查看活跃线程(如 SHOW PROCESSLIST)。
    • REPLICATION CLIENT:检查主从复制状态。
    • SELECT:查询性能模式(如 information_schema)。

2.5.3.配置 MySQL Exporter

(1)创建 /etc/.mysqld_exporter.cnf 文件,存储 MySQL 连接信息:

sudo vim /etc/.mysqld_exporter.cnf

内容如下:

[client]
user=monitor_user
password=123456
host=localhost
port=3306

(2)创建 /etc/systemd/system/mysql_exporter.service

sudo vim /etc/systemd/system/mysql_exporter.service

内容如下:

[Unit]
Description=Prometheus MySQL Exporter								# 服务描述
After=network.target												# 确保在网络就绪后启动

[Service]
Type=simple															# 服务类型为简单进程
Restart=always														# 崩溃后自动重启
ExecStart=/opt/module/mysqld_exporter-0.13.0/mysqld_exporter \		# 主程序路径
  --config.my-cnf=/etc/.mysqld_exporter.cnf \	 					# MySQL 连接配置文件
  --collect.global_status \											# 启用全局状态指标收集
  --collect.info_schema.innodb_metrics \							# 启用 InnoDB 指标收集
  --collect.slave_status \											# 启用主从复制状态收集
  --web.listen-address=:9104										# 监听端口 9104

[Install]
WantedBy=multi-user.target											# 在系统多用户模式下启用该服务

2.5.4.运行 MySQLId Exporter

(1)依次执行如下命令:

# 重新加载 systemd 的配置文件
sudo systemctl daemon-reload
# 启用服务的开机自启动
sudo systemctl enable mysql_exporter
# 立即启动名为 mysql_exporter 的服务
sudo systemctl start mysql_exporter
# 检查服务状态:
sudo systemctl status mysql_exporter

在这里插入图片描述

(2)在浏览器中输入:http://192.168.101.65:9104/metrics,来查看访问指标接口:

在这里插入图片描述

2.6.启动 Prometheus Server、 Pushgateway 和 Alertmanager

2.6.1.Prometheus Server 目录下执行启动命令

cd /opt/module/prometheus-2.29.1
# 后台执行
nohup ./prometheus --config.file=prometheus.yml > ./prometheus.log 2>&1 &
# 查看是否启动成功
ps -ef | grep prometheus

在这里插入图片描述

2.6.2.Pushgateway 目录下执行启动命令

cd /opt/module/pushgateway-1.4.1
# 后台执行
nohup ./pushgateway --web.listen-address :9091 > ./pushgateway.log 2>&1 &

在这里插入图片描述

2.6.3.Alertmanager 目录下执行启动命令

cd /opt/module/alertmanager-0.23.0
nohup ./alertmanager --config.file=alertmanager.yml > ./alertmanager.log 2>&1 &

在这里插入图片描述

在浏览器中输入 http://192.168.101.65:9093/,出现以下页面说明启动成功:

在这里插入图片描述

2.6.4.在浏览器中查看

浏览器中输入 http://192.168.101.65:9090,并选择 Status -> Targets,此时发现 prometheus、pushgateway、node exporter、mysqlId export都是 up 状态,表示安装启动成功:

在这里插入图片描述

3.PromQL 介绍

(1)Prometheus 通过指标名称 (metrics name) 以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而 label 则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤、聚合、统计从而产生新的计算后的一条时间序列。

(2)PromQL (Prometheus Query Language) 是 Prometheus 内置的数据查询语言,其提供对时间序列数据丰富的查询,聚合以及逻辑运算能力的支持。并且被广泛应用在 Prometheus 的日常应用当中,包括对数据查询、可视化、告警处理当中。可以这么说,PromQL 是 Prometheus 所有应用场景的基础,理解和掌握 PromQL 是 Prometheus 入门的第一课。

(3)关于 PromQL 更加详细的信息见官方文档 https://prometheus.io/docs/prometheus/latest/querying/basics/

3.1.基本用法

3.1.1 查询时间序列

(1)当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后,我们就可以通过 PromQL 对监控样本数据进行查询。当我们直接使用监控指标名称查询时,可以查询该指标下的所有时间序列。如:

prometheus_http_requests_total

等同于:

prometheus_http_requests_total{}

该表达式会返回指标名称为 prometheus_http_requests_total 的所有时间序列:

在这里插入图片描述

(2)PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。

  • PromQL 支持使用 = 和 != 两种完全匹配模式:
    • 通过使用 label=value 可以选择那些标签满足表达式定义的时间序列;
    • 反之使用 label!=value 则可以根据标签匹配排除时间序列;

例如,如果我们只需要查询所有 prometheus_http_requests_total 时间序列中满足标签 instancelocalhost:9090 的时间序列,则可以使用如下表达式:

prometheus_http_requests_total{instance="localhost:9090"}

反之使用 instance!="localhost:9090" 则可以排除这些时间序列:

prometheus_http_requests_total{instance!="localhost:9090"}
  • PromQL还可以支持使用正则表达式作为匹配条件,多个表达式之间使用 | 进行分离:
    • 使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列;
    • 反之使用 label!~regx 进行排除;

例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:

prometheus_http_requests_total{environment=~"staging|testing|development",method!="GET"}

排除用法:

prometheus_http_requests_total{environment!~"staging|testing|development",method!="GET"}

3.1.2.范围查询

(1)直接通过类似于 PromQL 表达式 httprequeststotal 查询时间序列时,返回值中只会包含该时间序列中的最新的一个样本值,这样的返回结果我们称之为瞬时向量。而相应的这样的表达式称之为瞬时向量表达式

(2)而如果我们想过去一段时间范围内的样本数据时,我们则需要使用区间向量表达式。区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。 例如,通过以下表达式可以选择最近 5 分钟内的所有样本数据:

prometheus_http_requests_total{}[5m]

该表达式将会返回查询到的时间序列中最近 5 分钟的所有样本数据:

在这里插入图片描述

通过区间向量表达式查询到的结果我们称为区间向量。 除了使用 m 表示分钟以外,PromQL 的时间范围选择器支持其它时间单位:

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

3.1.3.时间位移操作

(1)在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:

  • prometheus_http_requests_total{}:瞬时向量表达式,选择当前最新的数据;
  • prometheus_http_requests_total{}[5m]:区间向量表达式,选择以当前时间为基准,5 分钟内的数据;

(2)而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢?这个时候我们就可以使用位移操作,位移操作的关键字为 offset。 可以使用 offset 时间位移操作:

prometheus_http_requests_total{} offset 5m
prometheus_http_requests_total{}[1d] offset 1d

3.1.4.使用聚合操作

一般来说,如果描述样本特征的标签 (label) 在并非唯一的情况下,通过 PromQL 查询数据,会返回多条满足这些特征维度的时间序列。而 PromQL 提供的聚合操作可以用来对这些时间序列进行处理,形成一条新的时间序列:

# 查询系统所有 http 请求的总量
sum(prometheus_http_requests_total)
# 按照 mode 计算主机 CPU 的平均使用时间
avg(node_cpu_seconds_total) by (mode)
# 按照主机查询各个主机的 CPU 使用率
sum(sum(irate(node_cpu_seconds_total{mode!='idle'}[5m])) / sum(irate(node_cpu_seconds_total [5m]))) by (instance)

3.1.5.标量和字符串

除了使用瞬时向量表达式和区间向量表达式以外,PromQL 还直接支持用户使用标量 (Scalar) 和字符串 (String)。

  • 标量 (Scalar):一个浮点型的数字值,没有时序。 例如 10;需要注意的是,表达式 count(prometheus_http_requests_total) 返回的数据类型,依然是瞬时向量。用户可以通过内置函数 scalar() 将单个瞬时向量转换为标量。
  • 字符串 (String):一个简单的字符串值。直接使用字符串,作为 PromQL 表达式,则会直接返回字符串。例如:
"this is a string" 
'these are unescaped: \n \\ \t' 
`these are not unescaped: \n ' " \t`

3.1.6.合法的 PromQL 表达式

所有的 PromQL 表达式都必须至少包含一个指标名称(例如 http_request_total),或者一个不会匹配到空字符串的标签过滤器(例如 {code=”200”})。因此以下两种方式,均为合法的表达式:

prometheus_http_requests_total 		# 合法
prometheus_http_requests_total{} 	# 合法
{method="get"} 						# 合法

而如下表达式,则不合法:

{job=~".*"} 						# 不合法

同时,除了使用 {label=value} 的形式以外,我们还可以使用内置的 __name__ 标签来指定监控指标名称:

{__name__=~"prometheus_http_requests_total"} 				# 合法
{__name__=~"node_disk_bytes_read|node_disk_bytes_written"} 	# 合法

3.2 PromQL 操作符

使用 PromQL 除了能够方便的按照查询和过滤时间序列以外,PromQL 还支持丰富的操作符,用户可以使用这些操作符对进一步的对事件序列进行二次加工。这些操作符包括:数学运算符,逻辑运算符,布尔运算符等等。

3.2.1.数学运算

PromQL 支持的所有数学运算符有:+(加法)、-(减法) 、*(乘法)、/(除法)、%(求余)、^(幂运算)。

3.2.2.布尔运算

(1)Prometheus 支持以下布尔运算符有、==(相等)、!=(不相等)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)。

(2)使用 bool 修饰符改变布尔运算符的行为。布尔运算符的默认行为是对时序数据进行过滤。而在其它的情况下我们可能需要的是真正的布尔结果。例如,只需要 知道当前模块的 HTTP 请求量是否>=1000,如果大于等于1000 则返回 1(true)否则返回 0(false)。这时可以使 用 bool 修饰符改变布尔运算的默认行为。 例如:

prometheus_http_requests_total > bool 1000

使用 bool 修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果 0 或者 1。从而形成一条新的时间序列。

prometheus_http_requests_total{code="200",handler="query",instance="localhost:9090",job="prometheus",method="get"} 1 
prometheus_http_requests_total{code="200",handler="query_range",instance="localhost:9090",job="prometheus",method="get"} 0

同时需要注意的是,如果是在两个标量之间使用布尔运算,则必须使用 bool 修饰符,例如:

2 == bool 2 # 结果为 1

3.2.3.使用集合运算符

(1)使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。目前,Prometheus 支持以下集合运算符:

  • and(并且)
  • or(或者)
  • unless(排除)

(2)举例说明如下:

  • vector1 and vector2 会产生一个由 vector1 的元素组成的新的向量。该向量包含vector1 中完全匹配 vector2 中的元素组成。
  • vector1 or vector2 会产生一个新的向量,该向量包含 vector1 中所有的样本数据,以及 vector2 中没有与 vector1 匹配到的样本数据。
  • vector1 unless vector2 会产生一个新的向量,新向量中的元素由 vector1 中没有与vector2 匹配的元素组成。

3.2.4.操作符优先级

对于复杂类型的表达式,需要了解运算操作的运行优先级。例如,查询主机的 CPU 使用率,可以使用表达式:

100 * (1 - avg (irate(node_cpu_seconds_total{mode='idle'}[5m])) by(job))

其中 irate 是 PromQL 中的内置函数,用于计算区间向量中时间序列每秒的即时增长率。在 PromQL 操作符中优先级由高到低依次为:

  • ^
  • *, /, %
  • +, -
  • ==, !=, <=, =, >
  • and, unless
  • or

3.2.5.PromQL 聚合操作

(1)Prometheus 还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个新的时间序列。

  • sum(求和)
  • min(最小值)
  • max(最大值)
  • avg(平均值)
  • stddev(标准差)
  • stdvar(标准差异)
  • count(计数)
  • count_values(对 value 进行计数)
  • bottomk(后 n 条时序)
  • topk(前 n 条时序)
  • quantile(分布统计)

(2)使用聚合操作的语法如下:

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]

(3)其中只有 count_valuesquantiletopkbottomk 支持参数 (parameter)。without 用于从计算结果中移除列举的标签,而保留其它标签。by 则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过 without 和 by 可以按照样本的问题对数据进行聚合。例如:

sum(prometheus_http_requests_total) without (instance)

等价于

sum(prometheus_http_requests_total) by (code,handler,job,method)

如果只需要计算整个应用的 HTTP 请求总量,可以直接使用表达式:

sum(prometheus_http_requests_total)

(4)count_values 用于时间序列中每一个样本值出现的次数。count_values 会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签。 例如:

count_values("count", prometheus_http_requests_total)

(5)topkbottomk 则用于对样本值进行排序,返回当前样本值前 n 位,或者后 n 位的时间序列。获取 HTTP 请求数前 5 位的时序样本数据,可以使用表达式:

topk(5, prometheus_http_requests_total)

(6)quantile 用于计算当前样本数据值的分布情况 quantile(φ, express),其中 0 ≤ φ ≤ 1。例如,当 φ 为 0.5 时,即表示找到当前样本数据中的中位数:

quantile(0.5, prometheus_http_requests_total)

4.Prometheus 和 Grafana 集成

Grafana 是一款采用 Go 语言编写的开源应用,主要用于大规模指标数据的可视化展现,是网络架构和应用分析中最流行的时序数据展示工具,目前已经支持绝大部分常用的时序数据库。下载地址:https://grafana.com/grafana/download

4.1.上传并解压

grafana-8.1.2.linux-amd64.tar.gz 上传至 /opt/software/ 目录下,并解压:

tar -zxvf grafana-enterprise-8.1.2.linux-amd64.tar.gz -C /opt/module/

4.2.启动 Grafana

cd /opt/module/grafana-8.1.2/bin
nohup ./grafana-server web > ./grafana.log 2>&1 &

在浏览器中输入 http://192.168.101.65:3000,默认用户名和密码均为 admin

在这里插入图片描述

在这里插入图片描述

4.3.添加数据源 Prometheus

点击配置,点击 Data Sources:

在这里插入图片描述

点击添加按钮:

在这里插入图片描述

找到 Prometheus,点击 Select:

在这里插入图片描述

配置 Prometheus Server 地址 http://192.168.101.65:9090

在这里插入图片描述

点击下方的 Save & test:

在这里插入图片描述

出现绿色的提示框,表示与 Prometheus 正常联通:

在这里插入图片描述

点击 Back 返回即可,可以看到 Data Sources 页面,出现了添加的 Prometheus:

在这里插入图片描述

4.4.手动创建仪表盘 Dashboard

(1)点击左边栏的 “+”号,选择 Dashboard:

在这里插入图片描述

添加新的仪表板,点击 Add an empty panel:

在这里插入图片描述

配置仪表板监控项:

在这里插入图片描述

一个仪表板可以配置多个监控项,添加其他监控项:

在这里插入图片描述
(2)保存并查看当前仪表盘监控的指标的操作如下:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(3)新增 row 的操作如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在当前 row 下新建名称为节点文件最大值的 panel,显示效果如下:

在这里插入图片描述

(4)修改 row 信息的操作如下:

在这里插入图片描述

在这里插入图片描述

panel 与 row 的关系:一个 row 可以包含多个 panel。

4.5.导入 DashBoard 模板

(1)手动添加 Dashboard 比较繁琐,Grafana 社区鼓励用户分享 Dashboard,通过官方网站 ,可以找到大量可直接使用的 Dashboard 模板。Grafana 中所有的 Dashboard 通过 JSON 进行共享,下载并且导入这些 JSON 文件,就可以直接使用这些已经定义好的 Dashboard。

(2)例如下载 MySQLId Exporter 模板:

在这里插入图片描述

  • 选择自己需要的 dashBoard,下载 DashBoard 模板(一个 json 格式的文件)

在这里插入图片描述

(3)导入下载的模板

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(4)查看对应的监控指标:

在这里插入图片描述

在这里插入图片描述

4.6.页面配置告警案例

(1)以 MySQL 中的超过慢查询时间阈值的 SQL 语句数量为例,先配置监控指标 mysql_global_status_slow_queries 的告警策略:

在这里插入图片描述

在这里插入图片描述

(2)通过 mysql -u root -p 进入 MySQL 命令行,然后执行如下命令来模拟慢查询:

-- 查询慢查询时间阈值(默认10s)
SHOW VARIABLES LIKE 'long_query_time';
-- 设置开启
SET GLOBAL slow_query_log = 'ON';
-- 模拟慢查询,耗时 12s
SELECT SLEEP(12);

在这里插入图片描述

(3)观察监控指标的 mysql_global_status_slow_queries 变化:

在这里插入图片描述

注意:上面只是配置了告警策略,当监控的指标触发了告警策略时,并不会真正的做任何通知。如果想要达到告警通知效果,需要接入告警服务。

5.Prometheus 和 Alertmanager 集成

5.1.配置 Prometheus 连接 Alertmanager

prometheus.yml 中配置 Alertmanager 的地址:

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['192.168.101.65:9093']  # Alertmanager 地址
        - 
scrape_configs:
  # 添加 Alertmanager 监控配置
  - job_name: 'alertmanager'
    static_configs:
      - targets: ['192.168.101.65:9093']
        labels:
          instance: Alertmanager

5.2.定义告警规则

(1)在 Alertmanager 的告警规则文件(例如 /opt/module/alertmanager-0.23.0/rules/mysql_rules.yml)中配置指标 mysql_global_status_slow_queries 告警规则(MySQL 实例的慢查询速率持续 1 分钟超过 2 条/秒。):

groups:
- name: mysql-slow-query-alerts
  rules:
  - alert: MySQLTooManySlowQueries
    # 关键修改:使用 increase() 计算1分钟内的慢查询增量
    expr: increase(mysql_global_status_slow_queries[1m]) >= 2
    for: 1m  # 持续 1 分钟满足条件才触发
    labels:
      severity: warning
      service: mysql  # 附加服务标签便于分类
    annotations:
      summary: "MySQL 慢查询过多 (实例: {{ $labels.instance }})"
      description: "MySQL 实例 {{ $labels.instance }} 在最近 1 分钟内检测到 {{ $value | humanize }} 条慢查询,超过阈值(2 条/分钟)。"

注意:为了方便观察告警效果,上述规则可能与实际有出入!

(2)在 prometheus.yml 中加载规则文件:

rule_files:
  - "/opt/module/alertmanager-0.23.0/rules/mysql_rules.yml"

(3)重启 Prometheus 服务。

5.3.配置 Alertmanager 告警路由

(1)在 alertmanager.yml 中进行如下配置:

global:
  # 全局配置,会被所有接收器继承(除非被覆盖)
  resolve_timeout: 5m  # 当警报状态从 firing 变为 resolve 后,等待多久才声明已解决

  # SMTP 邮件服务器配置
  smtp_from: 'xxxxxx'  # 发件人邮箱
  smtp_smarthost: 'smtp.163.com:25'  # SMTP 服务器地址和端口
  smtp_auth_username: 'xxxxxx'  # SMTP 认证用户名
  smtp_auth_password: 'xxxxxx'  # SMTP 认证密码
  smtp_require_tls: true  # 是否启用 TLS 加密

templates:
  - '/opt/module/alertmanager-0.23.0/templates/*.tmpl'

# 路由树配置
route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 3h
  receiver: 'email-notifications'

receivers:
- name: 'email-notifications'
  email_configs:
  - to: '2642290139@qq.com'          # 收件人地址
    send_resolved: true              # 是否发送解决通知
    html: '{{ template "email.default.html" . }}'
	headers:
      Subject: '[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }} ({{ .CommonLabels.severity }})'

(2)在目录 /opt/module/alertmanager-0.23.0/templates 下配置邮件模板:

{{ define "email.default.html" }}
<!DOCTYPE html>
<html>
<head>
    <title>{{ .CommonLabels.alertname }}</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .header { background-color: #f8f8f8; padding: 20px; border-bottom: 1px solid #e7e7e7; }
        .content { padding: 20px; }
        .alert { margin-bottom: 20px; border-left: 4px solid; padding: 10px 15px; }
        .critical { border-color: #dc3545; background-color: #f8d7da; }
        .warning { border-color: #ffc107; background-color: #fff3cd; }
        .footer { margin-top: 20px; padding: 20px; font-size: 0.8em; color: #666; text-align: center; }
        table { width: 100%; border-collapse: collapse; margin: 15px 0; }
        th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
    </style>
</head>
<body>
    <div class="header">
        <h1>{{ .CommonLabels.alertname }}</h1>
        <p>状态: {{ .Status | toUpper }}</p>
    </div>

    <div class="content">
        {{ if eq .Status "firing" }}
        <div class="alert {{ if eq .CommonLabels.severity "critical" }}critical{{ else }}warning{{ end }}">
            <h2>告警详情</h2>
            <p>{{ .Annotations.summary }}</p>
            <p>{{ .Annotations.description }}</p>
    </div>
        {{ else }}
        <div class="alert" style="border-color: #28a745; background-color: #d4edda;">
            <h2>问题已解决</h2>
        </div>
        {{ end }}

        <h3>标签信息</h3>
        <table>
            <tr>
                <th>标签名</th>
                <th></th>
            </tr>
            {{ range .CommonLabels.SortedPairs }}
            <tr>
                <td>{{ .Name }}</td>
                <td>{{ .Value }}</td>
            </tr>
            {{ end }}
        </table>
        {{ if .CommonAnnotations }}
        <h3>附加信息</h3>
        <table>
            <tr>
                <th>注释名</th>
                <th></th>
            </tr>
            {{ range .CommonAnnotations.SortedPairs }}
            <tr>
                <td>{{ .Name }}</td>
                <td>{{ .Value }}</td>
            </tr>
            {{ end }}
        </table>
        {{ end }}
    </div>

    <div class="footer">
        <p>此邮件由 Alertmanager 自动发送</p>
    </div>
</body>
</html>
{{ end }}

(3)重启 Alertmanager。

5.4.验证告警

(1)通过 mysql -u root -p 进入 MySQL 命令行,然后执行 4 次下面的命令来模拟慢查询:

-- 模拟慢查询,耗时 12s
SELECT SLEEP(12);

-- 模拟慢查询,耗时 12s
SELECT SLEEP(12);

-- 模拟慢查询,耗时 12s
SELECT SLEEP(12);

-- 模拟慢查询,耗时 12s
SELECT SLEEP(12);

(2)在 Prometheus 页面中查看该告警:

在这里插入图片描述

(3)在 Alertmanager 页面中查看该告警:

在这里插入图片描述

(4)收到的告警邮件如下:

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到