Prometheus 架构

发布: (2025年12月19日 GMT+8 13:08)
13 分钟阅读
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的正文内容,我将为您翻译成简体中文。)

介绍

这是系列文章的第一篇,聚焦于现代监控栈主要组件的架构。

最初,我计划先比较 Prometheus 生态系统中的不同变体和工具(例如 MimirThanosCortex)。然而,先从 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 服务器

服务器是核心组件。它执行三个主要功能:

  1. 抓取(Scraping) – 定期通过 HTTP 连接到已配置的目标获取指标。
  2. 存储(Storage) – 将收集到的数据写入本地 TSDB。
  3. 评估与查询(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 / 服务
9100node_exporter – 操作系统指标
8080自定义应用指标
8081cAdvisor – 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.

ComponentResponsibility
Prometheus ServerDetects problems (evaluates PromQL rules) and fires alert states.
AlertmanagerReceives 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 的工具,例如 ThanosCortexMimir

接下来怎么办?

在后续的文章中,我将通过深入探讨以下内容来克服上述限制:

  1. Thanos – 添加长期存储(通过对象存储),并为 Prometheus 提供统一的全局视图。
  2. Cortex – 最初的多租户、水平可扩展的 Prometheus 解决方案。
  3. Mimir – Cortex 的演进版,侧重于大规模部署和运维简化。

Tags

#Prometheus #Monitoring #Observability #CNCF #DevOps #SRE

Back to Blog

相关文章

阅读更多 »