Prometheus 不仅是一个时序数据库,它是云原生监控的事实标准。 从 Kubernetes 集群到 Spring Boot 应用,从网络设备到自定义业务指标,Prometheus 生态已经覆盖了现代可观测性的每一个角落。
一、Prometheus 架构
1.1 核心组件
Prometheus 架构:
┌─────────────┐
│ Target │ ──→ 被监控的应用/服务
│ (exporter) │ /metrics HTTP 端点
└──────┬──────┘
│ pull
┌──────▼──────┐
│ Prometheus │ ──→ 抓取、存储、查询
│ Server │
└──┬──────┬───┘
│ │
┌──────────────┘ └──────────────┐
↓ ↓
┌─────────────┐ ┌─────────────┐
│ Alertmanager│ ──→ 告警管理 │ Grafana │ ──→ 可视化
│ (分组/路由) │ │ (Dashboard) │
└─────────────┘ └─────────────┘
↓
┌─────────────┐
│ PagerDuty /│ ──→ 通知渠道
│ Slack / │
│ Webhook │
└─────────────┘
1.2 为什么 Pull 模式
| Pull | Push |
|---|---|
| 控制节奏,防止目标被压垮 | 目标自主推送 |
| 集中配置,无需目标感知 | 每个目标需配置服务器地址 |
| 便于故障检测(目标不响应 = 宕机) | 无法区分"没数据"和"没推送" |
| 支持临时目标、批处理任务 | 批处理需要 Pushgateway |
二、指标类型详解
2.1 Counter(计数器)
# Python prometheus_client 示例
from prometheus_client import Counter, start_http_server
# 定义 Counter
http_requests_total = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'status', 'route']
)
# 使用
@app.route('/api/users')
def get_users():
http_requests_total.labels(method='GET', status='200', route='/api/users').inc()
return jsonify(users)
@app.errorhandler(500)
def handle_error(e):
http_requests_total.labels(method='GET', status='500', route='/api/users').inc()
return jsonify({'error': 'Internal error'}), 500
# PromQL:计算每秒请求率
rate(http_requests_total[5m])
# 按状态码分组统计
sum by (status) (rate(http_requests_total[5m]))
# 错误率
sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m]))
2.2 Gauge(仪表盘)
from prometheus_client import Gauge
# 内存使用量(可增可减)
memory_usage_bytes = Gauge(
'memory_usage_bytes',
'Current memory usage',
['instance']
)
# 更新值
memory_usage_bytes.labels(instance='web-01').set(get_memory_usage())
# 增减
queue_length = Gauge('queue_length', 'Current queue length')
queue_length.inc() # +1
queue_length.dec(5) # -5
queue_length.set(10) # 设为 10
2.3 Histogram(直方图)
from prometheus_client import Histogram
# 请求延迟直方图
request_duration = Histogram(
'http_request_duration_seconds',
'HTTP request latency',
['route'],
buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
)
# 记录延迟
start = time.time()
process_request()
request_duration.labels(route='/api/checkout').observe(time.time() - start)
# 直方图在 Prometheus 中存储为多个时间序列:
# _bucket(le="xxx"):各桶的累计计数
# _sum:所有观测值的总和
# _count:观测总数
# 计算 P95 延迟
histogram_quantile(0.95,
sum by (le, route) (
rate(http_request_duration_seconds_bucket{route="/api/checkout"}[5m])
)
)
# 平均延迟
rate(http_request_duration_seconds_sum[5m]) /
rate(http_request_duration_seconds_count[5m])
2.4 Summary(摘要)
from prometheus_client import Summary
# 客户端预计算分位数(服务端压力小,客户端压力大)
request_latency = Summary(
'http_request_latency_seconds',
'Request latency',
['method'],
# 计算 P50 和 P95
quantiles=[(0.5, 0.05), (0.95, 0.01)]
)
Histogram vs Summary:Histogram 在服务端计算分位数,适合聚合多个实例。Summary 在客户端计算,不可聚合但精确。绝大多数场景推荐 Histogram。
三、服务发现(Service Discovery)
3.1 Kubernetes 服务发现
# prometheus.yml
scrape_configs:
# 发现 Pod
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- default
- production
relabel_configs:
# 只抓取带有 prometheus.io/scrape: "true" 注解的 Pod
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
# 从注解中读取端口
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
# 添加标签
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
# 发现 Service Endpoints
- job_name: 'kubernetes-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
3.2 File SD(文件服务发现)
# prometheus.yml
scrape_configs:
- job_name: 'file-sd'
file_sd_configs:
- files:
- /etc/prometheus/targets/*.json
refresh_interval: 30s
// /etc/prometheus/targets/web-servers.json
[
{
"targets": ["web-01:9100", "web-02:9100"],
"labels": {
"env": "production",
"tier": "frontend"
}
}
]
四、PromQL 高级查询
4.1 基础查询
# 瞬时向量 —— 当前值
http_requests_total
# 范围向量 —— 过去 5 分钟的数据
http_requests_total[5m]
# 偏移查询
http_requests_total offset 1d
# 标签过滤
http_requests_total{status="200", method="GET"}
http_requests_total{status=~"2.."} # 正则匹配
http_requests_total{status!~"4..|5.."} # 反向正则
4.2 聚合操作
# 按标签分组求和
sum by (status) (rate(http_requests_total[5m]))
# 计算每个实例的 CPU 使用率
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Top 5 内存使用量
topk(5, container_memory_usage_bytes)
# 分位数
quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
4.3 二元运算
# 错误率计算
sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m]))
# 内存使用率
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) /
node_memory_MemTotal_bytes * 100
# 磁盘使用率
(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) /
node_filesystem_size_bytes{mountpoint="/"} * 100
4.4 预测与同比环比
# 预测 4 小时后磁盘是否满
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 4 * 3600) < 0
# 同比增长(对比昨天同一时刻)
(
sum(rate(http_requests_total[5m]))
-
sum(rate(http_requests_total[5m] offset 1d))
) / sum(rate(http_requests_total[5m] offset 1d))
# 环比(对比 5 分钟前)
(
sum(rate(http_requests_total[5m]))
-
sum(rate(http_requests_total[5m] offset 5m))
) / sum(rate(http_requests_total[5m] offset 5m))
五、Recording Rule 与告警规则
5.1 Recording Rule(记录规则)
# recording_rules.yml
groups:
- name: http_rules
interval: 30s
rules:
# 预计算请求率,加速查询
- record: job:http_requests:rate5m
expr: |
sum by (job, status) (
rate(http_requests_total[5m])
)
# P95 延迟
- record: job:http_request_latency:p95
expr: |
histogram_quantile(0.95,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
5.2 告警规则
# alerting_rules.yml
groups:
- name: service_alerts
rules:
# 高错误率
- alert: HighErrorRate
expr: |
(
sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total[5m]))
) > 0.05
for: 5m
labels:
severity: critical
team: backend
annotations:
summary: "High error rate on {{ $labels.job }}"
description: "Error rate is {{ $value | humanizePercentage }}"
# 高延迟
- alert: HighLatency
expr: |
histogram_quantile(0.95,
sum by (le, job) (
rate(http_request_duration_seconds_bucket[5m])
)
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "P95 latency > 2s on {{ $labels.job }}"
# 实例宕机
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} down"
六、Alertmanager
6.1 路由与分组
# alertmanager.yml
global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alerts@example.com'
route:
# 默认路由
receiver: 'default'
group_by: ['alertname', 'job']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
# critical 级别 → PagerDuty
- match:
severity: critical
receiver: pagerduty-critical
continue: false
# 按团队路由
- match:
team: backend
receiver: backend-slack
- match:
team: frontend
receiver: frontend-slack
receivers:
- name: default
slack_configs:
- api_url: 'https://hooks.slack.com/xxx'
channel: '#alerts'
- name: pagerduty-critical
pagerduty_configs:
- service_key: '<key>'
- name: backend-slack
slack_configs:
- api_url: 'https://hooks.slack.com/xxx'
channel: '#backend-alerts'
6.2 抑制与静默
# 抑制:高错误率时不发实例宕机告警
inhibit_rules:
- source_match:
alertname: HighErrorRate
severity: critical
target_match:
alertname: InstanceDown
equal: ['job', 'instance']
# 静默:计划维护期间
# 通过 Alertmanager UI 或 API 创建静默规则
七、高可用与扩展
7.1 Prometheus HA 联邦
# 联邦配置:中心 Prometheus 抓取边缘 Prometheus
scrape_configs:
- job_name: 'federate'
scrape_interval: 15s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job=~".*"}'
static_configs:
- targets:
- 'prometheus-dc1:9090'
- 'prometheus-dc2:9090'
7.2 Thanos 架构
Thanos 扩展架构:
┌──────────────────────────────────────────────┐
│ Querier — 全局查询层 │
│ 聚合多个 Store/Sidecar 的数据 │
└──────────────┬───────────────────────────────┘
│
┌──────────┼──────────┐
↓ ↓ ↓
┌───────┐ ┌───────┐ ┌───────┐
│StoreGW│ │StoreGW│ │StoreGW│ ──→ 读取对象存储的历史数据
│(S3) │ │(S3) │ │(GCS) │
└───────┘ └───────┘ └───────┘
↑ ↑ ↑
│ │ │
┌─────────┐ ┌─────────┐ ┌─────────┐
│Prom+Side│ │Prom+Side│ │Prom+Side│ ──→ 本地 Prometheus + Sidecar
│ (DC 1) │ │ (DC 2) │ │ (DC 3) │
└─────────┘ └─────────┘ └─────────┘
│ │ │
↓ ↓ ↓
对象存储(S3/GCS/Azure Blob)← Compactor 压缩数据
7.3 VictoriaMetrics
# 用 VictoriaMetrics 替代 Prometheus(更高性能/更低资源)
# docker-compose.yml
version: '3'
services:
victoriametrics:
image: victoriametrics/victoria-metrics:latest
ports:
- "8428:8428"
volumes:
- vmdata:/storage
command:
- '-storageDataPath=/storage'
- '-retentionPeriod=30d'
vmagent:
image: victoriametrics/vmagent:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '-promscrape.config=/etc/prometheus/prometheus.yml'
- '-remoteWrite.url=http://victoriametrics:8428/api/v1/write'
volumes:
vmdata:
八、常用 Exporter
| Exporter | 用途 | 端口 |
|---|---|---|
| node_exporter | Linux 系统指标 | 9100 |
| blackbox_exporter | HTTP/ICMP/DNS/TCP 探活 | 9115 |
| cadvisor | 容器指标 | 8080 |
| postgres_exporter | PostgreSQL | 9187 |
| redis_exporter | Redis | 9121 |
| mysql_exporter | MySQL | 9104 |
| kafka_exporter | Kafka | 9308 |
| elasticsearch_exporter | Elasticsearch | 9114 |
| nginx_exporter | Nginx | 9113 |
九、Prometheus Checklist
| 检查项 | 配置/实践 |
|---|---|
| 指标命名规范 | service_name_unit_total — 全小写+下划线 |
| 标签基数控制 | 避免高基数标签(如 user_id、order_id) |
| 抓取间隔 | 15-30s(平衡精度与开销) |
| 保留期 | 15d(本地)+ 远程存储(长期) |
| Recording Rule | 复杂查询预计算 |
| 告警 for 持续时间 | 避免毛刺误报 |
| 标签一致性 | job、instance、env 在所有指标上统一 |
| 高可用 | Thanos / Cortex / VictoriaMetrics |
参考与延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。