Administrator
Administrator
发布于 2026-11-03 / 0 阅读
0
0

Prometheus 从入门到生产实践(21):高可用架构:双 Prometheus 与 Alertmanager 集群

本篇是《Prometheus 从入门到生产实践》第 21 / 24 篇。配置以文中版本与环境前提为准,实验和故障均为教学场景。完整程序、配置及校验范围见配套实验包。

独立 Prometheus 双副本与 Alertmanager 集群

高可用要先回答“哪种故障发生后,哪项能力还能继续”。两个进程都在运行,不代表历史查询、规则求值、通知与数据备份都实现了高可用。本篇把 Prometheus 双副本和 Alertmanager 集群分开设计,再连接起来验证。

1. 双副本不是同一个 TSDB 的两个写入进程

常见模式是两台 Prometheus 独立抓取同一批目标、各自存储和求值。任意一台失效,另一台仍可继续采集和发出告警;代价是目标收到两次抓取,存储和计算资源也接近两份。

两台之间并不自动复制本地历史,也没有内建 leader 让另一台只待机。若它们看到的网络、目标或采样时刻不同,短窗口查询也可能出现合理差异。将一个查询负载均衡放在前面,可以改善入口可用性,但不能自动合并两份缺失的历史。

因此,每个副本要有独立数据目录,尽量分布在不同主机或故障域。两份程序放在同一台机器上,只适合验证进程级故障,不足以证明宿主机级高可用。

2. 外部标签标明数据来自哪一组副本

下面是副本 A 的独立配置,B 的文件只把 replica 改为 b;配套文件为 c21-prom-a.yml、c21-prom-b.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    monitor_cluster: lab
    replica: a
rule_files:
  - c21-ha.rules.yml
alerting:
  alert_relabel_configs:
    - action: labeldrop
      regex: replica
  alertmanagers:
    - static_configs:
        - targets: ['127.0.0.1:19093', '127.0.0.1:29093']
scrape_configs:
  - job_name: demo
    static_configs:
      - targets: ['127.0.0.1:19100']

global.external_labels 常用于向外部系统传输时标识监控来源;它们不是把所有本地样本都原地增加相同标签的机制。本机查询中没有看到 replica,并不能据此认定配置失效。

monitor_cluster 在这里区分不同监控集群,replica 区分同一组里的副本。外部标签与 relabel 的阶段见 Prometheus 配置文档。应用自己暴露的同名标签也可能影响最终身份,因此需要建立统一命名约定。

3. 发送给 Alertmanager 的告警身份必须一致

两份相同业务告警若分别带 replica=a、replica=b,完整标签集合就不同,Alertmanager 会将它们视为不同告警实例。示例使用 alert_relabel_configs 在发送阶段移除 replica,但保留 monitor_cluster 和业务维度。

不能为了去重把 cluster、environment、instance 一股脑删掉,否则不同环境或不同故障对象也可能合并。副本还需要一致的规则、目标标签和相关配置,仅移除 replica 无法修复其他标签差异。

配套规则如下,故障持续一分钟用于缩短实验,不是建议所有业务采用这一时长:

groups:
  - name: ha-lab
    rules:
      - alert: DemoTargetUnavailable
        expr: up{job="demo"} == 0
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: 'demo 抓取失败:{{ $labels.instance }}'

告警内容不同但标签相同,也可能造成难以理解的覆盖和通知行为。把变化的测量值写进 annotations,将识别对象的稳定字段留在 labels。

4. Prometheus 应把告警发给所有 Alertmanager 成员

Alertmanager 集群成员通过 gossip 协调静默和通知日志等状态,但不是靠一个共享数据库同步所有内存告警。每个成员应独立收到告警,所以示例明确列出两个地址,而不是只通过一个随机转发的负载均衡地址发送。

成员之间的集群通信端口与对外 Web/API 端口也不同。只放通 Web 端口,可能出现“两个界面都能打开,但集群实际没有连通”的情况。

这套机制优先避免漏报。网络分区时可能出现重复通知,不能对使用者承诺 exactly-once;接收端仍要能关联事件并妥善处理重复。机制见 Alertmanager High Availability。

5. 在同机隔离端口做机制实验

先把 c21-alertmanager.yml 中的 example.test 地址替换为自己授权的测试接收器,按接收器要求补充认证。原占位地址不会发送成功:

route:
  receiver: lab-webhook
  group_by: ['alertname', 'monitor_cluster', 'job']
  group_wait: 15s
  group_interval: 1m
  repeat_interval: 1h
receivers:
  - name: lab-webhook
    webhook_configs:
      - url: https://hooks.example.test/alerts
        send_resolved: true

在不同终端启动两个 Alertmanager,各用独立存储路径:

alertmanager --config.file=c21-alertmanager.yml \
  --storage.path=./data/am-a \
  --web.listen-address=127.0.0.1:19093 \
  --cluster.listen-address=127.0.0.1:19094 \
  --cluster.peer=127.0.0.1:29094
alertmanager --config.file=c21-alertmanager.yml \
  --storage.path=./data/am-b \
  --web.listen-address=127.0.0.1:29093 \
  --cluster.listen-address=127.0.0.1:29094 \
  --cluster.peer=127.0.0.1:19094

再启动两份 Prometheus,分别指定 c21-prom-a.yml、c21-prom-b.yml,存储目录分别为 data/prom-a、data/prom-b,Web 端口分别为 19090、29090。启动前检查端口冲突,不要与前面尚在运行的实验实例共用目录。

6. 按故障矩阵验收,而不是只看绿色图标

先保持 exporter 正常,确认两边 up=1。停掉专用实验 exporter,记录两边 pending、firing 和接收端事件;再依次停止一个 Prometheus、一个 Alertmanager,观察剩余链路能否继续提供预期能力。

恢复组件后,检查目标、规则加载和集群成员状态。再在受控环境模拟成员通信中断,明确记录可能重复通知的边界;不要通过破坏真实网络策略来做随手演练。

如果把两份样本写入远端存储,保留或移除 replica 又是另一项设计。通常需要按后端支持的 HA tracker 或查询去重配置处理,不能直接删掉标签让两份写入撞成同一序列。

7. 两条看起来相同的告警,怎样比较身份

重复通知排查时,先导出两边发送后的最终标签集合,逐项比较 alertname、monitor_cluster、job、instance、environment 和业务对象标识。不要只看 summary,因为两份摘要相同并不意味着标签相同。反过来,不同描述若共享同一完整身份,也可能被当成同一事件处理。

常见差异包括两个副本抓取了不同的地址格式,一边是主机名、另一边是 IP;一份服务发现额外带入 pod UID;某条规则把当前数值放入 label,每次求值就产生新身份。它们需要分别修正发现、规则或标签约定,而不该继续扩大 labeldrop 范围。

随后检查接收器本身:通知请求成功是否代表真正展示给人,超时后是否可能已经被接收再重试,事件平台如何识别重复消息。即使监控端尽量去重,接收端仍可能在网络边界遭遇不确定结果。生产验收要把允许的重复、人工处理方式和升级路径写清楚。

最后区分独立故障域与共同依赖。如果两台 Prometheus 共用一个 DNS、一个电源域或一份被误发布的配置,它们仍可能同时失效。高可用演练除了逐个停进程,还要审查共同依赖,并用独立的监控链路观察这组监控系统。分区实验中收到重复通知是需要解释的结果,不应为了追求零重复而牺牲关键告警的送达机会。

最终应形成一张能力表:单 Prometheus 故障、单通知节点故障、主机故障、网络分区时,采集、查询、告警、通知各剩下什么。这样高可用才是经过解释和演练的承诺。


上一篇:高基数与性能治理:限制、查询成本和容量实验 · 系列目录 · 下一篇:Remote Write 与长期存储:队列、兼容与恢复预算


评论