这个模块做什么 #
一台实例有很多话要说:fail2ban 封禁了一个 IP,aide 发现系统文件被改动,昨晚的备份失败了,根磁盘已经用到 95 %。如果每个模块各说各的——这边一封邮件,那边一行日志——谁都不会知道,而机器有十台时,问题就放大十倍。
global-alerts 模块是 imaxe 的中央告警总线:所有这些通知都经过同一条命令,也都汇聚到同一个终点——一个由整个机群共享的 Amazon SNS 主题。之后 SNS 想怎么分发都行:邮件、短信、Lambda 函数、SQS 队列、你的值班系统。发布使用实例的 IAM 角色(sns:Publish 权限),因此不需要保存任何凭证。发送前还会先过滤噪音:严重级别阈值丢弃达不到你关心级别的内容,去重窗口则避免同一条告警把你吵醒四十次。
如果 SNS 不可用——网络中断、角色还没有权限、区域不可达——告警不会丢失:它会在磁盘上排队,由一个 systemd 定时器每 5 分钟重试一次。
你需要一个 SNS 主题的 ARN(arn:aws:sns:区域:账户:主题),并且实例要能往里发布。如果你是从启动器启动的 AMI,CloudFormation 模板已经帮你创建了主题、订阅了你的邮箱、创建了带 sns:Publish 的 IAM 角色,并把 ARN 作为标签传给实例:模块会自动配置好,这里没有任何事要做。
常见任务 #
挑一件你想做的事。每个配方都带着写好的命令——把 ARN 和文字换成你自己的,然后点复制。
1
设置 SNS 主题
告诉实例该把通知发布到哪里。
用 ubuntu 用户通过 SSH 连上你的服务器。
把模块指向你的主题 ARN。区域会从 ARN 本身推导出来,所以通常不必指定:
$ sudo imaxe global-alerts configure \
--topic-arn arn:aws:sns:eu-west-1:123456789012:imaxe-alerts多台实例发布到同一个主题?用 --source 给每台一个能认出来的来源标签(默认使用 hostname):
$ sudo imaxe global-alerts configure --source web-prod-1/etc/imaxe/global-alerts.yml,发送随即启用。接着做发送一条测试告警这个配方。2
发送一条测试告警
在信任这条通道之前,先确认 IAM 角色真的能发布。
向已配置的主题发布一条测试告警:
$ sudo imaxe global-alerts test测试会跳过阈值和去重——它总是会发出去——而且一旦失败,它会把 AWS 的真实错误返回给你,而不是悄悄排队。查看订阅该主题的邮箱(以及垃圾邮件文件夹)。
MessageId 并且收到了通知,通道就是通的。如果出现 AuthorizationError,说明实例缺少该主题上的 sns:Publish 权限。3
从脚本发送告警
模块用的同一条通道,也可以拿来发你自己的东西。
一条带严重级别和来源的告警:
$ sudo imaxe global-alerts send --severity critical \
--source backup --subject "备份失败" \
"数据库的夜间备份以错误结束"如果文本由别的命令产生,用 - 作为消息,把它通过 stdin 传进来:
$ df -h / | sudo imaxe global-alerts send --severity warning -对于每隔几分钟就跑一次的东西,给它一个稳定的去重键:在配置的窗口内只有第一条会发出去:
$ sudo imaxe global-alerts send --severity warning \
--dedup-key root-disk-full "根磁盘已用 95%"--dedup-key 时,模块会用来源 + 严重级别 + 主题推导一个。4
查看总线状态
主题、区域、AWS CLI 和待发告警,一眼看完。
当前状态的摘要:
$ sudo imaxe global-alerts status要确认真正生效的是哪份配置——包括来自实例标签、优先级高于文件的那部分:
$ sudo imaxe global-alerts show
$ sudo imaxe global-alerts status --json--json 就可以直接给面板或脚本用。5
降低噪音
提高严重级别阈值,并放宽去重窗口。
如果你只想知道要紧的事,把低于 warning 的全部丢掉:
$ sudo imaxe global-alerts configure --min-severity warning去重窗口没有对应的标志:它在配置文件里调整。如果同一条告警重复得很频繁,就把它调大:
dedup_window: 1h # 30s、5m、1h…(默认 5m)test 仍然每次都发布,所以你始终留着检查通道的办法。6
查看队列并重试
SNS 没响应时留下了什么,以及如何强制发送。
看看有什么待发,以及最近发送过的去重键:
$ sudo imaxe global-alerts historysystemd 定时器每 5 分钟已经会重试一次,但在修好权限或网络之后你可以手动强制:
$ sudo imaxe global-alerts flush
$ systemctl status imaxe-global-alerts-flush.timer7
静音模块
停止发布,但不丢掉配置。
停用告警发送并移除重试定时器:
$ sudo imaxe global-alerts remove主题、区域和其余设置都保留在文件里:要重新打开,一条 configure 就够了,它会重新启用模块。
send 不会失败:它们通过 stderr 提示模块已停用,并以退出码 0 结束。模块使用实例角色的凭证发布,而不是保存下来的密钥。如果角色不允许对该主题执行 sns:Publish,告警只会一条接一条堆在队列里,永远送不出去。一条 imaxe global-alerts test 会当场告诉你,并原样给出 AWS 返回的错误。
用法概览 #
imaxe global-alerts <子命令> [--topic-arn ARN] [--severity 级别] [标志]所有子命令都需要 root 权限(用 sudo),因为它们要写 /etc/imaxe/、把状态保存在 /var/lib/imaxe/,还要管理一个 systemd 单元。没有需要经手的机密:发布走的是实例的 IAM 角色。给 status、show、history 或 flush 加上 --json,就能得到机器可读的输出。
子命令 #
| 子命令 | 作用 | 相关标志 |
|---|---|---|
| status | 状态:已配置的主题、生效的区域、AWS CLI 是否可用,以及队列中的告警。 | --json |
| configure | 设定 SNS 主题和发送选项。若模块此前被停用,会重新启用。 | --topic-arn, --region, --source, --min-severity |
| send | 发布一条告警。这是运维人员和其他模块使用的通道。 | --severity, --source, --subject, --dedup-key |
| test | 跳过阈值和去重发布一条测试告警,失败时报告真实错误。 | --severity |
| show | 显示生效的配置(文件 + 已应用的实例标签)。 | --json |
| history | 队列中待发的告警,以及最近发送过的去重键。 | --json |
| flush | 重试队列中的告警。systemd 定时器执行的也是它。 | --json |
| remove | 停用发送并移除定时器。保留配置。 | — |
参数与标志 #
| 标志 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| --topic-arn 必填 | string | — | 目标 SNS 主题的 ARN(arn:aws:sns:区域:账户:主题)。没有它模块无法发布。 |
| --region | string | 取自 ARN | AWS 区域。省略时从主题 ARN 推导;再不行则取自 IMDS 或 AWS_REGION。 |
| --source | string | hostname | 来源标签。在 configure 中是实例的;在 send 中是这条告警的(例如发出它的模块)。 |
| --min-severity | string | info | 阈值:丢弃低于该级别的告警。取值:info、warning、critical。 |
| --severity | string | info | 在 send/test 中:这条告警的级别。也接受简写 warn 和 crit。 |
| --subject | string | 取自消息 | 简短主题。省略时从消息本身推导。 |
| --dedup-key | string | 自动推导 | 去重键:抑制 dedup_window 内的重复。默认用来源 + 严重级别 + 主题计算。 |
| <消息> 必填 | 位置参数 | — | 在 send 中:告警正文,或用 - 从 stdin 读取。 |
| --json | bool | false | 在 status、show、history 和 flush 中,把结果以 JSON 输出到 stdout。 |
当一条告警被丢弃时——模块已停用、严重级别低于阈值,或在窗口内重复——send 会在 stderr 上说明原因,并以退出码 0 结束。这样发出它的脚本,就不会因为你自己设的过滤条件而中断。
通过实例标签配置 #
每一次部署都要指向它自己的主题,为此重建 AMI 显然说不通。所以模块除了读文件,还会通过 IMDSv2 读取前缀为 imaxe.global-alerts. 的实例标签:只要存在,它们就压过 YAML。启动器的 CloudFormation 模板正是这么做的,而且它还要求 MetadataOptions.InstanceMetadataTags: enabled,标签才读得到。
| 标签 | 等价于 | 取值 |
|---|---|---|
| imaxe.global-alerts.topic_arn | topic_arn | 目标 SNS 主题的 ARN。 |
| imaxe.global-alerts.region | region | AWS 区域;留空 = 从 ARN 或 IMDS 推导。 |
| imaxe.global-alerts.source | source | 来源标签;留空 = hostname。 |
| imaxe.global-alerts.min_severity | min_severity | info · warning · critical |
| imaxe.global-alerts.dedup_window | dedup_window | 时长:30s、5m、1h… |
| imaxe.global-alerts.enabled | enabled | true/false(也接受 1/0、yes/no、on/off)。 |
在 AWS 之外,或者 IMDS 被屏蔽时,读取会在毫秒内失败,模块继续按文件里的内容运行。想看真正生效的是什么,用 imaxe global-alerts show。
文件与路径 #
| 路径 | 内容 |
|---|---|
| /etc/imaxe/global-alerts.yml | 模块配置:主题、区域、来源、阈值和去重窗口。 |
| /var/lib/imaxe/state/global-alerts/spool/ | 待发告警队列,每条一个 .json 文件,按时间先后排列。 |
| /var/lib/imaxe/state/global-alerts/sent.json | 去重键的记录,附带最后一次发送的时间。 |
| /etc/systemd/system/imaxe-global-alerts-flush.timer | 重试定时器:开机 2 分钟后启动,之后每 5 分钟一次。 |
global-alerts.yml 示例:
enabled: true
topic_arn: arn:aws:sns:eu-west-1:123456789012:imaxe-alerts
region: "" # 留空 = 从 ARN 或 IMDS 推导
source: "" # 留空 = 实例的 hostname
min_severity: info
dedup_window: 5m状态(队列和去重记录)刻意放在 /var/lib/imaxe/ 而不是 /etc/:它是状态,不是配置。两个路径都可以用环境变量 IMAXE_CONFIG_DIR 和 IMAXE_STATE_DIR 改到别处。
告警格式 #
SNS 消息体是带版本的 JSON(schema: 1),这样订阅方除了用邮件阅读,也可以用 Lambda 或队列来处理:
{
"schema": 1,
"severity": "critical",
"source": "backup",
"subject": "备份失败",
"message": "数据库的夜间备份以错误结束",
"host": "web-prod-1",
"instance_id": "i-0abc123def4567890",
"region": "eu-west-1",
"ts": "2026-07-25T03:14:07Z",
"dedup_key": "9f2c1b7e44a0d513"
}SNS 消息的主题按 [imaxe][严重级别] host: 主题 组成,会清理为可打印 ASCII 并截断到 100 个字符,这是 SNS 的限制。
退出码与日志 #
每次执行都会返回一个可以用 echo $? 查看的退出码——在脚本里串联时很有用:
模块也会响应 imaxe 的健康检查:如果已启用却没有主题,health 就会失败,于是一条 imaxe health 能在第一条告警派上用场之前就把问题揪出来。
$ sudo imaxe global-alerts test; echo "退出码: $?"
$ journalctl -u imaxe-global-alerts-flush.service -n 50故障排查 #
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 出现 NO TOPIC(退出码 64) | 文件和标签里都没有主题 ARN。 | 执行 configure --topic-arn …,或检查实例是否带有 imaxe.global-alerts.topic_arn 标签,以及元数据中是否启用了标签。 |
| 反复出现「SNS 不可用;告警已排队」 | 实例角色缺少该主题上的 sns:Publish,或者 ARN 属于另一个账户或区域。 | 执行 test 查看 AWS 的确切错误,修正角色策略,然后 flush。 |
| status 里显示「aws CLI 可用:false」 | 实例没有安装 AWS CLI;模块是通过它发布的。 | 安装 AWS CLI。imaxe 的 AMI 默认自带;自建主机上需要自行添加。 |
| 你改了配置,show 却还显示另一个值 | 某个 imaxe.global-alerts.* 标签盖过了文件:这是设计上的优先级。 | 改实例标签(或 CloudFormation 堆栈参数),而不是改 YAML。 |
| 多条相同告警只到了第一条 | 去重窗口把它们抑制了。 | 这是预期行为。调小 dedup_window,或者如果它们确实是不同事件,就用不同的 --dedup-key。 |
| 什么都没收到,也没有报错 | 模块被停用了,或者严重级别低于 min_severity。 | show 会告诉你 enabled 和阈值;configure 可以重新启用发送。 |
| 告警发布出去了,但邮件收不到 | SNS 主题的订阅还没确认。 | 找到 AWS 的确认邮件(记得看垃圾箱),并在 SNS 控制台接受订阅。 |
告警 模块遇到问题了?
把「imaxe <module> status --json」的输出发给我们,我们会尽快回复你。