监控系统不只负责发现问题,还应该尽量缩短问题恢复时间。对于已经形成标准操作的应急预案,例如清理日志、重启进程、批量执行检查命令,可以通过告警自愈机制自动触发脚本,减少人工介入。
夜莺开源项目从 v7 版本开始内置告警自愈模块。本文介绍夜莺告警自愈的工作原理、服务端和 Categraf 配置、命令通道测试方法,以及如何把告警规则和自愈脚本关联起来。
核心要点
- 夜莺告警自愈的本质是“告警引擎 + 命令执行通道”协作。
- 从夜莺 v7.0.0-beta.2.0.1 开始,告警自愈不再需要单独部署 ibex 模块。
- 服务端需要开启
[Ibex],Categraf 需要开启[ibex]并连接夜莺服务端的20090端口。 - 告警规则通过回调地址
${ibex}/脚本ID触发指定自愈脚本。 - 告警事件里的
ident标签、机器列表和操作权限,会共同决定脚本能否被执行。
夜莺项目介绍
夜莺监控是一款开源云原生观测分析工具,采用 All-in-One 的设计理念,集数据采集、可视化、监控告警、数据分析于一体,与云原生生态紧密集成,提供开箱即用的企业级监控分析和告警能力。夜莺于 2020 年 3 月 20 日,在 github 上发布 v1 版本,已累计迭代 100 多个版本。
夜莺最初由滴滴开发和开源,并于 2022 年 5 月 11 日,捐赠予中国计算机学会开源发展委员会(CCF ODC),为 CCF ODC 成立后接受捐赠的第一个开源项目。夜莺的核心研发团队,也是 Open-Falcon 项目原核心研发人员,从 2014 年(Open-Falcon 是 2014 年开源)算起来,也有 10 年了,只为把监控这个事情做好。

夜莺项目的 Github 地址是:https://github.com/ccfos/nightingale。国内用这个开源项目的公司已经比较多了,下面直接进入告警自愈的原理和配置。
告警自愈的工作原理
夜莺告警引擎在产生告警事件之后,除了可以通过多种通知媒介通知相关人员,也可以自动化执行某个动作。主要有两种方式驱动自动化动作:
- Webhook:把告警事件推送到外部系统,外部系统根据告警事件内容执行相应动作。
- 脚本:直接到告警机器上,或指定中控机上执行脚本。脚本可以是 shell、Python、bat 等类型。
本文重点讲第二种:通过脚本做告警自愈。
要在告警机器上执行脚本,需要机器上部署一个 agent。这个 agent 周期性和服务端发起心跳,拉取要执行的脚本,并把脚本执行结果上报给服务端。在夜莺生态里,这个 agent 就是 categraf。
告警事件产生之后,告警引擎发现这个事件需要执行自愈动作,就会在服务端创建一个脚本任务,等待 agent 拉取执行。所以本质上,是告警引擎和命令执行通道共同协作,达成告警自愈的效果。
完整链路可以理解成四步:
- 告警规则触发,夜莺生成告警事件。
- 告警规则配置了自愈回调地址,夜莺创建脚本任务。
- Categraf Agent 从夜莺服务端拉取脚本任务并在目标机器执行。
- Categraf 将脚本执行结果上报回夜莺,用户可以在任务页面查看 stdout 等结果。
部署配置
首先需要夜莺 v7.0.0-beta.2.0.1 以上的版本。之前的版本也有告警自愈能力,但需要额外安装部署 ibex 模块;从这个版本开始,就不需要单独的 ibex 模块了。
修改夜莺服务端的配置
在夜莺配置文件 etc/config.toml 中搜索 Ibex,把 Enable 设置为 true:
[Ibex]
Enable = true
RPCListen = "0.0.0.0:20090"
重启夜莺,让配置生效。此时通过 ss 或 netstat 命令可以看到夜莺服务端监听了 20090 端口。这个端口用于 Categraf 拉取脚本任务、上报脚本结果。
ss -tln|grep 20090
注意
如果夜莺使用的数据库连接账号具备建表权限,进程启动后会自动创建 ibex 相关表,也就是告警自愈相关的表。如果数据库连接账号没有建表权限,就需要手工建表。
建表 SQL 在这里:https://github.com/flashcatcloud/ibex/blob/master/sql/ibex.sql 注意,从第 7 行开始复制,把这些表建到夜莺的库里,默认库名是 n9e_v6,不要建到 ibex 库里。老版本的告警自愈依赖单独的 ibex 模块,ibex 模块用的是 ibex 库;新版本把 ibex 能力内置到夜莺中,数据库也合并到一起。
如果你是从老版本夜莺升级上来的,需要把之前 ibex 库中的表迁移到 n9e_v6 库中,迁移命令如下:
mysqldump -u username -p ibex > ibex.sql
mysql -u root -p n9e_v6 < ibex.sql
修改 Categraf 的配置
Categraf 的配置文件是 conf/config.toml。在 conf/config.toml 中搜索 ibex,把 enable 设置为 true,并正确配置夜莺服务端的地址和端口:
[ibex]
enable = true
interval = "1000ms"
servers = ["127.0.0.1:20090"]
meta_dir = "./meta"
如果机器量比较大,比如超过 10000 台,建议把 interval 调整得稍微大一些,例如 2500ms,否则容易给服务端造成较大压力。servers 配置是数组,可以配置所有夜莺服务端地址。多个夜莺服务端实例存在时,Categraf 启动后会自动探测并连接网络延迟最小的实例;如果该实例挂了,Categraf 会自动切换到其他实例,保证高可用。
改完配置之后,重启 Categraf 让配置生效。
注意
如果使用夜莺的边缘部署模式,这里的 servers 配置为 n9e-edge 的地址即可。边缘模式下,n9e-edge 的配置文件中也要开启 Ibex。
测试命令通道
告警自愈依赖命令通道,所以正式配置自愈前,应该先测试命令通道是否正常。即便不用告警自愈,命令通道本身也很有用,可以用来批量远程执行命令,例如批量重启服务、清理日志、查看输出或安装软件。

去机器列表里,选中要执行命令的机器,点击标识栏上面的复制按钮,复制相关的机器标识。然后去【告警自愈】-【任务】页面创建临时任务,把刚才复制的机器列表填写到 Host 框中,并在 Script 中填写要执行的脚本内容。默认 Script 中已经有一个 ss -tln 命令,可以不修改直接执行。

执行完成之后,结果如下,可以点击 stdouts 查看所有机器的脚本 stdout 结果:

创建任务时字段内容较多,各字段页面上都有说明,这里不展开。核心就是去一批机器上跑脚本。因为执行脚本涉及权限控制,如果是 Admin 账号,所有机器都可以执行命令;如果是普通账号,只能在有权限的机器上执行脚本。权限范围取决于该账号管理了哪些业务组,账号管理的业务组下的机器才有权限。
创建自愈脚本
命令通道测通后,下一步是和监控告警引擎联动,让告警事件产生时自动创建脚本任务,再由 agent 执行这个脚本任务。创建自愈脚本的菜单入口是:【告警自愈】-【脚本】。比如我创建了如下脚本:

自愈脚本创建时,Host 字段留空即可。因为告警触发时才知道具体是哪台机器触发告警,Host 字段会由告警引擎动态填充。
上面这些脚本只是演示用。假设现在要创建一个告警规则:“机器磁盘快满了”,如果触发告警,就自动执行 ID 为 19 的脚本。配置方式很简单,在告警规则里配置一个回调地址 ${ibex}/19 即可:

这样,当告警事件产生时,告警引擎会自动创建一个脚本任务,让 agent 去执行 ID 为 19 的脚本。脚本任务的执行结果会上报给服务端,可以在【告警自愈】-【任务】页面查看。
通常一个告警规则对应一个自愈脚本。如果想把脚本做得更通用,用一个脚本处理不同场景,就需要在脚本里拿到告警事件详情,再根据事件内容分支处理。夜莺支持把告警事件的关键信息通过 stdin 传给脚本,脚本可以这样读取:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import sys
import json
payload = json.load(sys.stdin)
print(payload)
这是一个很简单的 Python 脚本,从 stdin 中读取内容,json decode 后放到 payload 变量里,然后用 print 把 payload 打印出来。打印结果如下:
{'__name__': 'system_load_norm_1', 'alert_severity': '2', 'alert_trigger_value': '0.195', 'env': 'ENV', 'ident': 'dev-n9e-01', 'rulename': '测试告警自愈参数-勿删23'}
这样就可以在脚本里根据告警事件内容做不同处理。例如根据 rulename 决定处理动作,根据 alert_severity 区分执行力度,根据 ident 确认目标机器。
注意:告警事件中需要有 ident 标签(表示是哪个机器告警了),ident 对应的机器需要在机器列表里,且告警规则的最后修改人对这个机器有操作权限,夜莺才会去对应的机器执行脚本。
配置检查清单
上线告警自愈前,建议按下面清单检查:
| 检查项 | 为什么重要 |
|---|---|
| 夜莺版本不低于 v7.0.0-beta.2.0.1 | 新版本内置 ibex 能力,不需要单独部署 ibex 模块 |
服务端 [Ibex] 已开启 |
Categraf 需要连接服务端拉取脚本任务 |
20090 端口可达 |
这是 Categraf 拉取任务、上报结果的端口 |
Categraf [ibex] 已开启 |
没有 Agent 拉取任务,自愈脚本不会执行 |
| 数据库表已创建或迁移 | 自愈任务和脚本需要持久化 |
告警事件带有 ident 标签 |
夜莺需要知道脚本应该在哪台机器执行 |
| 规则最后修改人有机器权限 | 权限不足时不会在目标机器执行脚本 |
| 脚本经过临时任务验证 | 避免告警触发后执行未验证的危险动作 |
FAQ
Q1: 夜莺告警自愈一定要用脚本吗? A: 不一定。夜莺也可以通过 Webhook 把告警事件推给外部系统,由外部系统执行动作。本文重点介绍的是脚本方式。
Q2: 为什么自愈脚本没有执行?
A: 优先检查 ident 标签、机器是否在机器列表、Categraf 的 ibex 配置、服务端 20090 端口、以及告警规则最后修改人是否有目标机器权限。
Q3: 自愈脚本应该直接做高风险操作吗? A: 建议先从只读检查、日志清理、可回滚动作开始。涉及重启、删除、扩容等高风险操作时,应先通过命令通道临时任务充分验证,并做好权限隔离。
小结
夜莺告警自愈把监控告警和自动化运维连接起来:告警规则发现问题,ibex 命令通道创建任务,Categraf 在目标机器执行脚本并回传结果。只要脚本动作足够标准、权限边界设置清楚,这套机制就可以把很多重复性的应急动作从人工处理变成自动触发。
