alertmanager模板路径须为绝对路径且文件真实存在、权限644;.alerts.sorted才按触发时间排序;.commonlabels仅含group_by字段及完全一致的非group_by标签;go服务需http调用api而非sdk。

Alertmanager配置中template_files路径必须绝对且可读
Alertmanager启动时若报错 failed to parse template: open /etc/alertmanager/template.tmpl: no such file or directory,大概率是 template_files 路径写相对路径或挂载权限不对。它不支持类似 ./templates/*.tmpl 这种写法,也不识别容器内软链接指向的路径。
- 路径必须为绝对路径,例如
/etc/alertmanager/templates/default.tmpl - 文件需在 Alertmanager 容器内真实存在,推荐用 ConfigMap 挂载,而非 volumeMount + hostPath(易因节点路径不一致失效)
- 挂载后执行
ls -l /etc/alertmanager/templates/确认文件权限为 644,属主属组不限,但不能是 root-only 可读(某些精简镜像会 drop 权限) - 若用 Helm 部署
kube-prometheus-stack,模板文件默认挂载在/etc/alertmanager/config.d/,此时template_files应设为["/etc/alertmanager/config.d/*.tmpl"]
Go模板里.Alerts和.Alerts.Sorted行为差异明显
在 alertmanager-alert-template.tmpl 中,直接遍历 .Alerts 是无序的;而 .Alerts.Sorted 才按触发时间升序排列——这点极易被忽略,导致通知里告警顺序混乱,尤其当一次推送含多个告警时,最新触发的可能排在最后。
- 正确写法:
{{ range .Alerts.Sorted }},不是{{ range .Alerts }} -
.Alerts是原始 map 结构,Go template 对 map 迭代顺序不保证;.Sorted是 Alertmanager 内部封装的 slice,已排序 - 若需倒序(如把最新告警放最前),得自己 reverse:先
{{ $alerts := .Alerts.Sorted }},再用{{ range $i, $a := $alerts | reverse }}(需引入text/template的reverse函数,或改用自定义 funcmap) - 别在模板里调
len .Alerts判断数量——它返回的是 map 长度,但.Alerts.Sorted才是实际推送的告警列表,二者值相等,但语义不同
Go模板中.CommonLabels不包含所有告警共有的label
很多人误以为 .CommonLabels 是所有告警 label 的交集,结果发现 namespace 或 job 没出现,其实是 Alertmanager 分组逻辑决定的:只有在当前分组(group_by)维度上完全一致的 label 才进 .CommonLabels。
- 例如 group_by 设置为
["alertname", "severity"],那即使 5 个告警都来自defaultnamespace,namespace也不会出现在.CommonLabels中 - 真正共有的 label 是那些被选入
group_by的字段,以及所有告警都带、且值完全相同的非 group_by label(极少) - 想稳定取 namespace?用
{{ with .Alerts.Sorted.First }}{{ .Labels.namespace }}{{ end }}更可靠,前提是确保该分组内所有告警确实有此 label - 更健壮的做法是模板里加判空:
{{ if .Labels.namespace }}Namespace: {{ .Labels.namespace }}{{ else }}N/A{{ end }}
Go服务发送告警通知时别直接调用alertmanager.Send()
Alertmanager 本身不提供 SDK,所谓 alertmanager.Send() 是社区封装的假想函数。真实场景下,Go 服务要发告警,只能走 HTTP POST 到 Alertmanager API,且必须构造符合其 v2 API 规范的 JSON payload。
- 目标 endpoint 是
http://alertmanager.monitoring.svc.cluster.local:9093/api/v2/alerts(集群内)或外网暴露地址 - body 必须是 alert 数组,每个 alert 至少含
labels(map[string]string)和annotations(map[string]string),startsAt建议填 RFC3339 格式时间 - 别漏掉
Content-Type: application/jsonheader,否则 Alertmanager 返回 400 - 生产环境务必加重试(指数退避)和超时控制,Alertmanager API 不保证幂等,重复发相同 alert 会触发多次通知











