PROMETHEUS

云原生时代的监控与警报标准

多维数据模型 | 强大的查询语言 | 高效的时间序列数据库

开始探索

1. 引言:什么是 Prometheus?

概述

Prometheus 是一套开源的系统监控和警报工具包,由前 Google 工程师在 SoundCloud 于 2012 年创建。它的设计灵感来源于 Google 内部的 Borgmon 监控系统,专为微服务和容器化环境设计。

2016 年,Prometheus 加入 Cloud Native Computing Foundation (CNCF),成为继 Kubernetes 之后的第二个托管项目,2018 年正式毕业,标志着其成为云原生监控的事实标准。

70K+
GitHub Stars
1000+
Contributors
200+
Official Exporters

核心设计目标

  • 多维数据模型:通过指标名称和键值对标签区分时间序列数据,支持灵活的多维查询。
  • 灵活的查询语言:PromQL 允许对收集的数据进行切片和切块,以生成图表、表格和警报。
  • 不依赖分布式存储:单个服务器节点是自治的,降低了部署和运维复杂度。
  • 基于 Pull 的采集:通过 HTTP 协议主动拉取指标数据,便于调试和服务发现。
  • 服务发现:原生支持 Kubernetes、Consul、DNS 等多种服务发现机制。
  • 高效存储:内置时间序列数据库,采用压缩算法实现高效存储。

2. 核心架构与组件

Prometheus 的生态系统由多个组件组成,其中许多是可选的。核心组件是 Prometheus Server,负责抓取和存储时间序列数据。

Prometheus Server Retrieval (Pull) TSDB (Storage) HTTP Server Jobs / Exporters Pushgateway Short-lived Jobs Alertmanager Grafana / UI Pull Metrics Scrape Alerts PromQL Query

关键组件解析

  • Prometheus Server:核心组件,负责定期从配置的目标(Targets)拉取数据,处理并存储到本地的时间序列数据库(TSDB)。
  • Exporters:运行在被监控节点上,将非 Prometheus 格式的指标转换为 Prometheus 可识别的格式。
  • Pushgateway:用于接收短生命周期作业(Short-lived jobs)推送的指标,Prometheus Server 再从中拉取。
  • Alertmanager:处理由 Server 推送的警报,进行去重、分组,并路由到正确的接收端(如 Email, Slack, PagerDuty)。
  • Client Libraries:官方提供 Go、Java、Python、Ruby 等语言的客户端库,方便应用程序暴露指标。
  • Service Discovery:支持 Kubernetes、Consul、DNS、EC2 等多种服务发现机制。

常用 Exporters

Node Exporter

主机级别指标(CPU、内存、磁盘)

Blackbox Exporter

黑盒探测(HTTP、DNS、TCP)

MySQL Exporter

MySQL 数据库指标

Redis Exporter

Redis 缓存指标

3. 数据模型与指标

Prometheus 将所有数据存储为时间序列:即属于同一指标名称和同一组标签维度的时间戳值流。每个时间序列由指标名称和一组键值对标签唯一标识。

http_requests_total 指标名称 (Metric Name) {method="POST", handler="/api"} 标签 (Labels): 维度键值对 Time 1024 t0 1050 t1 1100 t2 唯一标识:<metric name>{<label name>=<label value>, ...}

四种核心指标类型

Counter (计数器)

只增不减的计数器,用于记录请求数、任务完成数、错误数等。

http_requests_total

Gauge (仪表盘)

可增可减的数值,用于记录内存使用率、温度、并发请求数等。

node_memory_usage_bytes

Histogram (直方图)

对观察结果进行采样,在可配置的桶(bucket)中进行统计。

http_request_duration_seconds_bucket

Summary (摘要)

类似于直方图,但直接在客户端计算分位数(Quantiles)。

go_gc_duration_seconds{quantile="0.99"}

Histogram vs Summary

特性 Histogram Summary
分位数计算 服务端计算 客户端计算
可聚合性 ✅ 可聚合 ❌ 不可聚合
配置 需要预定义 bucket 需要预定义 quantile
推荐场景 大多数场景 精确分位数需求

4. 查询语言 PromQL

PromQL (Prometheus Query Language) 是 Prometheus 强大的函数式查询语言,允许用户实时选择和聚合时间序列数据。它支持多种数据类型,包括标量、向量和矩阵,并提供了丰富的函数库。

rate(http_requests[5m]) Query Input Query Engine Select Series + Calculate Rate Vector(value1, value2...) Result

数据类型

  • 标量 (Scalar):单一的数值,如 42
  • 即时向量 (Instant Vector):一组时间序列,每个序列包含一个样本,如 http_requests_total{job="api"}
  • 范围向量 (Range Vector):一组时间序列,每个序列包含一段时间内的样本,如 http_requests_total{job="api"}[5m]
  • 字符串 (String):用于表示文本数据,但在实际中很少使用。

操作符

算术操作符

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 取模
  • ^ 幂运算

比较操作符

  • == 等于
  • != 不等于
  • > 大于
  • < 小于
  • >= 大于等于
  • <= 小于等于

逻辑操作符

  • and 与(交集)
  • or 或(并集)
  • unless 排除(差集)

聚合操作符

  • sum 求和
  • avg 平均值
  • min/max 最小/最大值
  • count 计数
  • stddev 标准差
  • topk/bottomk 前/后 K 个

常用函数

函数 说明 示例
rate() 计算范围向量的每秒平均增长率 rate(http_requests_total[5m])
irate() 计算瞬时增长率(最后两个样本) irate(http_requests_total[5m])
increase() 计算范围内的增量 increase(http_requests_total[1h])
histogram_quantile() 计算直方图的分位数 histogram_quantile(0.95, rate(http_request_duration_bucket[5m]))
predict_linear() 线性回归预测未来值 predict_linear(node_filesystem_free_bytes[1h], 4*3600)
absent() 检测指标是否存在 absent(up{job="api"})
label_replace() 替换或添加标签 label_replace(up, "host", "$1", "instance", "(.*):.*)")

查询示例

基础查询

http_requests_total
选择所有名为 http_requests_total 的时间序列。

http_requests_total{job="api-server", handler="/api/comments"}
通过标签进行过滤。

速率计算

rate(http_requests_total[5m])
计算过去 5 分钟内每秒的平均增长率。

irate(http_requests_total[5m])
使用最近两个样本计算瞬时增长率。

聚合操作

sum(http_requests_total) by (job)
按 job 标签求和。

avg(rate(http_requests_total[5m]))
计算平均请求率。

高级函数

histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
计算 95% 分位的请求延迟。

topk(5, sum(http_requests_total) by (instance))
获取请求数最多的前 5 个实例。

5. 警报处理流程

Prometheus 的警报分为两部分:Prometheus Server 中的警报规则(Alerting Rules)和 Alertmanager。警报规则定义触发条件,Alertmanager 负责处理、路由和发送通知。

Prometheus Rule Evaluation HighErrorRate? FIRING Alertmanager Grouping Inhibition Silencing Routing Email Slack PagerDuty

警报规则示例

groups:
- name: example
  rules:
  - alert: HighErrorRate
    expr: rate(http_requests_total{status="5xx"}[5m]) > 0.5
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: "High error rate on {{ $labels.instance }}"
      description: "{{ $labels.instance }} has a 5xx error rate of {{ $value | humanizePercentage }} for more than 10 minutes."

Alertmanager 配置示例

global:
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alertmanager@example.com'

route:
  group_by: ['alertname', 'cluster']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'team-email'
  routes:
  - match:
      severity: critical
    receiver: 'pagerduty'

receivers:
- name: 'team-email'
  email_configs:
  - to: 'team@example.com'
- name: 'pagerduty'
  pagerduty_configs:
  - service_key: '<service-key>'

6. 服务发现机制

Prometheus 支持多种服务发现机制,可以自动发现和监控目标实例,而无需手动配置每个目标。

服务发现方式

kubernetes_sd_config

自动发现 Kubernetes 集群中的 Pod、Service、Node 等资源

consul_sd_config

从 Consul 服务注册中心发现服务

ec2_sd_config

发现 AWS EC2 实例

dns_sd_config

通过 DNS 查询发现目标

file_sd_config

从文件读取目标列表(JSON/YAML)

static_configs

静态配置目标列表

Kubernetes 集成

Prometheus 与 Kubernetes 完美集成,支持多种资源类型的自动发现:

scrape_configs:
- job_name: 'kubernetes-pods'
  kubernetes_sd_configs:
  - role: pod
  relabel_configs:
  # 只监控带有 prometheus.io/scrape 注解的 Pod
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  # 从注解获取抓取路径
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
    action: replace
    target_label: __metrics_path__
    regex: (.+)
  # 从注解获取抓取端口
  - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
    action: replace
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
    target_label: __address__

Kubernetes 服务发现角色

Role 说明
node 发现集群中的所有 Node
pod 发现所有 Pod 及其容器端口
service 发现所有 Service 及其端口
endpoints 发现 Service 对应的 Endpoints
ingress 发现所有 Ingress 资源

Relabeling 配置

Relabeling 是 Prometheus 强大的标签重写机制,允许在抓取前后修改标签:

replace

替换标签值

keep

保留匹配的目标

drop

丢弃匹配的目标

labelmap

映射标签名称

labeldrop

删除匹配的标签

labelkeep

保留匹配的标签

7. 存储与远程读写

Prometheus 内置了高性能的时间序列数据库 (TSDB),同时支持远程存储集成以实现长期数据保存。

本地存储 (TSDB)

数据压缩

采用高效压缩算法,每个样本平均只占用 1-2 字节

分块存储

数据按时间分块存储,默认 2 小时一个 block

WAL 机制

Write-Ahead Log 确保数据持久性和崩溃恢复

保留策略

通过 --storage.tsdb.retention.time 配置

# 存储相关启动参数
./prometheus \
  --storage.tsdb.path=/data/prometheus \
  --storage.tsdb.retention.time=30d \
  --storage.tsdb.retention.size=50GB \
  --storage.tsdb.wal-compression

远程存储

Prometheus 支持通过远程写入/读取接口集成外部存储系统:

Thanos

高可用 + 全局查询

Cortex

多租户 + 水平扩展

VictoriaMetrics

高性能 + 低资源消耗

M3DB

分布式时序数据库

# 远程写入配置示例
remote_write:
  - url: "http://remote-storage:9201/write"
    queue_config:
      max_samples_per_send: 1000
      batch_send_deadline: 5s

# 远程读取配置示例
remote_read:
  - url: "http://remote-storage:9201/read"
    read_recent: true

联邦集群 (Federation)

联邦允许一个 Prometheus 服务器从另一个 Prometheus 服务器抓取选定的时间序列,用于实现:

  • 分层联邦:上层 Prometheus 抓取下层的聚合数据
  • 跨数据中心查询:全局视图查看多个集群的数据
Global Prometheus DC1 Prometheus DC2 Prometheus DC3 Prometheus /federate
# 联邦配置示例
scrape_configs:
  - job_name: 'federate'
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{job="prometheus"}'
        - '{__name__=~"job:.*"}'
    static_configs:
      - targets:
        - 'prometheus-dc1:9090'
        - 'prometheus-dc2:9090'

8. 安装与配置

Prometheus 提供多种安装方式,包括二进制文件、Docker 容器和包管理器。以下是常用的安装方法:

二进制文件安装

# 下载最新版本
wget https://github.com/prometheus/prometheus/releases/download/v2.50.0/prometheus-2.50.0.linux-amd64.tar.gz

# 解压
 tar -xzf prometheus-2.50.0.linux-amd64.tar.gz
cd prometheus-2.50.0.linux-amd64

# 运行 Prometheus
./prometheus --config.file=prometheus.yml

Docker 安装

docker run -d \
                  -p 9090:9090 \
                  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
                  prom/prometheus

基础配置文件示例

global:
  scrape_interval:     15s # 全局抓取间隔
  evaluation_interval: 15s # 全局规则评估间隔

# Alertmanager 配置
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

# 规则文件
rule_files:
  - "alert.rules.yml"

# 抓取配置
scrape_configs:
  # 监控 Prometheus 自身
  - job_name: 'prometheus'
    static_configs:
    - targets: ['localhost:9090']
  
  # 监控 Node Exporter
  - job_name: 'node'
    static_configs:
    - targets: ['localhost:9100']

9. 最佳实践

指标设计

  • 使用有意义的指标名称,遵循 <what>_<unit> 命名规范
  • 不要在指标名称中包含可变部分,使用标签代替
  • 为每个指标添加足够的标签,以便进行多维度分析
  • 避免过度使用高基数标签(如 UUID、IP 地址)

性能优化

  • 合理设置抓取间隔,根据指标重要性调整
  • 使用 rate() 代替 irate() 进行长期趋势分析
  • 定期清理旧数据,设置适当的存储保留期限
  • 对于高 cardinality 指标,考虑使用聚合或采样

部署架构

  • 在生产环境中使用多个 Prometheus 实例实现高可用
  • 使用联邦集群(Federation)处理大规模部署
  • 考虑使用 Thanos 或 Cortex 实现长期存储和全局查询
  • 为 Alertmanager 配置集群模式,确保警报可靠传递

监控策略

  • 遵循 RED 指标(请求率、错误率、延迟)监控微服务
  • 结合 USE 方法(利用率、饱和度、错误)监控基础设施
  • 设置合理的警报阈值,避免告警风暴
  • 定期审查和优化警报规则

10. 总结与适用场景

主要优势

  • 去中心化架构:高可靠性,无单点故障。
  • 强大的查询能力:PromQL 支持复杂的聚合与分析。
  • 云原生友好:与 Kubernetes 完美集成,自动发现服务。
  • 活跃社区:丰富的 Exporter 生态。
  • 多维数据模型:灵活的标签系统支持多维度分析。

适用场景

  • 🚀 容器与微服务监控:动态环境下的服务发现与监控。
  • 💻 主机基础监控:CPU、内存、磁盘等硬件指标。
  • 📊 业务指标监控:请求量、订单量等业务层面的数据。
  • DevOps 工作流:CI/CD 管道监控与警报。
  • 🌐 全球化部署:多数据中心联邦查询。

不适用场景

  • 日志收集:Prometheus 专注于指标,不适合日志存储(推荐 Loki/ELK)。
  • 100% 准确性计费:采样机制可能丢失部分数据点。
  • 年级长期存储:本地存储有限,需要集成 Thanos/Cortex。
  • 事件驱动监控:Pull 模型不适合事件驱动架构。