
上图是夜莺的对象列表。很多小伙伴会奇怪:这个页面没有新增按钮,这些对象数据从哪里来?能不能手工修改?为什么夜莺要设计这个功能?
先给结论:
- 对象列表里的数据主要来自流经
n9e-server的监控数据。 n9e-server会从监控数据中解析机器标识,并写入数据库的targets表。- 对象列表主要用于机器打标签、业务组权限控制、自愈脚本执行范围和基础利用率展示。
- 如果数据没有流经
n9e-server,例如 Prometheus 直接抓取 node-exporter 并写入时序库,对象列表里可能看不到这些机器,但看图和告警通常不受影响。
简介
从“标识”这一列可以看到,对象列表里的内容基本都是机器名,说明这个表里的数据主要是机器信息。部署了 Categraf、Telegraf、Grafana-Agent、Datadog-agent 这些采集器的机器,通常会出现在这个表里。
但如果你使用 node-exporter 并通过 Prometheus 拉取监控数据,node-exporter 所在机器不一定会出现在对象列表里。关键差异不在于有没有监控数据,而在于这些数据是否经过 n9e-server。
原理
agent 采集监控数据之后上报给 n9e-server,n9e-server 会从监控数据中解析机器标识信息,然后写入 DB 的 targets 表。写入之后,用户就能在对象列表里看到这些机器。
换句话说,如果数据没有流经 n9e-server,n9e-server 就无法解析监控数据,也就不会把机器写入对象列表。典型例子是 node-exporter:node-exporter 的数据是 PULL 模式,你可能直接用 Prometheus 抓取 exporter 数据,然后由 Prometheus 写入时序库。这个链路里数据没有经过 n9e-server,所以对象列表里不会出现这些机器。
| 数据链路 | 是否容易进入对象列表 | 原因 |
|---|---|---|
Categraf / Telegraf / Grafana-Agent / Datadog-agent 上报到 n9e-server |
是 | n9e-server 可以解析机器标识并写入 targets 表 |
| Prometheus 直接抓取 node-exporter 并写入时序库 | 否 | 数据没有流经 n9e-server |
手工写入 targets 表 |
可以 | 直接注册对象数据,但需要自行保证字段正确 |
用处
1. 给机器打标签,做细粒度分类
机器只属于一个业务组,但只用业务组来划分,颗粒度往往太粗。更细粒度的划分需要通过标签完成。这部分设计逻辑可以参考《Nightingale|夜莺监控机器分组的设计逻辑》。
机器一旦打了标签,机器相关监控数据上报时,就会自动为时序数据附上这些标签。比如给 host1 打一个标签 service=a,过一会儿(约 20s)查看 host1 的时序数据,例如 mem_available_percent,就会发现 metric 上多了 service=a 标签。
这样做的好处是:即使不用夜莺看图,而是使用 Grafana 等 UI 工具直接查询时序库,也可以使用 service=a 做过滤。
2. 给机器划分业务组,做权限控制
对象列表还用于建立机器与业务组的关系。告警自愈功能需要在机器上执行脚本,这类操作必须强管控。哪些人可以对哪些机器执行脚本,就需要依赖业务组和机器的对应关系。同样可以参考《Nightingale|夜莺监控机器分组的设计逻辑》。
3. 显示机器基础利用率数据
对象列表表格里的红绿区块,实际展示的是监控指标数据。具体指标可以参考 webapi.conf 的如下配置:
[TargetMetrics]
TargetUp = '''max(max_over_time(target_up{ident=~"(%s)"}[%dm])) by (ident)'''
LoadPerCore = '''max(max_over_time(system_load_norm_1{ident=~"(%s)"}[%dm])) by (ident)'''
MemUtil = '''100-max(max_over_time(mem_available_percent{ident=~"(%s)"}[%dm])) by (ident)'''
DiskUtil = '''max(max_over_time(disk_used_percent{ident=~"(%s)", path="/"}[%dm])) by (ident)'''
实际就是这几个 PromQL。PromQL 里有两个变量:
%s:填充多台机器,用|分隔。%d:时间段,默认是2,也就是最近 2 分钟。
如果表格里没有数据,常见原因有两个:
- 机器时间没有校准,尤其是浏览器所在 PC 和服务端时序库的时间不一致。
- 监控数据上报滞后,最近 2 分钟内没有新数据,导致上面的 PromQL 查不到结果。
自行注册
如果想自行往 target 表里注册数据,有两个办法:
- 直接上报监控数据到
n9e-server。监控数据里带有ident标签时,n9e-server会取ident的值作为机器标识并写入target表。 - 直接写 DB 中的
target表。
对象列表内容缺失的影响
如果使用 Prometheus 或 vmagent 作为抓取器,直接抓取 node-exporter 的数据并写入时序库,数据没有流经 n9e-server,此时对象列表可能为空。
对象列表为空是否有影响?有影响,但影响范围有限:
- 不影响告警规则配置。
- 不影响监控看图。
- 会影响依赖对象列表和业务组关系的能力,例如告警自愈。
很多公司没有使用告警自愈功能,所以对象列表为空未必是阻塞问题。判断时不要只看“列表有没有机器”,更要看你的使用场景是否依赖机器标签、业务组权限和自愈脚本。
FAQ
Q1:对象列表没有新增按钮,是否代表不能手工维护?
A:对象列表主要由监控数据自动注册,也可以通过直接写 target 表的方式注册,但需要自行保证数据正确。
Q2:node-exporter 有数据,为什么对象列表里没有机器?
A:因为 node-exporter 常见链路是 Prometheus PULL 抓取并写入时序库,数据没有流经 n9e-server,所以 n9e-server 无法解析并注册对象。
Q3:对象列表为空,告警还能用吗?
A:通常不影响告警规则和看图;但如果要做告警自愈、机器业务组权限控制或对象标签管理,就需要对象列表里的机器信息。
