Prometheus核心概念与查询语言入门指南
在现代云原生监控体系中,Prometheus 作为 CNCF(云原生计算基金会)毕业项目,已成为 Kubernetes 和微服务架构下的首选监控解决方案。它不仅提供了强大的数据采集和存储能力,还拥有灵活的查询语言 PromQL。本文将深入探讨 Prometheus 的核心概念、数据模型以及 PromQL 的基本用法,帮助初学者快速掌握 Prometheus 的理论基础。
一、Prometheus 简介
Prometheus 是一个开源的系统监控和告警工具包,最初由 SoundCloud 开发。它采用 Pull 模式采集时间序列数据,通过 HTTP 协议定期从各种目标获取指标信息。其核心特性包括:
- 多维数据模型(时间序列由指标名称和键值对标签组成)
- PromQL 查询语言,提供强大的数据查询和分析能力
- 不依赖分布式存储,单个服务器节点是自治的
- 通过服务发现或静态配置来发现目标
- 支持图表和仪表板等多种可视化方式
二、Prometheus 架构详解
Prometheus 的整体架构由多个核心组件构成,这些组件协同工作以提供完整的监控解决方案:
1. 核心组件
| 组件 | 作用 |
|---|---|
| Prometheus Server | 主服务,负责指标抓取、存储和查询 |
| Exporters | 暴露各种系统和服务的指标 |
| Alertmanager | 处理告警通知 |
| Pushgateway | 允许临时和批量作业推送指标 |
| Service Discovery | 服务发现机制,自动发现监控目标 |
2. 架构图
+--------------+
| Prometheus |
| Server |
+--------------+
|
+-----------------+-----------------+
| | |
+--------v-------+ +-------v--------+ +-----v---------+
| Exporters | | Pushgateway | | Service |
| (Node, MySQL, | | | | Discovery |
| etc.) | | | | (K8s, Consul, |
+----------------+ +----------------+ | etc.) |
+---------------+
+---------------+
| Alertmanager |
+---------------+
+---------------+
| Grafana/Other |
| Visualisation |
+---------------+
3. 工作流程
- Prometheus Server 通过配置的抓取任务定期从目标获取指标
- 通过服务发现机制动态发现监控目标
- 将抓取的指标存储在本地时序数据库中
- 用户通过 PromQL 查询语言查询和分析数据
- 当触发告警规则时,将告警发送到 Alertmanager
- Alertmanager 处理告警并发送通知(邮件、Slack 等)
- 通过 Grafana 等工具进行数据可视化
三、核心概念详解
1. 时间序列数据模型
Prometheus 存储的是时间序列数据,每个时间序列由以下部分组成:
- 指标名称(Metric Name):描述被监控样本的含义,例如
http_requests_total表示 HTTP 请求总数 - 标签(Labels):一组键值对,用于标识时间序列的特征,例如
method="POST"、status="200" - 时间戳(Timestamp):样本数据的时间点
- 样本值(Sample Value):当前时间点的具体数值
例如:http_requests_total{method="POST", handler="/api/v1/users", status="200"} 42
2. 指标类型
Prometheus 定义了四种核心指标类型:
| 指标类型 | 说明 | 示例 |
|---|---|---|
| Counter(计数器) | 只增不减的累计型指标,常用于请求总数、任务完成数等 | http_requests_total |
| Gauge(仪表盘) | 可增可减的指标,用于表示瞬时状态,如 CPU 使用率、内存用量 | node_memory_available_bytes |
| Histogram(直方图) | 对观测值(通常是请求持续时间或响应大小)进行分组计数 | http_request_duration_seconds_bucket |
| Summary(摘要) | 类似直方图,但直接提供分位数计算结果 | http_request_duration_seconds{quantile="0.99"} |
3. 作业(Job)与实例(Instance)
在 Prometheus 的术语中:
- Instance(实例):一个单独的监控目标,通常对应一个进程或服务
- Job(作业):具有相同目的的实例集合,例如一个 API 服务的所有副本
四、PromQL 查询语言详解
PromQL(Prometheus Query Language)是 Prometheus 提供的功能强大的表达式语言,允许用户实时选择和汇聚时间序列数据。
1. 基本表达式
最基本的 PromQL 表达式是指标名称,例如:
http_requests_total
可以通过标签匹配器来过滤时间序列:
http_requests_total{job="apiserver", status=~"5.."}
其中:
=:完全相等!=:不相等=~:正则表达式匹配!~:正则表达式不匹配
2. 常用函数
count 函数
count 函数用于计算时间序列的数量:
count(http_requests_total)
这将返回匹配指标的时间序列数量。例如,如果有多个实例都在暴露 http_requests_total 指标,该函数会返回这些实例的数量。
rate 函数
rate 函数计算时间序列在时间窗口内的每秒增长率,通常用于 Counter 类型指标:
rate(http_requests_total[5m])
这将返回 HTTP 请求在最近 5 分钟内的每秒增长率。由于 Counter 是累计值,直接查看其数值意义不大,通常需要计算其增长率。
sum 函数
sum 函数对时间序列进行求和:
sum(http_requests_total) by (status)
按状态码对 HTTP 请求总数进行分组求和。这会将所有实例中相同状态码的请求总数加在一起。
其他常用函数
| 函数 | 说明 | 示例 |
|---|---|---|
increase() | 计算时间窗口内计数器的增长量 | increase(http_requests_total[5m]) |
avg_over_time() | 计算时间窗口内值的平均值 | avg_over_time(node_cpu_seconds_total[1m]) |
max_over_time() | 计算时间窗口内值的最大值 | max_over_time(node_memory_bytes_available[1h]) |
min_over_time() | 计算时间窗口内值的最小值 | min_over_time(node_memory_bytes_available[1h]) |
predict_linear() | 基于线性回归预测未来值 | predict_linear(node_filesystem_free_bytes[1h], 4 * 3600) |
3. 操作符
Prometheus 支持多种操作符:
- 算术运算符:
+、-、*、/、%、^ - 比较运算符:
==、!=、>、<、>=、<= - 逻辑运算符:
and、or、unless
例如,使用 offset 计算指标的变化:
http_requests_total - http_requests_total offset 1h
这个表达式计算的是当前时刻的 HTTP 请求数与 1 小时前的请求数之间的差值。
4. 高级查询示例
计算错误率
计算 HTTP 错误请求的占比:
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m])
计算 CPU 使用率
计算 CPU 使用率:
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
计算内存使用率
计算内存使用率:
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
五、存储机制与数据分块
1. 时序数据库(TSDB)原理
Prometheus 使用自研的时序数据库 TSDB,专门优化用于存储时间序列数据。其主要特点包括:
- 按时间分块存储(chunk)
- 高效的压缩算法
- 支持长期存储和快速查询
2. 数据分块(Chunk)
在 Prometheus 中,数据以 2 小时为单位划分为块(chunk)。每个 chunk 包含一个时间序列在该时间窗口内的所有样本数据。这种设计有以下优势:
- 提高查询效率:查询特定时间范围的数据只需访问相关块
- 优化存储:可以对整个块进行压缩
- 便于管理:可以按块进行删除或归档操作
每个 chunk 最多包含 120 个样本点,当达到最大样本数或时间窗口结束时,chunk 会被关闭并压缩。
3. 块存储结构
Prometheus 的存储结构如下:
数据目录/
├── chunks/
│ ├── 000001
│ └── 000002
├── wal/
│ ├── 000001
│ └── 000002
├── index/
└── meta.json
各目录作用:
chunks/:存储实际的样本数据块wal/:预写日志(Write-Ahead Log),用于保证数据持久性index/:倒排索引,用于快速查找时间序列meta.json:元数据文件,包含块的时间范围等信息
4. 压缩与保留策略
Prometheus 采用多种压缩策略来减少存储空间:
- Delta 编码:存储时间戳和值的差值而非绝对值
- 变长编码:使用更少的位数表示较小的数字
- 重复数据删除:移除重复的标签集
默认情况下,Prometheus 会保留 15 天的数据,但可以通过配置 --storage.tsdb.retention.time 参数来调整保留时间。
| 参数 | 说明 | 示例 |
|---|---|---|
--storage.tsdb.retention.time | 数据保留时间 | --storage.tsdb.retention.time=30d |
--storage.tsdb.retention.size | 数据保留大小 | --storage.tsdb.retention.size=10GB |
--storage.tsdb.wal-compression | 是否压缩 WAL | --storage.tsdb.wal-compression=true |
六、Prometheus 生态系统
Prometheus 拥有丰富的生态系统,包括各种 Exporter、Alertmanager、Pushgateway 等组件:
1. Exporters
Exporter 是 Prometheus 生态中的重要组件,用于将各种系统和服务的指标转换为 Prometheus 可以理解的格式。
| Exporter | 监控对象 |
|---|---|
| Node Exporter | 主机系统指标(CPU、内存、磁盘等) |
| MySQL Exporter | MySQL 数据库指标 |
| Redis Exporter | Redis 数据库指标 |
| Blackbox Exporter | 网络探测(HTTP、TCP、ICMP 等) |
| JMX Exporter | Java 应用指标 |
| cAdvisor | 容器指标 |
2. 其他核心组件
| 组件 | 作用 |
|---|---|
| Alertmanager | 处理告警通知 |
| Pushgateway | 允许临时和批量作业推送指标 |
| Prometheus Operator | 在 Kubernetes 上管理 Prometheus 实例 |
| Thanos | 提供全局查询视图、长期存储和高可用性 |
3. 可视化工具
| 工具 | 说明 |
|---|---|
| Grafana | 流行的可视化平台,支持 Prometheus 数据源 |
| Prometheus UI | Prometheus 内置的简单查询界面 |
七、实际应用场景
1. 微服务监控
在微服务架构中,Prometheus 可以通过服务发现机制自动发现并监控各个服务实例,通过标签区分不同的服务、版本和环境。
常用指标示例:
http_requests_total:HTTP 请求总数http_request_duration_seconds:HTTP 请求持续时间go_goroutines:Goroutine 数量process_resident_memory_bytes:进程内存使用量
2. Kubernetes 集群监控
Prometheus 与 Kubernetes 深度集成,可以通过 kube-state-metrics 获取集群状态,通过 node-exporter 获取节点指标,实现全面的集群监控。
关键监控指标:
- 节点资源使用情况:CPU、内存、磁盘
- Pod 状态:运行、失败、重启次数
- 容器资源使用:CPU、内存、网络
- 集群组件健康状态:API Server、etcd、kubelet
3. 业务指标监控
通过自定义指标暴露,可以监控业务关键指标,如订单量、用户活跃度等,为业务决策提供数据支持。
示例:
- 订单处理量:
orders_processed_total - 用户登录次数:
user_login_total - 支付成功率:
payment_success_rate
4. 告警规则配置
Prometheus 可以通过配置告警规则来实现自动化监控告警:
groups:
- name: example
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
for: 10m
labels:
severity: warning
annotations:
summary: "High error rate detected"
description: "Error rate is above 5% for more than 10 minutes"
八、最佳实践建议
- 合理设计指标名称和标签:遵循命名规范,避免标签过多导致的基数问题
- 选择合适的指标类型:正确使用 Counter、Gauge、Histogram 和 Summary
- 控制时间序列基数:避免高基数标签,如 user_id、request_id 等
- 设置合理的保留时间:根据存储容量和查询需求平衡数据保留时间
- 使用记录规则优化查询:对于复杂的查询表达式,可以预先计算并存储结果
- 合理使用 Histogram 和 Summary:Histogram 更适合聚合,Summary 更适合分位数计算
- 避免查询高基数时间序列:高基数查询可能导致性能问题
- 使用服务发现自动发现监控目标:减少手动配置工作量
总结
Prometheus 作为现代监控体系的核心组件,其强大的数据模型和灵活的查询语言为系统监控提供了坚实的基础。通过理解其核心概念、掌握 PromQL 的基本用法,并了解其存储机制,我们可以更好地利用 Prometheus 构建高效的监控系统。
评论区