alertmanager 不能直接对接钉钉或飞书,因其 webhook_configs 要求接收端兼容原生 json 格式,而钉钉/飞书 api 需特定消息结构、签名及认证;必须通过 golang webhook 服务完成协议转换、路由决策与安全加固。

Alertmanager 本身不直接对接钉钉或飞书,它只负责路由、分组和去重;真正完成「翻译+发送」的是你用 Golang 写的 Webhook 服务。所以别在 alertmanager.yml 里硬塞钉钉 URL——那只会 404 或超时失败。
为什么不能直接配钉钉/飞书 URL 到 webhook_configs
Alertmanager 的 webhook_configs 是通用 HTTP POST 接口,但它要求接收端能处理 Alertmanager 原生 JSON 格式(含 alerts 数组、groupLabels、commonAnnotations 等字段)。钉钉/飞书机器人 API 完全不认这个结构,直接 POST 过去会返回 400 Bad Request 或 invalid signature。
- 钉钉要求
msgtype+text.content或card结构,且需带timestamp+sign(如果启用了加签) - 飞书要求
msg_type+content对象,且部分字段如chat_id或user_id需提前查或配置 - Alertmanager 发来的原始 payload 没有这些字段,也不做签名计算
Golang Webhook 服务必须实现的核心逻辑
你的 Go 服务不是简单转发,而是要承担「协议转换 + 路由决策 + 安全加固」三件事。关键点如下:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 接收
/alert(或任意路径)的 POST 请求,Content-Type: application/json,用json.Unmarshal解析成AlertmanagerPayload结构体(注意字段嵌套层级) - 从
alerts[0].labels.severity或alerts[0].labels.team提取路由依据,决定发钉钉还是飞书(比如severity == "critical"→ 飞书值班群,team == "infra"→ 钉钉运维群) - 对每条告警生成独立消息体:钉钉用
text或markdown,飞书用post类型并拼content.elements;模板里必须包含alertname、startsAt、generatorURL等关键信息 - 调用钉钉前,若配置了
secret,得按文档算HMAC-SHA256签名;飞书若用bot_token,需在 Header 加Authorization: Bearer xxx - HTTP Client 必须设
Timeout: 10s,避免 Alertmanager 因等待卡住(默认timeout: 10s)
Alertmanager 配置中 route 和 receiver 的写法陷阱
很多人把 receiver 名字写成 dingtalk 就以为万事大吉,其实 Alertmanager 不关心你叫什么,只认 webhook_configs.url 是否可达。常见错误:
-
url: "http://localhost:8080/alert"→ 本地地址在容器里跑不通,得用宿主机 IP 或 service name(如http://go-webhook:8080/alert) -
group_by: ["alertname", "severity"]→ 分组太细导致每条告警都单独发,失去聚合意义;建议至少保留instance或job - 漏配
send_resolved: true→ 恢复通知不会触发,你的 Go 服务收不到status: "resolved"的 payload - 没设
repeat_interval→ 同一告警反复刷屏,Go 服务得自己做防抖(比如内存缓存 lastSentTime),否则钉钉/飞书限流封 IP
生产环境必须加的防护层
上线前这三件事不做,告警可能发不出或被限流:
- 钉钉机器人开启「自定义关键词」后,你的 Go 消息体
text.content必须包含该关键词(如"[ALERT]"),否则消息静默丢弃 - 飞书机器人若配置了
app_id+app_secret,Go 服务得先调/open-apis/auth/v3/token换tenant_access_token,再用它发消息;不能直接拿 bot_token 当万能钥匙 - 所有 HTTP 调用必须包一层
retry.Retry(比如用github.com/hashicorp/go-retryablehttp),网络抖动时重试 2 次,避免单次失败就丢告警
最易被忽略的是签名时间戳:钉钉要求 timestamp 是毫秒级且与服务器时间误差 timestamp 是秒级;Golang 里别直接用 time.Now().Unix(),得确认时区和精度是否匹配 API 要求。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










