Alertmanager
pg addon install alertmanager 以受管容器方式运行 Alertmanager——位于 Prometheus 下游的告警去重、分组、路由与通知层——直接跑官方 docker.io/prom/alertmanager 镜像。与 Prometheus、Grafana 一样,它是顶层插件:不前置某个具体实例,也不依附于任何一个。Prometheus 与 Alertmanager 是天然一对——Prometheus 触发告警,Alertmanager 决定通知谁、怎么通知——而本插件在形状上是 Prometheus 的近乎完全同构体(单容器、Linux 上宿主网络、各自端口池里的一个 web 端口、持久数据目录、开机自启、日志、渲染配置文件 + 镜像名之后的 CLI flag、SIGHUP 热加载、无 Web 登录)。
衔接的工作在 Prometheus 那一侧。
pg addon install alertmanager不碰任何prometheus.yml——也不需要碰:由 Prometheus 自己指向本实例,命令是pg addon install prometheus --alertmanager-url <本实例的 host:port>,它会注入alerting:段(外加一个抓取本实例/metrics的 job)。若 Prometheus 用的是自己的 配置文件(--conf-file),就自己在里面写alerting:段。两种方式只要指过来了,告警 就会流进来。
没有 Web 登录/密码——而且比 Prometheus 的赌注更大。 Alertmanager 完全不 带鉴权,且它的无鉴权 API 的可写性比 Prometheus 那个以读为主的 API 更危险:任何能 连到端口的人都能创建 silence——即悄悄压掉 oncall 期待的每一条通知,且不会在 Prometheus 自己的指标里留下任何痕迹。它的
0.0.0.0默认因此只靠网络边界保护, 而这条边界在这里比插件家族里任何其他地方都更重要。请把它当作把一套告警体系的静音 开关交出去来对待,而非一个有密码保护的面板。
平台:Linux 是已实测的平台。设计上也支持 macOS(镜像多架构;容器在
pgcli-netbridge 上以发布端口的方式跑在 podman machine 里),但尚未在 Mac 上验证 过。
参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--name |
alertmanager |
实例名(map 键) |
--image |
docker.io/prom/alertmanager:v0.34.1 |
覆盖镜像 |
--port |
自动(基址 9093) | Web 宿主端口;自 alertmanager_start_port 自动分配 |
--listen |
0.0.0.0 |
绑定地址——默认开放全部网卡;127.0.0.1 收紧为仅回环(见上方暴露警告) |
--webhook-url |
— | 要通知的 webhook URL(可重复)。每个 URL 都被渲染成同一个 web.hook receiver 下的一条 webhook_configs——多个 URL 会扇出通知到每一个。写入任何东西之前先用 net/url 校验(可解析、http/https、Host 非空);格式错误的 URL 会让 install 直接中止,不留任何痕迹。不探测连通性(见下)。与 --conf-file 互斥 |
--conf-file |
— | 你自己的 alertmanager.yml 路径——完全跳过渲染(与 --webhook-url 互斥);见下 |
--data-dir |
自动 | 覆盖数据目录(默认在 base 目录下) |
--force |
false | 即使正在运行也重建——用于不热加载改动的配置,或应用改动的端口/监听 |
数据目录承载 Alertmanager 的状态:silence 与通知状态。它跨 pg addon remove 存活
(用 --clean-data 才删除),重装同名实例即复活它们。镜像以固化的 nobody(uid/gid
65534)运行且不自建可写目录,所以 pgcli 在创建容器前先在宿主上把数据目录 chown 过
去:rootless podman 下经 podman unshare chown 65534:65534,rootful 宿主且 pgcli 以
root 运行时直接递归 chown(与 Prometheus、Grafana 完全同构,只是 id 不同)。
--webhook-url 不做连通性探测,这是刻意为之:不像 Prometheus 的抓取(GET /metrics,install 时即可达并可应答),webhook 只在告警真正路由过去时才发的 POST
——install 时拨它一下也告诉不了你什么可靠信息。唯一的提前闸门是 URL 的形状;端点
是否存在、是否可达、能否接受这个 payload,只能在告警实际触发时才知道(通知没到就查
pg logs addon alertmanager)。
安装
命令会按需拉取镜像、渲染一份 alertmanager.yml、创建容器,并打印 URL、配置路径以及
路由渲染成什么:
没有 --webhook-url 时,渲染的配置是一条指向仅有名字、no-op receiver 的单路由:一
份合法、功能完整的配置——Web UI 与 API 在线、silence 可用、HA 集群端口已禁用——只是
什么都不发。这是"先把端点拉起来,路由之后再定"的默认形态。要真正发出通知,加一个
webhook:
对运行中的实例重复 install:当渲染/拷贝的配置确实变了时热加载(SIGHUP),没变
则原样不动;--force 则重建容器——用于应用改动的 --port / --listen(它们是容器参
数,而非配置文件内容)。
带不同的 --webhook-url 集合重复 install 会整体替换已存列表(一个都不传则清空回
no-op);正是这个 diff 决定要不要 reload。
自定义配置文件(--conf-file)
把你自己的 alertmanager.yml 交给 pgcli,它就完全跳过渲染:
pgcli 把你的文件拷贝进托管路径(<base>/addon/alertmanager/<name>/alertmanager.yml),
并只读挂载这份拷贝——绝不挂你的原文件。这是刻意为之:单文件 bind mount 锁死源
inode,原地改你的原文件不会传播进运行中的容器。正因它是拷贝,改完你的原文件后跑
pg addon alertmanager reload 会重拷并通知 Alertmanager 重读。pgcli 不校验、不改写文
件内容(与 nginx/haproxy/prometheus 的 --conf-file 同一约定)。--conf-file 与
--webhook-url(塑造渲染文件的那个 flag)互斥——真正的路由树(email/Slack/PagerDuty、
子路由、inhibition)活在你自己的文件里。重装时省略 --conf-file 即回到渲染模式。
这份文件就是普通的 Alertmanager YAML——pgcli 不往里加东西,除了"能解析"之外对它也没 任何要求。下面是一份完整示例,含子路由树、inhibition,以及三种不同类型的 receiver:
pgcli 本身不校验这份文件(install 阶段没有 amtool check-config 闸门——见已知限
制),但镜像自带 amtool,所以你可以在信任一次 reload 之前,进正在运行的容器里检查
托管的那份拷贝(容器名以 pg addon list 打印的为准,带命名空间前缀——上面那段实录里
是 pgcli-alertmanager-default-am1):
热加载(配置热更新)
它重写托管的 alertmanager.yml(渲染模式重渲、--conf-file 模式重拷你的文件),并向
运行中的容器发 SIGHUP,让 Alertmanager 原地重读——不重建容器、不中断通知。
与 Prometheus 不同,Alertmanager 的 POST /-/reload 端点是存在的,且无法关闭(没
有类似 --web.enable-lifecycle 的开关)。pgcli 仍然用 SIGHUP 重载——不是因为那条路由
被关掉了,而是为了永远不需要依赖一条按镜像设计就一直敞开的无鉴权 HTTP 端点。任何能打
到端口的人本就能直接打这条路由;pgcli 只是不往这个面上再加东西。若你 reload 一份被拒
绝的手写 --conf-file,Alertmanager 会沿用上一份好配置并打日志,所以之后请查
pg logs addon alertmanager。实例须已在运行(pg addon start alertmanager)。
监听与暴露
Alertmanager 的 Listen 默认 0.0.0.0:容器共享宿主网络命名空间,所以 UI 与 API 在
宿主每个网卡的分配端口上可达。背后没有密码,而且——与 Prometheus 不同——这个 API
允许调用方创建 SILENCE,即压掉 oncall 期待的每一条通知,还能重载自身配置。仅回环
部署才是安全的默认:传 --listen 127.0.0.1(用 --force 重建);pg addon list 会
显示 http://127.0.0.1:<port>/。否则请在防火墙层面限制访问,并把敞开的 0.0.0.0 当
作一个可被触达的静音开关来对待。
端口
每个 Alertmanager 实例占有一个端口:Web UI/API。它取自以 alertmanager_start_port
(默认 9093——Alertmanager 惯例端口)为基址的端口池,每多一个实例递增,并跳过任何
已被受管容器或 used_ports 列表占用的端口。分配结果写入 pg.yaml,所以重装绝不会把
别的插件在用的端口再发一遍。9093 与 Grafana(3000)、pgAdmin(5050)、
Prometheus(9090)、nginx(8080)都不重号;显式 --port 仍优先。
9094——HA gossip 端口——永不被开启,因为它被一个 flag 关掉了。 Alertmanager 的高可用集群默认在 TCP+UDP
9094上监听,且对一个单实例而言会不停尝 试引导永远不会到来的 peer。pgcli 传--cluster.listen-address=(空串)彻底关掉它 ——这是单实例约定,每次创建都强制执行,于是集群端口永远不开、也没有 UDP 监听器残 留。(这只关乎9094的集群用途;这个数字并未被预留,所以 web 端口池照样可以 把9094作为第二个实例的 web 端口分配出去——见下面的示例。)把多个 pgcli 托管的 Alertmanager 集群成一个 gossip 组并未接通(见已知限制)。
配置
渲染的 alertmanager.yml 承载一个 global.resolve_timeout、一条根路由
(group_by: ['alertname'],默认 group_wait/interval/repeat_interval)指向单个
receiver,以及这个 receiver 的 webhook_configs——web.hook 下一个 webhook URL 一
条,列表为空时则是仅有名字的 no-op receiver。监听绑定、存储路径、被禁用的集群地址
不在那个文件里——它们作为 CLI flag 传给 alertmanager 二进制
(--web.listen-address、--storage.path、--cluster.listen-address=),这正是
--listen 能与 --conf-file 并存的原因。
列出
没有凭据可揭示——Alertmanager 本就没有——所以 --show-password 对它不会多显示任何东
西,pg addon password alertmanager 也解析不出任何东西。
启停
容器以 podman 的 unless-stopped 重启策略运行,宿主重启后随 podman 服务自动回来。
start/stop 显式管理它们:
开机自启
要让 Alertmanager 实例在宿主开机时自动启动,开启它:
这会在 pg.yaml 里给实例打标记,并安装/刷新一个开机服务(Linux 上是 systemd --user
unit,macOS 上是 LaunchAgent)来执行 pg start --autostart。开机启动只负责把容器拉起
来——读磁盘上已存在的托管 alertmanager.yml,且数据目录在创建时已 chown 过,除 podman
本身外不需要任何宿主特权。启动顺序上 Alertmanager 排在 Prometheus 之后、nginx 之前——
是上面那个采集器天然的搭档,衔接也恰好在采集器那一侧完成(pg addon install prometheus --alertmanager-url …)。完整机制、状态与关闭方式见 开机
自启。
移除
rootless podman 下,--clean-data 经 podman unshare rm 删除数据目录——Alertmanager
以容器内 uid(65534)写文件,它映射到宿主的 subordinate uid,宿主用户无法直接 rm。
--conf-file 模式只删 pgcli 的拷贝;你的原文件在何处都不被触碰。
日志
排障
install失败于 “chowning Alertmanager data dir … to 65534:65534” —— 镜像以nobody(uid/gid 65534)运行且从不自己修复属主,所以 pgcli 在创建容器前先把宿主数 据目录 chown 过去:rootless podman 下经podman unshare chown(映射后的 subordinate uid 才是正确目标),rootful 宿主且 pgcli 自身以 root 运行时直接递归chown。pgcli 是直接调用podmanCLI,所以只在这两种情形之外才会失败——例如非 root 的pg被显式指向别人的 rootful daemon。遇到时以 root 跑 install,或改用 rootless podman;单纯sudo chown -R 65534:65534 <data-dir>不能消除该错误,因为每 次 install 都会重新校验属主。- 收不到任何通知 —— 最常见的原因是
no-opreceiver:一次不带--webhook-url的 install 渲染的配置永远什么都不发。查pg addon list里的Config:行(它写的是no-op receiver还是rendered (N webhook))。若确实配了真实 webhook,它在 install 时不做连通性探测——可达性只有告警真正触发时才知道,所以要查pg logs addon alertmanager里的 POST 失败,并确认端点能接受 Alertmanager 的 webhook payload。 --webhook-url中止于解析错误 —— 这是设计行为:每个 URL 都在 pg.yaml 或任何文 件被写入之前完成校验(net/url解析、http/https scheme、Host 非空),所以格式错 误的 URL 不会动到运行中的实例与配置。改对 URL 再重跑。- 配置 reload 没生效 ——
pg addon alertmanager reload需要容器在运行;若新的alertmanager.yml被拒绝(路由引用了未定义的 receiver、YAML 格式错误), Alertmanager 会沿用上一份好配置并打日志。查pg logs addon alertmanager,改好文件, 再 reload。 - 端口已被分配 —— 已分配的端口记在
pg.yaml里并为后续实例跳过;先pg addon remove释放,或用--port N另选一个。 - 远程 API 打不开 / 意外可访问 —— 默认
0.0.0.0下打不开是宿主防火墙问题,不是绑 定地址;反之若你不想被访问(记住:可触达即意味着任何人能创建 silence),用--listen 127.0.0.1 --force。
已知限制
- 单向衔接。 本插件既不往
prometheus.yml注入alerting:段,也不从 Prometheus 读取任何信息——它只接收被推进其 API 的东西。接通的动作在 Prometheus 那一侧完成(pg addon install prometheus --alertmanager-url …,渲染模式;--conf-file模式就自己写alerting:段)。反过来,本插件这边也永远不会去检视任何prometheus.yml。 - 无鉴权——且其后果比 Prometheus 更尖锐。API 能创建 silence(静音 oncall)、能重载
配置,且
POST /-/reload在镜像里无法关闭(pgcli 只是不去用它)。0.0.0.0绑定的 唯一保护是网络边界;不要把它暴露到不可信网络。 - 单实例 / 集群已禁用。
--cluster.listen-address=始终以空串传入,所以 HA gossip (TCP+UDP 9094)永不打开。把多个 pgcli 托管的 Alertmanager 集群起来在 v1 里不支持。 - Webhook 在 install 时不做连通性探测(只校验 URL 形状)。可达性与 payload 是否 被接受,在告警触发时才浮现于日志。
- pgcli 渲染或拷贝
alertmanager.yml,但不校验它(install 阶段没有amtool check-config闸门)。渲染出的配置不可能有错,但有错的--conf-file只会在 reload 时 从容器日志里暴露。 - 宿主侧的属主 chown 在 rootless podman(
podman unshare chown)下自动完成,pgcli 以 root 跑在 rootful 宿主上也自动完成(直接chown)。非 root 的 pgcli 连接一个显式配 置的远程 rootful daemon 时没有自动路径。 - macOS 上容器跑在 podman machine 里;目前只在 Linux 上验证过。