概述
Prometheus 默认是单节点架构,这在生产环境中是一个危险的隐患。一个 Prometheus 实例挂掉意味着整个监控体系失明——你无法在故障期间看到任何指标,告警也会因为规则不评估而完全失效。当数据量增长到单机存储和处理能力的极限时,还会面临写入超时、查询缓慢、磁盘爆满等问题。
本文系统性地分析 Prometheus 高可用和水平扩展方案,从最简单的双副本到 Thanos、Mimir、VictoriaMetrics、Cortex 等远程存储方案,帮助你根据实际场景做出正确的技术选型。
一、单点问题分析
1.1 单点 Prometheus 的风险
┌──────────────┐ ┌───────────────┐ ┌──────────┐
│ Exporters │ ──→ │ Prometheus │ ──→ │ Grafana │
│ (targets) │ │ (单节点) │ │ Alertmgr│
└──────────────┘ └───────────────┘ └──────────┘
│
┌──────┴──────┐
│ 本地 TSDB │
│ (15-30 天) │
└─────────────┘
这个架构的脆弱点:
| 风险点 | 影响 | 发生概率 |
|---|---|---|
| Prometheus 进程崩溃 | 监控完全中断,告警失效 | 中 |
| 宿主机宕机 | 同上,且可能丢失最近数据 | 中 |
| 磁盘故障 | 历史数据丢失 | 低-中 |
| 磁盘空间耗尽 | 写入失败,数据丢失 | 中-高 |
| 单机内存/CPU 不足 | 写入延迟、查询超时 | 高(数据量增长后) |
| 网络分区 | 部分 target 无法采集 | 中 |
1.2 单机性能瓶颈
Prometheus 的性能受以下因素制约:
- 时间序列数量:每百万条活跃时间序列约占 1-2 GB 内存
- 采集速率:单机推荐每秒处理不超过 100 万采样点
- 查询复杂度:大范围 PromQL 查询可能导致 OOM
- 本地存储:TSDB 默认保留 15 天,长时间保留需要大量磁盘
# 检查 Prometheus 活跃时间序列数量
curl -s http://localhost:9090/api/v1/status/tsdb | jq '.data.seriesCountByMetricName | length'
# 检查写入速率
curl -s http://localhost:9090/api/v1/status/tsdb | jq '.data.headStats'
当单实例的活跃时间序列超过 200 万或写入速率超过 80 万/秒时,就该考虑水平扩展了。
二、双副本方案
2.1 双副本架构
最直接的高可用方案是部署两个完全相同的 Prometheus 实例,采集相同的目标:
┌──────────────┐
│ Exporters │
└──────┬───────┘
│
┌───┴───┐
▼ ▼
┌─────────┐ ┌─────────┐
│ Prom-A │ │ Prom-B │
│ (副本1) │ │ (副本2) │
└────┬────┘ └────┬────┘
│ │
▼ ▼
┌──────────────────────┐
│ Alertmanager HA │
│ (Gossip 去重) │
└──────────────────────┘
两个 Prometheus 实例独立采集和评估告警规则,都向 Alertmanager 发送告警。Alertmanager 通过 Gossip 协议在实例间去重,确保同一告警只发送一次通知。
2.2 Alertmanager HA 配置
# Alertmanager 集群配置
alerting:
alertmanagers:
- static_configs:
- targets:
- 'alertmanager-1:9093'
- 'alertmanager-2:9093'
- 'alertmanager-3:9093'
Alertmanager 启动时通过 --cluster.peer 参数组成集群:
# alertmanager-1
alertmanager \
--config.file=/etc/alertmanager/config.yml \
--storage.path=/data/alertmanager \
--cluster.listen-address=0.0.0.0:9094 \
--cluster.peer=alertmanager-2:9094 \
--cluster.peer=alertmanager-3:9094
# alertmanager-2
alertmanager \
--config.file=/etc/alertmanager/config.yml \
--storage.path=/data/alertmanager \
--cluster.listen-address=0.0.0.0:9094 \
--cluster.peer=alertmanager-1:9094 \
--cluster.peer=alertmanager-3:9094
2.3 双副本的局限
双副本解决了单点故障问题,但有以下局限:
- 存储翻倍:两个实例各自存储完整数据,存储成本翻倍
- 查询需外部去重:Grafana 查询时需要指定数据源,两个实例的数据有微小差异(采集时间点不完全一致)
- 无法水平扩展:单实例的采集和处理能力上限没有改变
- 无长期存储:仍然依赖本地 TSDB,无法保留超过 30 天的历史数据
双副本方案适合中小规模(活跃时间序列 < 100 万)的监控需求,是成本最低的高可用方案。
三、远程存储方案概述
当单机性能或存储容量成为瓶颈时,需要引入远程存储。Prometheus 原生支持 remote_write 和 remote_read 接口,可以将数据流式传输到外部存储系统。
┌─────────────────────────────────────────────────────┐
│ 各集群 Prometheus │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Prom-1 │ │ Prom-2 │ │ Prom-3 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └────────────┼────────────┘ │
│ │ remote_write │
└────────────────────┼─────────────────────────────────┘
│
▼
┌──────────────────────┐
│ 远程存储后端 │
│ (Thanos/Mimir/VM) │
└──────────┬───────────┘
│
┌──────────┴───────────┐
│ 全局查询 / 长期存储 │
│ (PromQL 兼容) │
└──────────────────────┘
主流远程存储方案对比:
| 方案 | 开发者 | 核心特性 | 对象存储 | 多租户 | 成熟度 |
|---|---|---|---|---|---|
| Thanos | Improbable | Sidecar + 对象存储 + 全局查询 | 支持 | 不支持 | 高 |
| Mimir | Grafana Labs | Cortex 重写版,水平扩展强 | 支持 | 支持 | 高 |
| VictoriaMetrics | VictoriaMetrics | 自研存储引擎,性能极高 | 支持 | 支持(企业版) | 高 |
| Cortex | Grafana Labs | Mimir 前身,多租户 | 支持 | 支持 | 维护模式 |
| InfluxDB | InfluxData | 时序数据库,非 Prom 生态 | 不支持 | 支持 | 中 |
四、Thanos:最流行的远程存储方案
4.1 Thanos 架构
┌──────────────────────────────────────────────────────────┐
│ Thanos 架构 │
│ │
│ ┌─────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Prom + │ │ Thanos │ │ Thanos │ │
│ │ Sidecar │ │ Store │ │ Compactor │ │
│ │ (上传) │ │ (读历史数据) │ │ (降采样) │ │
│ └────┬────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ │ ▼ │
│ ┌─────────────────────┴───────────────────┐ │
│ │ 对象存储 (S3/GCS/MinIO) │ │
│ └─────────────────────┬───────────────────┘ │
│ │ │
│ ┌─────────────────────┴───────────────┐ │
│ │ Thanos Query │ │
│ │ (全局 PromQL 查询入口) │ │
│ └─────────────────────┬───────────────┘ │
│ │ │
│ ┌─────────────────────┴───────────────┐ │
│ │ Thanos Query Frontend │ │
│ │ (查询缓存 / 分片 / 限流) │ │
│ └─────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
Thanos 的核心组件:
| 组件 | 作用 |
|---|---|
| Sidecar | 部署在 Prometheus 旁,将 TSDB 块上传到对象存储 |
| Store | 从对象存储读取历史数据,响应 Query 请求 |
| Compactor | 对对象存储中的数据进行降采样和压缩 |
| Query | 接收 PromQL 查询,从多个数据源(Sidecar/Store/Ruler)获取结果 |
| Query Frontend | 查询缓存、分片、限流 |
| Ruler | 独立评估告警规则(不依赖 Prometheus 实例) |
| Receiver | 接收 remote_write 数据(可选,支持写入路径高可用) |
4.2 Sidecar 模式部署
# Prometheus + Thanos Sidecar (K8s Deployment)
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
spec:
replicas: 1
template:
spec:
containers:
- name: prometheus
image: prom/prometheus:v2.52.0
args:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=24h' # 本地只保留 24h,历史数据上传到对象存储
- '--storage.tsdb.min-block-duration=2h'
- '--storage.tsdb.max-block-duration=2h'
- '--web.enable-lifecycle'
ports:
- containerPort: 9090
- name: thanos-sidecar
image: thanosio/thanos:v0.35.0
args:
- sidecar
- --tsdb.path=/prometheus
- --prometheus.url=http://localhost:9090
- --objstore.config-file=/etc/thanos/objstore.yml
- --shipper.upload-compacted
volumeMounts:
- name: prometheus-data
mountPath: /prometheus
对象存储配置(以 S3 为例):
# objstore.yml
type: S3
config:
bucket: thanos-storage
endpoint: s3.us-east-1.amazonaws.com
region: us-east-1
access_key: AKIAIOSFODNN7EXAMPLE
secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
insecure: false
4.3 全局查询
Thanos Query 对接 Grafana,提供跨集群全局查询能力:
# Thanos Query 部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: thanos-query
spec:
template:
spec:
containers:
- name: query
image: thanosio/thanos:v0.35.0
args:
- query
- --http-address=0.0.0.0:9090
- --grpc-address=0.0.0.0:10901
- --store=thanos-sidecar-cluster-a:10901 # 集群 A 的实时数据
- --store=thanos-sidecar-cluster-b:10901 # 集群 B 的实时数据
- --store=thanos-store:10901 # 对象存储中的历史数据
- --query.replica-label=replica # 去重标签
ports:
- containerPort: 9090
通过 --query.replica-label=replica,Thanos Query 会自动对双副本 Prometheus 的重复数据进行去重,查询时返回一致性结果。
4.4 Thanos 的优势与局限
优势:
- 无侵入式接入,Prometheus 配置改动最小
- 全局查询,跨集群统一视图
- 对象存储成本低(S3 约 $0.023/GB/月)
- 支持降采样(5m → 1h → 精度递减),长周期查询性能好
- 社区活跃,生产案例多
局限:
- Sidecar 模式依赖 Prometheus 本地 TSDB 的 2 小时 block 机制,数据上传有延迟
- 不原生支持水平扩展写入(需 Receiver + ingestion blocks)
- 组件较多,运维复杂度中等
- 不支持多租户
五、Mimir:Grafana Labs 的新一代方案
5.1 Mimir 架构
Mimir 是 Grafana Labs 对 Cortex 的重写版本,采用微服务架构,原生支持水平扩展和多租户。
┌──────────────────────────────────────────────────┐
│ Mimir 架构 │
│ │
│ Prom ──remote_write──→ ┌──────────────┐ │
│ │ Distributor │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ Ingester │ │
│ │ (内存写入层) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ Store-gw │ │
│ │ (历史数据读) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────┴───────┐ │
│ │ Querier │ │
│ │ (PromQL 查询) │ │
│ └──────────────┘ │
│ │
│ 对象存储 (S3) ←── 块存储 / 索引 / 元数据 ──→ │
│ │
│ Consul/Memberlist ←── 服务发现 ──→ │
└──────────────────────────────────────────────────┘
5.2 Prometheus remote_write 配置
# prometheus.yml
remote_write:
- url: http://mimir-distributor:8080/api/v1/push
headers:
X-Scope-OrgID: tenant-1 # 多租户 ID
write_relabel_configs:
- source_labels: [__name__]
regex: 'go_(gc|memstats)_.+'
action: drop # 丢弃不需要的指标,减少写入量
queue_config:
capacity: 10000
max_samples_per_send: 2000
batch_send_deadline: 5s
min_backoff: 30ms
max_backoff: 100ms
5.3 Mimir vs Thanos
| 维度 | Thanos | Mimir |
|---|---|---|
| 写入路径 | Sidecar 被动上传(2h block) | remote_write 主动推送(实时) |
| 写入延迟 | 2 小时(block 完成) | 秒级 |
| 水平扩展 | 有限(Receiver 可扩展但有瓶颈) | 原生水平扩展 |
| 多租户 | 不支持 | 原生支持 |
| 查询性能 | 中等 | 高(有查询缓存和分片) |
| 组件复杂度 | 中 | 高 |
| 对象存储 | S3/GCS/Azure/MinIO | S3/GCS/Azure/MinIO |
| 告警评估 | Ruler 组件 | Ruler 组件 |
| 压缩/降采样 | Compactor | Compactor |
| 社区活跃度 | 高 | 高 |
选型建议:单集群或少量集群优先考虑 Thanos,简单且足够。多租户、大规模(活跃时间序列 > 1000 万)或需要毫秒级写入延迟时选择 Mimir。
六、VictoriaMetrics:高性能自研存储
6.1 架构特点
VictoriaMetrics(VM)使用自研的列式存储引擎,在写入吞吐和查询性能上显著优于基于 TSDB 的方案。
┌──────────────────────────────────────────────────────┐
│ VictoriaMetrics 架构 │
│ │
│ Prom ──remote_write──→ ┌──────────────────┐ │
│ │ vminsert │ │
│ │ (写入入口,LB) │ │
│ └────────┬──────────┘ │
│ │ │
│ ┌────────┴──────────┐ │
│ │ vmstorage (×N) │ │
│ │ (数据分片存储) │ │
│ └────────┬──────────┘ │
│ │ │
│ ┌────────┴──────────┐ │
│ │ vmselect │ │
│ │ (查询入口,合并) │ │
│ └───────────────────┘ │
└──────────────────────────────────────────────────────┘
6.2 集群模式部署
# 单节点模式(快速体验)
./victoria-metrics \
-storageDataPath=/data \
-retentionPeriod=12 \
-httpListenAddr=:8428
# 集群模式(生产环境)
# vmstorage 节点(数据存储,3 个节点)
./vmstorage \
-storageDataPath=/data \
-retentionPeriod=12 \
-httpListenAddr=:8482
# vminsert 节点(写入入口)
./vminsert \
-httpListenAddr=:8480 \
-storageNode=vmstorage-1:8400,vmstorage-2:8400,vmstorage-3:8400
# vmselect 节点(查询入口)
./vmselect \
-httpListenAddr=:8481 \
-storageNode=vmstorage-1:8400,vmstorage-2:8400,vmstorage-3:8400
6.3 VictoriaMetrics 优势
| 优势 | 说明 |
|---|---|
| 极致性能 | 列式压缩 + 内存映射,写入吞吐比 Prometheus 高 3-5 倍 |
| 低存储成本 | 压缩率比 Prometheus 高 5-10 倍 |
| PromQL + MetricsQL | 兼容 PromQL,额外提供 MetricsQL 扩展函数 |
| 原生高可用 | 集群模式原生支持副本和分片 |
| 单二进制部署 | 单节点模式只有一个二进制文件,部署极简 |
| 内置降采样 | 自动对不同时间范围的数据做降采样 |
| 成本低 | 开源版免费,企业版支持多租户和告警 |
6.4 vmagent:轻量级采集代理
VM 还提供 vmagent,可替代 Prometheus 做采集,支持更多服务发现方式和远程写入:
./vmagent \
-promscrape.config=/etc/vmagent/prometheus.yml \
-remoteWrite.url=http://vminsert:8480/insert/0/prometheus/api/v1/write \
-remoteWrite.url=http://backup-vminsert:8480/insert/0/prometheus/api/v1/write \
-remoteWrite.multitenantURL=http://vminsert:8480/insert/multitenant/prometheus/api/v1/write
vmagent 支持同时写入多个远程存储(多活写入),写入失败自动重试,是替代 Prometheus 采集层的轻量方案。
七、联邦集群
7.1 联邦架构
联邦是 Prometheus 原生提供的高可用和聚合查询方案,通过 /federate 端点从一个 Prometheus 拉取另一个 Prometheus 的指标。
┌─── 区域 A ──────────┐ ┌─── 区域 B ──────────┐
│ Prometheus-A │ │ Prometheus-B │
│ (采集 A 区域 targets)│ │ (采集 B 区域 targets)│
└────────┬────────────┘ └────────┬────────────┘
│ │
│ scrape /federate │
│ ←────────────────────────│
▼ ▼
┌──────────────────────────────────────────────┐
│ 全局 Prometheus (联邦) │
│ (聚合查询,跨区域视图) │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────┐
│ Grafana │
└──────────┘
7.2 联邦配置
# 全局 Prometheus
scrape_configs:
- job_name: 'federate'
scrape_interval: 30s
honor_labels: true
metrics_path: '/federate'
params:
'match[]':
- '{job="node"}'
- '{job="mysql"}'
- '{__name__=~"up|prometheus_.*|alertmanager_.*"}'
- '{alertname!=""}' # 告警指标
static_configs:
- targets:
- 'prometheus-region-a:9090'
- 'prometheus-region-b:9090'
relabel_configs:
- source_labels: [__address__]
regex: 'prometheus-(.+):9090'
target_label: source_prometheus
replacement: '${1}'
match[] 参数控制联邦拉取的指标范围。honor_labels: true 确保原始标签不被覆盖。
7.3 联邦的局限
- 查询压力传递:联邦查询会在子 Prometheus 上执行,大量联邦请求会增加子节点负载
- 级联延迟:数据从子 Prometheus → 联邦 Prometheus,存在 1-2 个采集周期的延迟
- 不支持跨 Prometheus 查询聚合:
sum(rate(metric[5m]))会在每个子 Prometheus 上分别计算再聚合,结果可能不准确 - 无长期存储:联邦不解决存储扩展问题
结论:联邦适合小规模集群的简单聚合查询。如果需要跨集群精确聚合查询或长期存储,应使用 Thanos/Mimir/VictoriaMetrics。
八、Cortex 架构(了解)
Cortex 是 Grafana Labs 的早期方案,现已逐步被 Mimir 取代。了解其架构有助于理解 Mimir 的设计。
Cortex 与 Mimir 的关系:
| 维度 | Cortex | Mimir |
|---|---|---|
| 状态 | 维护模式 | 积极开发 |
| 架构 | 微服务 | 微服务(优化) |
| 存储引擎 | 基于 chunks | 基于 blocks(兼容 Prometheus TSDB) |
| 兼容性 | PromQL 部分 | 完全兼容 PromQL |
| 性能 | 中 | 高(2-5x Cortex) |
| 迁移 | 可迁移到 Mimir | — |
新项目不建议选择 Cortex,直接使用 Mimir。
九、方案选型对比
9.1 综合对比矩阵
| 维度 | 双副本 | 联邦 | Thanos | Mimir | VictoriaMetrics |
|---|---|---|---|---|---|
| 高可用 | ✓ | ✓ | ✓✓ | ✓✓✓ | ✓✓ |
| 长期存储 | ✗ | ✗ | ✓✓ | ✓✓ | ✓✓✓ |
| 水平扩展 | ✗ | ✗ | ✓ | ✓✓✓ | ✓✓✓ |
| 多租户 | ✗ | ✗ | ✗ | ✓✓ | ✓(企业版) |
| 全局查询 | ✗ | ✓ | ✓✓ | ✓✓✓ | ✓✓ |
| 部署复杂度 | 低 | 低 | 中 | 高 | 低-中 |
| 存储成本 | 高 | 中 | 低(对象存储) | 低(对象存储) | 极低 |
| 查询性能 | 高 | 中 | 中-高 | 高 | 极高 |
| 运维复杂度 | 低 | 低 | 中 | 高 | 低-中 |
9.2 选型决策框架
活跃时间序列 < 50 万?
├── 是 → 双副本 + Alertmanager HA(最简方案)
└── 否 → 活跃时间序列 < 200 万?
├── 是 → 单集群 Thanos Sidecar(对象存储 + 全局查询)
└── 否 → 需要多租户?
├── 是 → Mimir(原生多租户 + 水平扩展)
└── 否 → 追求极致性能?
├── 是 → VictoriaMetrics 集群
└── 否 → Thanos Receiver 或 Mimir
9.3 按场景推荐
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 初创团队 / 小规模 | 双副本 | 成本最低,运维简单 |
| 单 K8s 集群 | Thanos Sidecar | 无侵入接入,社区成熟 |
| 多 K8s 集群 | Thanos / VM | 全局查询 + 对象存储 |
| SaaS 平台 | Mimir | 原生多租户 + 水平扩展 |
| 大规模 / 追求性能 | VictoriaMetrics | 存储压缩率最高,查询性能最强 |
| 需要可视化告警一体化 | Thanos / Mimir + Grafana | Grafana 生态深度集成 |
十、生产实践建议
10.1 数据分层保留
# Thanos Compactor 降采样配置
# 原始数据保留 30 天,5m 降采样保留 90 天,1h 降采样保留 1 年
compaction:
retention_resolution_raw: 30d
retention_resolution_5m: 90d
retention_resolution_1h: 365d
10.2 remote_write 调优
remote_write:
- url: 'http://thanos-receive:19291/api/v1/receive'
queue_config:
capacity: 10000 # 队列容量
max_samples_per_send: 2000 # 每批发送采样数
batch_send_deadline: 5s # 批量发送超时
min_backoff: 30ms # 最小重试间隔
max_backoff: 100ms # 最大重试间隔
remote_timeout: 30s
write_relabel_configs:
# 丢弃不需要的指标
- source_labels: [__name__]
regex: 'go_(gc|memstats|threads)_.+'
action: drop
- source_labels: [__name__]
regex: 'prometheus_.+'
action: drop
10.3 监控你的监控
别忘了监控 Prometheus 自身和远程存储:
# 监控 Thanos 组件
scrape_configs:
- job_name: 'thanos-sidecar'
static_configs:
- targets: ['thanos-sidecar:10902']
- job_name: 'thanos-query'
static_configs:
- targets: ['thanos-query:10902']
# 关键告警规则
groups:
- name: prometheus-ha
rules:
- alert: PrometheusRemoteWriteFailures
expr: rate(prometheus_remote_storage_failed_samples_total[5m]) > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Prometheus remote write 失败"
description: "实例 {{ $labels.instance }} remote write 失败率 > 0"
- alert: ThanosSidecarUploadFailing
expr: rate(thanos_sidecar_bucket_uploads_failures_total[5m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: "Thanos Sidecar 上传失败"
总结
Prometheus 高可用和水平扩展是一个渐进式选择,没有一劳永逸的方案。核心决策路径:
- 规模判断先行:先评估活跃时间序列数量、写入速率和存储保留需求,再决定方案
- 双副本是底线:无论什么规模,双副本 Prometheus + Alertmanager HA 是高可用的基本保障
- Thanos 适合多集群:无侵入式 Sidecar 模式,对象存储成本低,社区成熟,是多集群场景的首选
- Mimir 适合大规模多租户:原生水平扩展和多租户,适合 SaaS 平台和超大规模监控
- VictoriaMetrics 追求性能:存储压缩率和查询性能最优,适合对成本和性能敏感的场景
- 联邦方案仅适合小规模:简单但局限大,大规模场景应迁移到 Thanos 或 VM
记住:监控系统的可用性决定了你的运维上限。一个不可靠的监控系统,比没有监控更危险——因为它给你虚假的安全感。
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- Prometheus 官方文档 — HA — Prometheus 官方,参考了Prometheus 官方文档 — HA相关内容
- Thanos 官方文档 — Thanos 项目,参考了Thanos 官方文档相关内容