Prometheus 架构
Source: Dev.to
(请提供您希望翻译的正文内容,我将为您翻译成简体中文。)
介绍
这是系列文章的第一篇,聚焦于现代监控栈主要组件的架构。
最初,我计划先比较 Prometheus 生态系统中的不同变体和工具(例如 Mimir、Thanos 和 Cortex)。然而,先从 Prometheus 本身开始更为合理;毕竟,它是所有这些解决方案的基础和起源。
很可能,在你的 IT 旅程中的某个阶段,你已经听说、见过或使用过以 Prometheus 格式公开的度量指标来进行可观测性。Prometheus 是一个开源项目,已由云原生计算基金会(CNCF)毕业——这是继 Kubernetes 之后第二个获得此状态的项目。
它在 Kubernetes 环境中表现极佳,同时也能完美适配云平台和基于容器的环境。
Prometheus 采用 pull‑based(拉取)方式收集指标。不同于代理主动发送数据的系统,Prometheus 会主动前往数据源并 拉取 数据。
图 1 – Prometheus 数据收集流程(拉取 vs 推送)
[Insert diagram showing pull and push mechanisms]
入门
最简单的入门方式是以容器方式运行 Prometheus:
docker run -p 9090:9090 prom/prometheus:latest
要使用它,你需要一个 YAML 配置文件,在其中定义全局参数、抓取频率和目标。
基本启动配置
global:
scrape_interval: 15s # Scrape frequency
evaluation_interval: 15s # Rule evaluation frequency
external_labels:
cluster: 'demo-cluster'
environment: 'dev'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
labels:
instance: 'prometheus-server'
instance 标签(以及你添加的其他标签)使你在后续查询时能够过滤和聚合指标,为数据提供上下文。
典型的 Prometheus 部署
| 组件 | 描述 |
|---|---|
| Prometheus Server | 操作的大脑,负责收集和存储。 |
| Targets | 您的应用或服务器暴露指标的端点。 |
| Exporters | 将第三方系统的指标转换为 Prometheus 格式的代理。 |
| Time‑Series Database (TSDB) | 为时间序列数据优化的内部数据库。 |
| PromQL | 用于分析数据的强大查询语言。 |
| Pushgateway | 处理短暂作业的辅助组件。 |
| Alertmanager | 管理、分组并路由警报通知。 |
| Client Libraries | 用于在应用程序中直接对自定义代码进行仪表化的库。 |
图 2 – 完整的 Prometheus 架构,包含所有核心组件
[Insert diagram showing all core components and their interactions]
组件详情
1. Prometheus 服务器
服务器是核心组件。它执行三个主要功能:
- 抓取(Scraping) – 定期通过 HTTP 连接到已配置的目标获取指标。
- 存储(Storage) – 将收集到的数据写入本地 TSDB。
- 评估与查询(Evaluation & Querying) – 评估告警规则并通过 PromQL API 响应查询(例如来自 Grafana 的查询)。
实际上,它是整个系统的心脏,确保数据从来源持续流向存储。
2. 目标
目标 是指标的来源。它们可以是几乎任何东西:Linux 服务器、Java 应用、API 端点或 Kubernetes Pod。默认情况下,Prometheus 从目标的 /metrics HTTP 端点抓取指标,虽然该路径是可配置的。
scrape_configs:
- job_name: 'node-metrics'
static_configs:
- targets: ['instance-dev:9100']
labels:
instance: 'instance-dev'
常见目标端口
| 端口 | 常见 Exporter / 服务 |
|---|---|
| 9100 | node_exporter – 操作系统指标 |
| 8080 | 自定义应用指标 |
| 8081 | cAdvisor – Docker 容器指标 |
3. Exporter
并非所有软件都原生以 Prometheus 格式暴露指标(例如 MySQL、Redis)。Exporter 是小型二进制文件,充当翻译器:它们从原系统(使用其原生 API)收集指标并转换为 Prometheus 能理解的纯文本格式,然后在 HTTP 端点上暴露。
社区维护且官方支持的常用 Exporter
node_exporter– 硬件与操作系统指标(CPU、内存、磁盘)。blackbox_exporter– 通过 HTTP、DNS、TCP、ICMP 对外部端点进行探测。mysqld_exporter/postgres_exporter/redis_exporter– 数据库专属指标。
完整列表请参见官方文档。
示例指标输出
来自 node_exporter(系统)
node_cpu_seconds_total{instance="instance-dev",cpu="0",mode="idle"} 145893.45
node_memory_MemAvailable_bytes{instance="instance-dev"} 4294967296
来自 cAdvisor(容器)
container_cpu_usage_seconds_total{instance="instance-dev",name="my-app",image="nginx:latest"} 234.56
自定义应用指标
http_requests_total{instance="instance-dev",method="GET",status="200"} 1547
http_request_duration_seconds{instance="instance-dev",endpoint="/api/users"} 0.234
4. 时间序列数据库(TSDB)
Prometheus 收集的数据本质上是 时间序列:随时间变化的数值,始终带有时间戳。为高效存储,Prometheus 使用自研的 TSDB,针对高写入吞吐和快速读取进行了优化。
Prometheus 将指标以 块(block) 的形式存储在磁盘上。
图 3 – Prometheus TSDB 生命周期与存储流程
[Insert diagram showing in‑memory buffering, block creation, compression, and retention]
关键特性
- 追加写入(Append‑only) 设计 → 高写入性能。
- 最近的数据保存在内存中以实现快速访问;定期刷新到磁盘。
- 每个块包含压缩后的样本、用于快速查找的索引以及元数据。
保留策略 – 默认情况下,Prometheus 在本地保留 15 天 的数据。超过保留期的块会被删除以释放空间。虽然 Prometheus 最初并非为长期存储设计,但可以调整保留期限,或使用远程存储集成(如 Thanos、Cortex)实现更长时间的保存。
敬请期待下一篇文章,我们将探讨远程存储方案以及基于 Prometheus 的监控栈的扩展策略。
PromQL(Prometheus 查询语言)
PromQL 是用于检索和分析数据的集成功能查询语言。正是通过 PromQL,你在 Grafana 中创建仪表盘或定义告警。
该语言允许你 选择、过滤、聚合,以及对时间序列数据执行 复杂的数学运算。
简单指标选择(当前值)
http_requests_total
按标签过滤
http_requests_total{instance="instance-dev", status="200"}
每秒请求速率(最近 5 分钟的平均)
rate(http_requests_total[5m])
按实例聚合的请求速率全局求和
sum(rate(http_requests_total[5m])) by (instance)
可用内存百分比计算
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
CPU 使用率(除 idle 之外的所有)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
PromQL 还包括以下函数:
- 百分位数:
histogram_quantile - 线性预测:
predict_linear - 时间比较:
offset
Source: …
Push Gateway(用于短期作业)
Prometheus 使用 pull 模型,但短期作业(例如批量备份脚本)可能在 Prometheus 抓取之前就已经结束。
Push Gateway 充当中间缓存:作业 push 指标到网关,Prometheus 再按常规间隔抓取该网关。
示例:发送一个表示作业耗时的指标
echo "job_duration_seconds 45.2" | curl --data-binary @- \
http://pushgateway:9091/metrics/job/batch-job/instance/worker-1
注意: Push Gateway 仅适用于非常特定的使用场景。它 不应 被用于将 Prometheus 变成推送式系统。pull 模型仍然更可取,因为它:
- 允许 Prometheus 控制负载。
- 能轻松检测不活跃的目标(
up/down)。- 简化服务发现。
Alerting Architecture
It’s common to confuse the responsibilities of the components involved in alerting.
| Component | Responsibility |
|---|---|
| Prometheus Server | Detects problems (evaluates PromQL rules) and fires alert states. |
| Alertmanager | Receives firing alerts and decides what to do with them (group, inhibit, silence, route). |
Alertmanager Features
- Grouping – Combine many similar alerts into a single notification.
- Inhibition – Suppress less important alerts when a critical one is active.
- Silencing – Mute alerts during planned maintenance windows.
- Routing – Send alerts to different channels (e.g., PagerDuty, Slack).
Example: Prometheus detection rule
groups:
- name: example
rules:
- alert: HighCPUUsage
expr: rate(node_cpu_seconds_total{mode!="idle"}[5m]) > 0.8
for: 5m # Condition must hold for 5 minutes
labels:
severity: warning
Example: Alertmanager routing configuration
route:
# Default route
receiver: 'team-slack'
routes:
# Specific route for critical alerts
- match:
severity: critical
receiver: 'pagerduty-oncall'
receivers:
- name: 'team-slack'
slack_configs:
- channel: '#alerts-general'
- name: 'pagerduty-oncall'
pagerduty_configs:
- service_key: '...'
为您自己的应用程序进行仪表化
除了使用现成系统的 exporter 之外,最佳实践是 为您自己的应用程序进行仪表化,让它们原生暴露业务和性能指标。
Prometheus 为 Go、Java/Scala、Python 和 Ruby 提供官方客户端库,并有社区维护的 .NET、Node.js、Rust 等库。只需几行代码,您的应用程序即可提供一个 /metrics 端点。
Python 示例
from prometheus_client import Counter, Histogram, start_http_server
import time
# 1. 定义指标
requests_total = Counter(
'http_requests_total',
'Total HTTP requests received',
['method', 'endpoint', 'status'] # Labels for dimensionality
)
request_duration = Histogram(
'http_request_duration_seconds',
'Histogram of request duration',
['endpoint']
)
# 2. 在应用代码中使用(例如,使用装饰器)
@request_duration.labels(endpoint='/api/users').time()
def handle_user_request():
# Application logic...
time.sleep(0.1)
# Increment the counter at the end
requests_total.labels(method='GET', endpoint='/api/users', status='200').inc()
if __name__ == '__main__':
# 3. 启动 HTTP 服务器以暴露指标
start_http_server(8000)
print("Metrics server running on port 8000...")
# Main application loop...
客户端库会为您处理线程安全、正确的数据格式化以及其他复杂性。
为什么 Prometheus 成为市场标准
| 优势 | 描述 |
|---|---|
| 拉取模型 | 便于对目标进行流量控制、调试和故障检测。 |
| 多维数据 | 标签实现了极其灵活的分析。 |
| PromQL | 专为监控数据设计的查询语言。 |
| 运维简易性 | 单一静态二进制文件,部署简便,无复杂的外部依赖。 |
| 服务发现 | 原生、动态集成 Kubernetes、AWS、Azure 等。 |
| 开放生态系统 | 数百个导出器,几乎覆盖所有技术。 |
Source: …
Prometheus 的局限性
- 单节点架构 – 并未为原生水平扩展设计;当负载过高时,需要手动在多台服务器之间进行分片。
- 本地与临时存储 – 数据存放在服务器的本地磁盘上;如果服务器宕机且磁盘丢失,数据也随之消失。没有原生的数据复制机制。
- 长期保留 – 在没有外部方案(如远程写入到 Thanos、Cortex 或 Mimir)的情况下,长时间存储数据会变得成本高昂或不可行。
了解这些权衡有助于判断何时 Prometheus 是合适的工具,何时需要补充系统来实现高可用性或长期存储。
概览
- 期限保留:在 Prometheus 中存储多年历史数据并不高效。
- 碎片化的全局视图:当拥有多个 Kubernetes 集群且每个集群都有自己的 Prometheus 实例时,缺乏原生的统一指标视图,无法跨所有集群统一查看。
这些架构限制促使人们创建了 “拥抱并扩展” Prometheus 的工具,例如 Thanos、Cortex 和 Mimir。
接下来怎么办?
在后续的文章中,我将通过深入探讨以下内容来克服上述限制:
- Thanos – 添加长期存储(通过对象存储),并为 Prometheus 提供统一的全局视图。
- Cortex – 最初的多租户、水平可扩展的 Prometheus 解决方案。
- Mimir – Cortex 的演进版,侧重于大规模部署和运维简化。
Tags
#Prometheus #Monitoring #Observability #CNCF #DevOps #SRE