Prometheus 告警怎么推到钉钉?从单群通知到跨网络 Alertmanager 实战
前言
监控系统真正有价值的时刻,不是图表看起来多完整,而是异常发生以后,负责的人能不能及时收到一条足够清楚、能够继续处理的告警。Prometheus 负责发现问题,Alertmanager 负责分组、路由和通知,但钉钉并不是它直接支持的通知目标,所以中间还需要一层 prometheus-webhook-dingtalk。我比较在意这种链路能不能一段一段验证,而不是一上来就把"生产可用、高可靠"写在标题里。告警系统最怕的不是配置多,而是链路长:任何一环没通,最后表现出来都只是"群里没消息",所以越是这种跨组件集成,越应该先把每层职责拆开。我也不希望因为最终能收到一条消息,就默认中间所有环节都稳定可靠;只有逐层看清输入和输出,真正出问题时才知道应该从哪一段开始查。
这次的实操从 Prometheus 关联 Alertmanager 开始,先创建钉钉自定义机器人,再用 Docker 启动 prometheus-webhook-dingtalk,把 Alertmanager 的 Webhook 指向 8060 服务,并实际看到钉钉收到告警;随后继续扩展到两个钉钉群。最后再处理一个更容易被忽略的场景:Prometheus 和 Alertmanager 不在同一个局域网时,用 cpolar 把 Alertmanager 的 9093 端口提供成 TCP 公网入口,再让另一侧 Prometheus 指向这个地址。整篇只围绕一件事展开:告警从 Prometheus 出发,经过 Alertmanager 和 Webhook 中转,最后真正到达钉钉。

1. 先把整条告警链看清楚
这套方案里,各组件的职责并不复杂:
Prometheus → Alertmanager → prometheus-webhook-dingtalk → 钉钉机器人
其中:
- Prometheus 负责采集指标,并根据规则触发告警;
- Alertmanager 负责告警分组、路由、重复通知和恢复通知;
prometheus-webhook-dingtalk负责把 Alertmanager 的 Webhook 消息转换为钉钉能够接收的请求;- 钉钉机器人负责把消息送进指定群聊。
我更愿意先把这四层分开理解,因为出了问题以后,排查顺序会清楚很多:是 Prometheus 没触发、Alertmanager 没收到、Webhook 服务没转发,还是钉钉机器人拒绝了消息。
2. 部署前先确认基础条件
当前流程要求:
- 本机已经部署 Prometheus 和 Alertmanager;
- 有一个可用的钉钉群,并具备管理员权限;
- 可以创建钉钉自定义机器人;
- Webhook 部署节点具备外网访问能力;
- Alertmanager 与
prometheus-webhook-dingtalk网络互通; - 准备 Docker 或 systemd,以及
curl、jq、vim/nano等调试和编辑工具。
如果 Alertmanager 和 Webhook 服务在同一主机,还要留意 Docker 网络隔离。当前说明建议不要直接假定 127.0.0.1 一定可用,而是根据部署方式选择宿主机 IP 或 Docker 自定义网络。
先确认 Docker:
shell
docker --version
3. 让 Prometheus 知道 Alertmanager 在哪里
进入 Prometheus 配置文件,按当前页面配置 Alertmanager。

修改后执行:
shell
systemctl restart prometheus
这一步的目标很明确:Prometheus 触发告警以后,要能把告警送到 Alertmanager。
后面的钉钉配置都建立在这条链已经可用的基础上。
4. 创建钉钉自定义机器人
打开钉钉群,进入右上角设置。

找到智能群助手并添加机器人。


选择自定义机器人。

点击添加。

当前示例给机器人的名称是:
prometheus告警

接下来设置机器人安全策略。
当前操作使用了关键词,同时页面也提供加签或 IP 地址等安全方式。

完成以后复制生成的 Webhook URL。

这个地址后面要写进 prometheus-webhook-dingtalk 配置,因此不要把它当作普通公开链接传播。
5. 部署 prometheus-webhook-dingtalk
先创建:
dingtalk.yaml
当前单群配置如下:
shell
cat > dingtalk.yaml <<EOF
targets:
webhook1:
url: https://oapi.dingtalk.com/robot/send?access_token=你的_access_token
EOF
这里的 webhook1 是后面 Alertmanager URL 中会使用到的目标名称。
然后启动 Docker 容器:
shell
docker run -d \
--name dingtalk-webhook \
-p 8060:8060 \
-v $(pwd)/dingtalk.yaml:/etc/prometheus-webhook-dingtalk/config.yml \
--restart always \
timonwong/prometheus-webhook-dingtalk:latest

当前服务监听:
8060
端口。
到这里,链路中间多了一层:
Alertmanager → 8060 → prometheus-webhook-dingtalk → 钉钉 Webhook
6. 配置 Alertmanager,把告警交给钉钉中转服务
打开 Alertmanager 配置:
shell
vi alertmanager.yml
当前配置如下:
shell
global:
resolve_timeout: 2m
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'dingtalk-webhook'
receivers:
- name: 'dingtalk-webhook'
webhook_configs:
- url: 'http://<你的服务器IP> :8060/dingtalk/webhook1/send'
send_resolved: true
这里几个参数值得单独看:
group_by: ['alertname']group_wait: 10sgroup_interval: 10srepeat_interval: 1h- receiver:
dingtalk-webhook send_resolved: true
其中 send_resolved: true 表示恢复状态也会继续通过当前通知链发送。
配置完成后执行:
shell
systemctl restart alertmanager
当前 URL 代码块中写的是:
http://<你的服务器IP> :8060/dingtalk/webhook1/send
其中 <你的服务器IP> 需要换成实际运行 Webhook 服务的主机地址;当前记录里 IP 与 :8060 之间还保留了一个空格,复现时要结合自己的实际配置确认请求地址。

随后已经能看到钉钉告警。

这一步真正验证的是:
Prometheus → Alertmanager → prometheus-webhook-dingtalk → 单个钉钉群
已经连通。
7. 多个钉钉群怎么处理?
如果运维、开发或安全团队需要分别接收告警,可以继续配置多个钉钉目标。
先编辑:
shell
vi dingtalk.yaml
当前多目标结构如下。
这里的 Webhook token 和 secret 属于敏感凭据,改写文件中只保留配置结构,具体值使用占位符。
shell
targets:
ops-team:
url: https://oapi.dingtalk.com/robot/send?access_token=<your_access_token>
secret: <your_secret>
dev-team:
url: https://oapi.dingtalk.com/robot/send?access_token=<your_access_token>
secret: <your_secret>
然后重新启动 Webhook 容器:
shell
docker run -d \
--name dingtalk-webhook \
-p 8060:8060 \
-v $(pwd)/dingtalk.yaml:/etc/prometheus-webhook-dingtalk/config.yml \
--restart always \
timonwong/prometheus-webhook-dingtalk:latest

接着编辑 Alertmanager:
shell
vi alertmanager.yml
当前配置通过一个 broadcast receiver 同时写入两个 Webhook 地址:
shell
global:
resolve_timeout: 2m
# 主路由:所有告警走这个路径
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'broadcast' # ← 指向一个组合 receiver
# 定义 receivers
receivers:
- name: 'broadcast'
webhook_configs:
# 发给 ops 钉钉群
- url: 'http://<你的服务器IP>/dingtalk/ops-team/send'
send_resolved: true
# 发给 dev 钉钉群
- url: 'http://<你的服务器IP>/dingtalk/dev-team/send'
send_resolved: true

这里要留意一个现有配置差异:Webhooks 服务前面映射的是 8060:8060,但这两个多群 URL 当前没有写 :8060。这里保持现有配置不改,复现时需要根据自己的网络和监听方式确认实际可达地址。
配置后执行:
shell
systemctl restart alertmanager

等待告警触发后,当前测试里两个群都收到了消息。

这一步验证的是同一份 Alertmanager 告警可以同时送到两个钉钉目标。
8. Prometheus 和 Alertmanager 不在一个局域网怎么办?
前面的链路默认各组件之间能够直接访问。
但如果 Prometheus 在一个内网,Alertmanager 在另一台隔离主机或另一个网络,Prometheus 就可能无法直接连接 Alertmanager 的 9093。
这时需要解决的不是钉钉机器人,而是:
Prometheus → Alertmanager
这一段网络链路。
这里使用 cpolar 的作用很明确:
把 Alertmanager 的
9093TCP 服务提供成另一侧 Prometheus 可以到达的公网入口。
它不参与告警分组,也不负责向钉钉发送消息。
9. 安装 cpolar
执行:
shell
sudo curl https://get.cpolar.sh | sh

安装完成后检查服务状态:
shell
sudo systemctl status cpolar

服务正常以后,通过主机 IP + 9200 进入 cpolar Web 管理页面。
当前页面同时出现:
http://ip:9200
和链接目标:
http://localhost:9200/
实际使用时,以当前环境真正可以打开的地址为准。

10. 先为 Alertmanager 创建随机 TCP 入口
创建隧道时,当前设置为:
- 隧道名称:
alertmanager - 协议:
tcp - 本地地址:
9093 - 端口类型:随机临时 TCP 端口
- 地区:
China Top

创建完成以后,当前生成的公网地址是:
- 域名:
2.tcp.cpolar.top - 端口:
10409

因此远端 Prometheus 需要连接的是:
2.tcp.cpolar.top:10409
11. 把远端 Prometheus 指向这个公网 Alertmanager 地址
在 Prometheus 主机上编辑:
shell
vi prometheus.yml
当前配置为:
shell
alerting:
alertmanagers:
- static_configs:
- targets: ["2.tcp.cpolar.top:10409"]

也就是说,Prometheus 的 Alertmanager 目标从原来的局域网地址换成:
2.tcp.cpolar.top:10409
当前操作记录在修改 prometheus.yml 后执行的是:
shell
systemctl restart alertmanager
这里保持当前步骤不变。实际复现时,应根据自己的服务管理方式确认新配置是否已经被对应进程加载。
当前测试中,重启之后钉钉仍然继续收到告警。

这说明在当前环境里:
Prometheus → cpolar TCP → Alertmanager 9093 → Webhook → 钉钉
这条跨网络链路能够继续工作。
12. 长期使用再保留固定 TCP 地址
随机 TCP 适合先验证,但如果 Prometheus 配置文件长期指向这个目标,固定地址会更方便。
进入 TCP 地址预留页面。

当前页面存在一个地区显示差异:
-
下拉菜单选择:
China VIP -
已保留记录显示:
China Top -
固定地址:
3.tcp.cpolar.top:11755
然后回到 cpolar 隧道列表。
当前文字说明里写的是找到:
ssh
隧道,但前面实际创建的隧道名称是:
alertmanager
复现时应以列表中实际指向 9093 的那条隧道为准。

把端口类型改成固定 TCP,并填写已经保留的 TCP 地址。

更新以后,在线隧道列表会显示固定 TCP 地址。

到这里,Alertmanager 的公网入口就不再依赖随机 TCP 端口。
总结
这套配置最值得保留的,不是"Prometheus 告警终于能发钉钉"这一句话,而是把整条链拆开以后,每一段都能独立验证。
实际跑通的核心路径是:
Prometheus → Alertmanager → prometheus-webhook-dingtalk:8060 → 钉钉机器人 → 单群告警 → 双群告警 → cpolar → Alertmanager 9093 → 2.tcp.cpolar.top:10409 → 固定 TCP 3.tcp.cpolar.top:11755。
如果以后告警没有到钉钉,我会按这个顺序查:先看 Prometheus 有没有触发,再看 Alertmanager 有没有收到,再看 Webhook 服务是否可达,最后才看钉钉机器人安全策略。跨网络场景再额外检查 9093 公网入口。这样比把"告警系统有问题"当成一个整体去猜,要省事得多。