
告警发不出去这件事最让人难受的不是技术难而是链路太长、每一段都长得像没问题。Prometheus 采集正常Alertmanager 日志里 receiver 也执行了钉钉群里就是没动静。我从第一次把 Alertmanager 的 webhook 直接怼到钉钉机器人上到后来把 PrometheusAlert 接进链路中间前后踩过的坑基本覆盖了“配置写错”“模板渲染炸了”“消息太长被截断”“机器人被限流”“时间显示成 UTC”这五类。这篇就把 PrometheusAlert 的安装、配置、模板、路由、对接和排错一次性讲透适合已经跑着 Prometheus Alertmanager 但告警体验还很粗糙的运维同学也适合刚接手告警平台、需要快速搭一套能用的通知中心的人。看完你应该能做到半小时内把服务跑起来把钉钉、企业微信、飞书里至少一个渠道打通并且知道出问题该从哪一段开始掐。1. 告警链路上为什么值得插一层 PrometheusAlert1.1 Alertmanager 直连机器人的那几个固有短板Alertmanager 自带的 webhook 接收端其实非常“素”它只负责把一组告警按group_by聚合好然后 POST 到你在webhook_configs里写的地址。剩下的活——拼消息、选样式、 指定的人、按业务分群、留下告警记录——它一概不管。于是很多团队的第一版方案就是把钉钉机器人的 webhook 地址直接填进 Alertmanager靠钉钉那一侧做一点点内容格式适配。这个方案在只监控三五个服务的时候勉强能用一旦服务数量上到几十个问题立刻暴露。第一是模板能力太弱Alertmanager 的templates虽然支持 Go template但想按“告警级别”输出不同颜色、想在企业微信里 值班人、想在消息末尾附上跳转链接配置起来非常别扭。第二是渠道切换成本高今天用钉钉、明天想加飞书、后天要给老板发短信每一次都要动 Alertmanager 的配置文件并 reload。第三是没有记录三天前那条数据库连接数告警到底发没发出去、发给了谁翻聊天记录只能靠人肉搜。第四是路由能力缺失生产库的告警想发给 DBA 群、测试环境的告警想直接丢进一个“噪音群”在 Alertmanager 里靠route树硬写也能做但每加一个业务就要重画一遍匹配规则。PrometheusAlert 正是冲着这四个点来的。它本质是一个告警转发与通知中心上游接 Alertmanager、Grafana、Zabbix甚至你自己写的脚本中间做模板渲染、路由匹配、记录落库下游把渲染好的消息投递到钉钉、企业微信、飞书、邮件、短信、语音、Bark、自定义 Webhook 等一堆通道。链路变成“Alertmanager → PrometheusAlert → 各种机器人”Alertmanager 只管聚合PrometheusAlert 管表达和分发职责一下就清楚了。1.2 它在链路里的准确位置和能力边界我先把这个组件的能力说清楚免得你抱着错误的预期去装。它是一次“转发 渲染 记录”不是“聚合器”也不是“告警规则引擎”。聚合并发这件事仍然由 Alertmanager 的group_by、group_wait、group_interval负责PrometheusAlert 拿到的已经是聚合过后的一批告警了。它不做告警抑制也不做静默的判定那些还是 Alertmanager 的活。它做的是把一批告警渲染成一条或几条人类一眼能读懂的消息然后按你定义的规则送去正确的群。它提供的能力大致有这几块一是多通道通知主流的几个 IM 机器人都覆盖二是模板自定义可以给钉钉一套模板、给飞书另一套模板同一批告警渲染出不同风格三是路由按告警里的某个标签常见是app或者job把消息分派到不同的机器人地址四是告警记录默认落在 SQLite 或者 MySQL 里Web 界面能翻历史五是对外提供 HTTP 接口也就是/prometheusalert这类路径你可以用 curl 直接怼一条消息进去这让它天生适合被自研的发布系统、巡检脚本、批处理任务调用。注意PrometheusAlert 的接收接口默认不做身份校验。你可以把它理解成一个“谁拿到地址谁就能往里发消息”的服务。所以它一定不要直接暴露在公网放在内网、加一层反向代理做 IP 白名单是最省事的做法。1.3 什么规模的团队适合上什么情况可以先不上监控对象少于十个、告警每天不到二十条、只用一个 IM 渠道说实话没必要引入额外组件Alertmanager 直连机器人加一个稍微讲究点的模板就能过日子。多一个组件就多一个故障点这是实话。但只要出现下面任意一种情况我就建议上需要同时投递两个以上渠道不同业务线的告警必须进不同的群需要在消息里 到具体的人需要留一份可检索的告警历史用于事后复盘或者算 SLA自研系统需要程序化地推消息。这几条满足一条引入 PrometheusAlert 带来的收益就明显大于它带来的维护成本了。还有一个容易被忽略的点它能顺手把“人写的脚本要发通知”这件事统一掉。以前每个脚本各自维护一份钉钉 token、各自拼 JSONtoken 一换要满地改。接到 PrometheusAlert 之后脚本只需要 POST 一个 JSON 到固定地址渠道怎么变都不用动脚本。2. 部署前的选型装在哪、用什么存、怎么保证安全2.1 三种部署方式的实际取舍PrometheusAlert 是 Go 写的编译成了单个静态二进制部署方式上有三条路裸机跑二进制、容器跑 Docker、编排跑 Kubernetes。我三种都用过体感差别很明显。二进制方式的好处是排障最直接。日志文件在哪、配置改了有没有生效、端口有没有起来一条ss -lntp就看清了。适合物理机或者长期不变的虚拟机环境也适合你第一次摸这个组件、想先搞清楚它到底怎么跑的阶段。缺点是升级要手动停服、换文件、重启系统级的环境变量还得自己管。Docker 是我目前最推荐的默认选项。镜像里依赖都打包好了配置文件通过挂载进来环境变量通过-e传升级就是改一下 tag 再docker compose up -d。唯一要小心的是数据持久化SQLite 文件和日志目录都要挂到宿主机上否则容器一重建历史记录就没了。Kubernetes 适合本来就跑在集群里的团队好处是配置走 ConfigMap、密码走 Secret、存储走 PVC和其他服务的治理方式一致。但要注意 PrometheusAlert 本身不太适合盲目扩多副本下面讲存储的时候会详细说为什么。部署方式上手难度升级成本适合场景主要坑点二进制低中物理机、虚拟机、初次验证环境变量与 systemd 管理要自己写Docker低低绝大多数中小规模场景数据目录必须挂载出来Kubernetes中低已有集群、追求统一治理多副本与 SQLite 冲突2.2 数据落盘的三条路线内存、SQLite、MySQLPrometheusAlert 的记录存储有三条路线选错了后面会很难受。不落盘、纯内存重启就清空。适合“我只是想转发消息不需要历史”的场景性能最好也最省心。SQLite 是默认选项数据落在本地一个 db 文件里零依赖。单机部署用它完全够用我自己的测试环境跑了几个月几十万条记录也没什么问题。但要注意两点一是文件必须持久化容器里挂载出来二是 SQLite 不支持多进程同时写所以你不能用它来支撑多个 PrometheusAlert 副本。MySQL 适合数据量大、需要长期保留、或者要多副本部署的场景。配置上把驱动换成 mysql填好地址、库名、账号密码即可它会自动建表。多副本的前提就是所有副本指向同一个 MySQL。我的经验判断标准很简单单实例 记录保留一个月以内用 SQLite需要多副本或者记录要跨年保留、要接数据分析上 MySQL。中间那种“记录要留很久但只有单实例”的情况SQLite 也扛得住只是备份要做成定时拷贝文件。2.3 端口、网络与暴露面的规划默认 Web 端口是 8080。这个端口在很多环境里已经被占用了比如某些管理后台部署前先ss -lntp | grep 8080看一眼撞了就换。换端口的方式有两种配置文件的httpport或者启动参数具体名字各版本略有差异装完后用首页能不能打开来验证比背参数名靠谱。网络方向要想清楚两件事。第一PrometheusAlert 需要能访问外网的机器人地址吗如果是钉钉、企业微信、飞书这类 SaaS 机器人答案是必须能出去。如果你们的出口是白名单制要提前把这些域名放行。第二谁能访问它的 8080上游 Alertmanager、Grafana 所在的机器必须能通其他机器尽量关掉。PrometheusAlert 默认有一个 Web 管理界面登录账号默认是admin密码默认是prometheusalert这个默认密码第一次登录就必须改改的方式是设置登录账号密码相关的环境变量或者配置项。还有一个小细节如果你前面挂了 Nginx 做域名注意把请求体的体积放开一点。告警批次大的时候Alertmanager POST 过来的 JSON 可能有好几 MBNginx 默认的client_max_body_size 1m会直接给你 413然后你会在 Alertmanager 日志里看到发送失败但完全不知道是 Nginx 拦的。3. 从零把 PrometheusAlert 跑起来3.1 二进制方式最省事也最好排障二进制方式我一般这么走。先拿到对应平台的压缩包解压之后目录里通常有一个可执行文件、一个conf目录和一份示例配置。把可执行文件丢到/opt/prometheusalert/配置放在/opt/prometheusalert/conf/日志目录建好然后直接前台跑一次看它输出的端口和配置加载信息。mkdir -p /opt/prometheusalert/{conf,logs,db} cd /opt/prometheusalert # 解压后的可执行文件建议重命名成一个固定的名字方便写 systemd mv prometheusalert_linux_amd64 prometheusalert chmod x prometheusalert # 前台先跑一次确认端口和配置没问题 ./prometheusalert前台跑起来之后浏览器打开http://机器IP:8080能看到登录页就说明主进程没问题。这时候用默认账号登进去第一件事改密码第二件事看首页有没有报数据库相关的错误。确认没问题了CtrlC 停掉写 systemd 托管。# /etc/systemd/system/prometheusalert.service [Unit] DescriptionPrometheusAlert Afternetwork.target [Service] Typesimple WorkingDirectory/opt/prometheusalert ExecStart/opt/prometheusalert/prometheusalert Restartalways RestartSec5 EnvironmentTZAsia/Shanghai [Install] WantedBymulti-user.target这里EnvironmentTZAsia/Shanghai这行别省。我最早一次部署就是漏了它结果告警记录里的时间全是 UTC和本地时间差八小时事后复盘时把两条不相干的告警看成同一时刻发生的白白绕了半小时。容器方式同理-e TZAsia/Shanghai加上PrometheusAlert 自己也有时区相关的配置项两边保持一致最稳。3.2 Docker 与 Compose参数怎么传才不乱Docker 方式的核心是把“配置”和“数据”两件事处理干净。配置我倾向于用环境变量传关键项登录账号密码、各渠道 token、数据库连接用配置文件管那些不常变的项端口、日志级别。数据就是 db 文件和 logs 目录必须挂出来。docker run -d \ --name prometheusalert \ --restartalways \ -p 8080:8080 \ -e TZAsia/Shanghai \ -e PA_LOGIN_USERadmin \ -e PA_LOGIN_PASSWORD换成你自己的强密码 \ -v /data/prometheusalert/conf:/app/conf \ -v /data/prometheusalert/db:/app/db \ -v /data/prometheusalert/logs:/app/logs \ feiyu563/prometheusalert:latest用 Compose 会更顺手尤其是升级的时候改个 tag 再up -d就行。写法上我把环境变量集中放在environment段把易变的密码放到同目录的.env文件里Compose 会自动读取这样配置文件可以放心提交到代码仓库密码不会跟着进去。services: prometheusalert: image: feiyu563/prometheusalert:latest container_name: prometheusalert restart: always ports: - 8080:8080 environment: TZ: Asia/Shanghai PA_LOGIN_USER: admin PA_LOGIN_PASSWORD: ${PA_PASSWORD} PA_TIMEZONE: Asia/Shanghai volumes: - ./conf:/app/conf - ./db:/app/db - ./logs:/app/logs关于环境变量的命名这里必须提醒一句不同版本的前缀和拼写有过调整我建议你不要完全照抄网上任何一篇教程包括这篇而是以你拉下来那个版本自带的示例配置为准。做法很简单容器起来之后docker exec -it prometheusalert sh进去把conf目录里的示例配置读一遍再对照官方仓库的说明文档核一遍。这一步花五分钟能省掉后面半小时“为什么我传了 token 还是发不出去”的困惑。3.3 Kubernetes 部署配置、存储与探针K8s 部署我建议拆成四块ConfigMap 放配置文件Secret 放机器人的 token 和数据库密码PVC 放数据和日志Deployment Service Ingress 把它们串起来。探针这块有个实际建议优先用tcpSocket探 8080或者 HTTP 探首页。PrometheusAlert 的健康检查路径在不同版本里不完全一致用 TCP 探针最不容易踩坑因为它只要求端口在监听而这个条件在任何版本里都成立。containers: - name: prometheusalert image: feiyu563/prometheusalert:latest ports: - containerPort: 8080 env: - name: TZ value: Asia/Shanghai - name: PA_LOGIN_PASSWORD valueFrom: secretKeyRef: name: prometheusalert-secret key: login-password volumeMounts: - name: conf mountPath: /app/conf - name: data mountPath: /app/db readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 10 periodSeconds: 10 livenessProbe: tcpSocket: port: 8080 initialDelaySeconds: 30 periodSeconds: 20副本数这里重点说一下。用 SQLite 的话副本数必须是 1而且 Deployment 的更新策略最好设置成Recreate否则滚动更新时新旧两个 Pod 同时挂在同一个 PVC 上写 SQLite轻则报锁错误重则该写的记录丢了。想扩多副本就先把存储换成 MySQL。4. 核心配置拆解渠道、模板、路由4.1 通知渠道配置与几个容易填错的字段渠道配置基本都在 Web 界面的“配置”菜单里或者写在配置文件的对应段落。钉钉需要两个东西机器人的 webhook 地址以及安全设置里如果你选了“加签”还需要那个以SEC开头的密钥。这两个字段分开填只填 webhook 不填密钥钉钉会返回签名校验失败。企业微信只需要一个 key就是从 webhook 地址里key后面那串配置项叫不叫 token 各版本不一样看到的字段含义对了就行。飞书自定义机器人的地址比较长形如https://open.feishu.cn/open-apis/bot/v2/hook/xxxx整条填进去。渠道必填项常见错误验证方式钉钉webhook 地址 加签密钥只填地址漏密钥、IP 段未加白后台“测试”按钮发一条企业微信webhook 中的 key把整条 URL 填进了 key 字段群里看到测试消息飞书完整 webhook 地址地址被截断、签名校验未开群里看到测试消息邮件SMTP 地址、端口、账号、授权码用了登录密码而不是授权码收件箱收到测试信自定义 Webhook目标 URL、请求头对方要求特定 Content-Type对方服务日志里看到请求邮件这一项特别容易卡住。现在主流邮箱服务基本都要求用“授权码”而不是账号登录密码端口和加密方式也有讲究465 一般配 SSL587 一般配 STARTTLS。如果你填完一直报认证失败先别怀疑代码去邮箱后台把授权码重新生成一个再试。填完之后不要急着去改 Alertmanager先在 PrometheusAlert 的配置页点“测试”或者在首页找测试入口发一条。渠道本身通了再去接上游这样后面出问题就只剩一层链路要查。4.2 模板机制与常用变量速查模板是 PrometheusAlert 最值钱的部分也是最容易出问题的地方。它的模板语法是 Go templateAlertmanager 传过来的那批告警在模板里就是标准的结构化数据你可以遍历.Alerts可以取.Status、.CommonLabels、.CommonAnnotations、.ExternalURL、.GroupLabels每条告警里还有.Labels、.Annotations、.StartsAt、.EndsAt。一个我常用的、兼顾信息量和可读性的钉钉 markdown 模板大致长这样## {{ .CommonLabels.alertname }} ({{ .Status }}) **告警数量**{{ .Alerts | len }} **集群**{{ .CommonLabels.cluster }} **时间**{{ .CommonLabels.starts_at }} {{ range .Alerts }} --- **实例**{{ .Labels.instance }} **级别**{{ .Labels.severity }} **摘要**{{ .Annotations.summary }} **详情**{{ .Annotations.description }} {{ end }} [查看告警面板]({{ .ExternalURL }})这里面有几个关键取舍值得说。第一为什么不直接在模板里格式化时间因为不同渠道对时间字符串的容忍度不一样最稳的做法是在告警规则那边就把时间做成一个 label 带过来或者干脆不放时间让 Alertmanager 的StartsAt原样透传阅读时按需换算。第二为什么用CommonLabels而不是遍历每一条的 labels因为聚合后的告警往往共享同一组公共标签用公共标签做标题最简洁逐条信息放在循环里。第三ExternalURL这个字段非常有用它就是你 Alertmanager 的访问地址拼出来的链接能一键跳回复盘页面值班同学会感谢你这个细节。模板里还有一类“全局可用变量”比如告警条数这类统计值具体名字各版本可能有差异建议做法是先用一个最简模板只输出{{ . }}把渲染结果看一眼你就知道当前版本到底给了你哪些字段。这比翻文档快得多也是我接手任何模板引擎时的第一招。4.3 路由规则怎么用才不打架路由解决的问题是同一批告警A 业务的进 A 群B 业务的进 B 群。PrometheusAlert 的路由通常按告警里的某个标签做匹配app是最常用的那一维。你在 Prometheus 的告警规则里给每条告警打上app: order-service然后在路由配置里写“app 等于 order-service 的走订单群机器人”。路由配置有三个坑。第一个坑是顺序和优先级如果一个告警同时命中了两条规则会发生什么取决于实现的匹配逻辑是取第一条还是全部命中都发。我的做法是把路由设计成互斥的宁可多写几条精确规则也不要依赖“谁先谁后”这种隐含行为。第二个坑是缺省路由一定要配一个兜底规则否则某条新业务上线忘了配路由告警就静默地消失了——这种“没报错但也没发出去”的问题最难查。第三个坑是标签没打上路由匹配不到。上线新业务的时候先在 Alertmanager 里确认告警带上了目标标签再去配路由。路由配好之后有一个验证动作必须做手动构造一条带目标标签的告警走一遍完整链路确认它进了预期的群。我见过太多次“路由配置看着完全正确但就是不生效”最后发现是标签名大小写不一致或者标签根本就没在告警规则里定义。4.4 告警记录与数据留存告警记录的价值在事后。值班交接的时候翻一遍昨晚发了哪些告警比口头描述靠谱得多月底算告警数量、统计噪音比例也需要有数据。启用记录的方式就是配置里把记录开关打开再把存储指向你要用的后端。数据量这件事要有预期。假设每天 200 条告警、每条记录按 2KB 算一个月也就 12MB 左右SQLite 完全无压力。但如果你的环境告警很吵每天几千条一年下来就是好几个 GB这时候要么上 MySQL 并做定期归档要么在告警源头把噪音先治理掉——后者才是根本解法。提示无论用哪种存储都要把备份写成定时任务。SQLite 直接定期拷贝 db 文件即可拷贝前最好先停写或者用 SQLite 的备份命令避免拷到半截文件MySQL 用常规的 mysqldump。备份这件事平时没感觉等你要查三个月前那次故障的告警记录时就知道它的价值了。5. 对接上下游Alertmanager、Grafana 与主动推送5.1 Alertmanager webhook 对接的两种写法对接 Alertmanager 有两条路一条是让 Alertmanager 直接 POST 到 PrometheusAlert 的接收接口并在 URL 里带上渠道参数另一条是把渠道信息交给 PrometheusAlert 的路由去决定URL 里只带最少的参数。第一种写法最直观URL 里把类型、模板、机器人地址都写全receivers: - name: prometheusalert-dingtalk webhook_configs: - url: http://10.0.0.10:8080/prometheusalert?typeddtplprometheus-ddddurlhttps://oapi.dingtalk.com/robot/send?access_tokenxxx send_resolved: truetype指定渠道类型tpl指定用哪个模板send_resolved一定要设成true否则恢复通知不会发出来——这是个极高频的遗漏项很多人的“告警恢复了但群里没消息”就是因为它默认是false。第二种写法更适合多渠道场景URL 里不带机器人地址由 PrometheusAlert 的路由根据标签决定投递目标。好处是机器人地址变了只改 PrometheusAlert 一处Alertmanager 完全不用动而且天然支持“同一批告警投多个群”。receivers: - name: prometheusalert-router webhook_configs: - url: http://10.0.0.10:8080/prometheusalert?typeddtplprometheus-dd send_resolved: true改完 Alertmanager 配置记得 reload然后去 Alertmanager 的界面看 Status 页确认 receiver 配置已经被正确加载。这一步不做你会对着旧配置查半天。5.2 Grafana 与自研系统的接入Grafana 的告警通知渠道里也能配 webhook把它指向 PrometheusAlert 对应的接收路径即可。这里的关键是模板要换一套因为 Grafana 推过来的 JSON 结构和 Alertmanager 不一样字段名、嵌套层级都不同。我的建议是给 Grafana 单独建一个模板名字上带grafana-前缀别试图用一套模板同时吃两种数据源那样只会让模板变得又长又脆。自研系统接入的思路一样。发布系统上线完成后想发条通知、巡检脚本发现异常想推一条、批处理任务失败想告警都只需要 POST 到 PrometheusAlert。这样做最直接的好处是把 token 集中到了一处以后机器人换了、密钥轮转了改 PrometheusAlert 的配置就行散落在各处的脚本一个都不用动。5.3 API 主动推送与自定义 Webhook主动推送的写法就是一条 curl把要渲染的字段当成 JSON 传进去模板里用对应的变量取。比如你要发一条纯文本到飞书curl -X POST http://10.0.0.10:8080/prometheusalert?typefstpl自定义模板名 \ -H Content-Type: application/json \ -d {msg:订单服务发布完成版本 v1.8.3,env:prod}模板里就能用相应的变量把msg和env渲染出来。这套机制特别适合做发布通知和巡检报告模板固定字段由调用方填展示风格统一。自定义 Webhook 这个渠道也值得说一句它的价值在于“把 PrometheusAlert 当成一个格式转换器”。有些内部系统只认特定格式的 JSON你没有必要去改 PrometheusAlert 的代码写一个自定义 Webhook把目标地址、请求头、请求体模板配好让它做一次格式转换再转发出去就行。我见过有人用它对接内部的工单系统告警一来自动建单效果出乎意料地好。6. 实战避坑与排查手册6.1 告警不来的逐段排查表排查这类问题的核心方法只有一个把链路切成段从后往前推每段单独验证。先确认渠道本身通不通再确认 PrometheusAlert 收没收到再确认 Alertmanager 发没发出去最后看 Prometheus 有没有真的触发告警。现象优先排查位置常见原因处理方式测试都发不出去PrometheusAlert 配置token 填错、加签密钥缺失重新复制 webhook 与密钥测试能发真实告警不来Alertmanagerreceiver 未 reload、URL 写错看 Status 页确认配置已加载Alertmanager 报发送失败网络与代理层反向代理体积限制、防火墙放开 body 大小与出站策略消息发出但内容空白模板变量名写错、字段不存在用输出整个上下文的最简模板定位恢复了但没通知Alertmanagersend_resolved为 false改成 true 并 reload历史里没有记录存储记录开关未开、目录未挂载检查配置与挂载路径、确认可写从后往前推还有个小技巧让 PrometheusAlert 的日志级别先调到 debug观察它接收到请求时打印的原始内容。很多时候你在 Alertmanager 侧纠结半天日志里一眼就能看出“根本没收到任何请求”方向立刻就明确了。6.2 模板渲染与消息截断的坑模板相关的故障有两类一类是渲染出来一片空白一类是消息发出去被截断。空白的原因八成是变量名对不上——你写.Labels.instance但告警里根本没有instance这个标签Go template 对不存在的字段不会报错只会输出空。定位方法就是前面说的先用最简模板把整个上下文吐出来看一遍。截断的原因基本是渠道的长度限制。企业微信 markdown 消息的上限明显比钉钉紧一批告警几十条的时候非常容易超。这个问题有三种解法我按推荐程度排第一在 Alertmanager 那边把group_by调细让每批告警的条数变少从源头控制消息长度第二在模板里做截断只展示前 N 条剩下的用一句“另有 X 条告警请点击链接查看”带过第三把详情交给一个跳转页面消息里只放摘要。注意消息里如果有特殊字符比如 markdown 语法里的星号、下划线、方括号可能导致渲染异常。项目名、实例名里带这些字符的场景不少稳妥的做法是在模板里适当转义或者干脆把这类字段放在代码块样式里输出。6.3 告警风暴、限流与聚合的分工每个 IM 机器人都有频率限制量级大概在每分钟几十条这个范围一旦超了就会返回限流错误表现是“部分告警发出去了、部分没发”。这也是很多人第一次遇到“告警丢失”的原因。治理这个问题的根子在源头。第一层是 Prometheus 告警规则的阈值要合理别让一个磁盘使用率波动就来回触发第二层是 Alertmanager 的聚合参数group_wait太短会导致同一类告警重复发repeat_interval太短会导致长时间未恢复的告警反复提醒第三层才是 PrometheusAlert 的路由和模板把同类告警合并成一条更长的消息而不是多条短消息。我的经验是一套健康的告警系统里普罗米修斯的规则治理占七成功劳Alertmanager 的参数调优占两成剩下的才是通知工具的部分。指望靠通知工具去解决告警风暴方向从一开始就错了。6.4 升级、备份与多副本升级前必须备份两样东西配置文件和数据库。配置文件里躺着所有渠道的 token 和路由规则数据库里躺着历史记录。升级的动作就是换镜像 tag 或者换二进制文件重启然后立刻做三件事登录看首页有没有异常、发一条测试消息、翻一下告警记录能不能正常写入。这三步做完升级才算真的完成。多副本这件事再强调一次SQLite 不支持别硬上。要副本就先换 MySQL换完之后所有副本指向同一个库前面用负载均衡把上游请求分过来。但说句实话PrometheusAlert 本身负载很轻绝大多数场景单实例完全够用把精力花在“数据库定时备份”和“配置版本化”上收益比折腾多副本大得多。配置版本化是个我强烈推荐的习惯把配置文件和 Compose 文件一起放到代码仓库里token 用环境变量注入每次改路由、改模板都留一次提交记录。这样某天有人问“上周三那条告警为什么发到测试群了”你能直接翻出当时的配置。我在吃过一次“谁把路由改了导致生产告警进了测试群”的亏之后就再也没让配置脱离版本管理。最后分享一个我一直在用的小习惯给 PrometheusAlert 单独建一个“通知测试群”所有新配的模板、新加的渠道、新写的路由都先在这个群里跑一遍。看着一条渲染完整的消息真的出现了再去动生产配置。这个习惯看着笨但它把“改配置”这件事从一次需要屏住呼吸的操作变成了一件随手就能做的小事。