WEBKT

生产环境Prometheus高可用架构实战:从双写到联邦集群的演进之路

13 0 0 0

前言:单点Prometheus的生产危机

在早期的微服务架构中,单实例Prometheus似乎足以应对监控需求。直到某天凌晨,核心集群的Prometheus节点因磁盘IO瓶颈宕机,我们才发现:监控系统的可用性直接决定了故障恢复的速度

生产环境的Prometheus高可用并非简单的"多副本部署",而是涉及数据一致性、查询聚合、长期存储的系统性工程。本文基于笔者在电商和金融场景的实战经验,梳理从双写到联邦集群的架构演进路径,帮助你在不同业务阶段做出正确的技术选型。


第一阶段:双写(Double Write)—— 快速止损的权宜之计

架构原理

双写是最简单的高可用方案:通过两个独立的Prometheus实例同时抓取相同目标,上层通过负载均衡或DNS轮询进行查询分流。

# prometheus-A.yml 与 prometheus-B.yml 配置完全一致
global:
  external_labels:
    replica: 'A'  # B实例改为'B',用于区分数据源

scrape_configs:
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true

关键问题与解决

数据不一致性:由于抓取时间差,两个实例的指标存在微小差异。在 Grafana 中配置查询时,务必使用 max()avg() 聚合函数消除副本差异:

max by (instance) (up{job="api-gateway"})

告警重复:Alertmanager 的 group_by 需包含 replica 标签,并配置 inhibit_rules 抑制重复告警:

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'critical'
    equal: ['alertname', 'instance']

适用场景与局限

适合场景:中小规模集群(target < 500),短期容灾过渡
致命缺陷

  • 数据无法持久化,本地存储限制在15天(默认)
  • 查询无法跨实例聚合,全局视图缺失
  • 扩容时线性增加资源浪费

第二阶段:远程存储(Remote Storage)—— 打破数据孤岛

当双写无法满足长期存储全局查询需求时,引入远程存储成为必然选择。

方案选型对比

方案 架构复杂度 资源成本 查询性能 适用规模
Thanos 中大型
VictoriaMetrics 极低 极高 全规模
Cortex/Mimir 超大规模

Thanos 实战配置(主流选择)

Thanos Sidecar 模式是最平滑的演进路径,无需改造现有 Prometheus:

# prometheus 启动参数增加
--storage.tsdb.min-block-duration=2h
--storage.tsdb.max-block-duration=2h

# thanos-sidecar 配置
thanos sidecar \
  --tsdb.path=/prometheus/data \
  --objstore.config-file=thanos-bucket.yml \
  --prometheus.url=http://localhost:9090

thanos-bucket.yml 配置对象存储(以MinIO为例):

type: S3
config:
  bucket: "prometheus-metrics"
  endpoint: "minio.monitoring.svc.cluster.local:9000"
  access_key: "xxx"
  secret_key: "xxx"
  insecure: true

架构升级要点

  1. Store Gateway:负责历史数据查询,需独立部署避免影响实时写入
  2. Compactor:定期压缩块文件,降低存储成本90%以上
  3. Query Layer:实现全局 PromQL 查询,自动去重(基于 external_labelsreplica 标签)

第三阶段:联邦集群(Federation)—— 多地域多集群的统一视图

当业务扩展到多可用区、多K8s集群时,分层联邦架构成为唯一选择。

架构拓扑设计

采用 "边缘采集 + 中心聚合" 的两层架构:

[边缘层]                    [中心层]
Prom-A1 (AZ-1) ──┐
Prom-A2 (AZ-1) ──┤──> Thanos Query ──┐
                  │                   │
Prom-B1 (AZ-2) ──┤                   ├──> Global Query
Prom-B2 (AZ-2) ──┘                   │
                                      │
[业务K8s-1] ──> Sidecar ─────────────┤
[业务K8s-2] ──> Sidecar ─────────────┘

联邦抓取配置(关键细节)

中心层 Prometheus 仅抓取边缘的聚合指标,避免网络风暴:

scrape_configs:
  - job_name: 'federate'
    scrape_interval: 15s
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{__name__=~"up|node_cpu_seconds_total|container_memory_usage_bytes"}'
        - '{job="api-gateway"}'
    static_configs:
      - targets:
        - 'edge-prometheus-az1:9090'
        - 'edge-prometheus-az2:9090'

关键技巧:使用 match[] 过滤器仅拉取关键指标,边缘层保留完整数据用于本地故障排查。

高可用强化策略

  1. 反亲和性部署:确保同一集群的 Prometheus 实例分布在不同节点/可用区
  2. 对象存储双活:Thanos 支持多区域对象存储复制,防范单区域故障
  3. 查询层缓存:部署 Thanos Query Frontend,缓存频繁查询结果,降低后端压力

实战演进路线图

基于团队规模和技术储备,建议按以下路径演进:

阶段 集群规模 关键指标 推荐架构 切换时机
起步期 < 50 nodes 数据量 < 100GB 双写 + 本地存储 磁盘告警频繁时
成长期 50-200 nodes 数据量 100GB-1TB Thanos Sidecar + S3 需要跨集群看板时
成熟期 > 200 nodes 多地域部署 联邦集群 + Thanos 单查询超时 > 5s 时

避坑指南

  1. 外部标签冲突:不同集群的 external_labels 必须唯一,建议采用 cluster + replica 组合
  2. 时间同步:所有 Prometheus 节点必须配置 NTP,时间偏差会导致查询结果错位
  3. ** Cardinality 爆炸**:联邦层级只保留低基数指标,高基数指标(如 http_request_duration_seconds_bucket)留在边缘层查询

结语:没有银弹,只有权衡

从双写到联邦集群,本质上是在一致性、可用性、分区容错性之间的持续权衡。对于多数中小团队,Thanos Sidecar + 单联邦层已能支撑万级节点规模;而超大规模场景则需要投入Cortex/Mimir的深度定制。

高可用架构不是一次性设计,而是随着业务 pain point 逐步演进的有机体。建议在每个阶段保留降级方案(如双写模式作为Thanos故障时的fallback),确保监控体系自身的可靠性不低于业务系统。

云原生架构师 Prometheus高可用架构云原生监控

评论点评