Linux Node Problem Detector 的自定义问题检测插件

7次阅读

lnpd 自定义检测插件需满足:文件置于 plugins/ 目录、命名合法、默认导出含 name/run/intervalseconds 的对象;run() 须返回 promise 且仅 error/warning 级 problems 转为 nodecondition;不支持热更新,须重启 lnpd 生效。

Linux Node Problem Detector 的自定义问题检测插件

怎么写一个能被 LNPD 加载的自定义检测插件

LNPD 不会自动扫描任意 JS 文件,它只认 plugins/ 目录下符合命名和导出规范的模块。你写的插件必须导出一个带特定字段的对象,否则启动时直接忽略,连日志都不会打。

实操建议:

  • 插件文件必须放在 /var/lib/node-problem-detector/plugins/(或你启动 LNPD 时用 --plugin-dir 指定的路径)
  • 文件名必须匹配 xxx.jsxxx.mjs,且不能以 ._ 开头
  • 必须默认导出一个对象,含 name(字符串)、run(函数)、intervalSeconds(数字)三个字段
  • run() 必须返回一个 Promise,resolve 值为 {problems: []} 格式,problems 是数组,每个元素至少有 severityproblem

常见错误现象:LNPD 启动没报错,但你的插件完全没运行痕迹 ——大概率是导出结构不对,或者文件没放对位置。

run() 函数里该查什么、怎么查才不拖垮节点

LNPD 运行在宿主机上,所有检测逻辑都跑在 Node.js 进程里,run() 执行期间会阻塞整个插件轮询周期。别在里面做同步文件遍历、无超时 HTTP 请求或 execSync 调用。

实操建议:

  • 优先读取 /proc/sys 下的瞬时状态,比如检查 /proc/sys/net/ipv4/ip_forward 是否为 0
  • 调用系统命令必须用 execFile + timeout 选项,例如 execFile('ss', ['-tuln'], {timeout: 2000})
  • 避免重复解析大文件,比如检查 /var/log/messages 时,用 tail -n 100 配合流式处理,而不是 fs.readFileSync
  • 如果要聚合指标(如 CPU 使用率),直接读 /proc/stat 算差值,别依赖 os.loadavg() —— 它不反映容器内真实压力

性能影响:一个耗时 800ms 的 run()intervalSeconds: 30 下看似没事,但若同时启用 5 个插件,就可能造成轮询堆积,导致问题上报延迟。

上报的问题为什么没出现在 kubectl describe node 的 Events 里

LNPD 只把 severity"error""warning" 的条目转成 NodeCondition,其它一律丢弃。而且 Condition 名称必须合法:只能含小写字母、数字、-,且以字母开头,长度 ≤ 253 字符。

实操建议:

  • problems 数组中每个对象必须有 problem(字符串,即 Condition 名)和 severity"error" / "warning"
  • 不要用空格或下划线命名 problem,比如 "disk full""disk_full" 都非法,得写成 "disk-full"
  • 如果想附带详情,加 detail 字段(字符串),LNPD 会把它塞进 NodeCondition 的 message
  • 确认 LNPD 启动参数含 --enable-node-condition=true,否则即使格式全对,也不生成 Condition

常见错误现象:kubectl get node <node> -o wide</node> 看不到新 Condition,但 journalctl -u node-problem-detector 显示插件执行成功——八成是 severity 写成了 "info"problem 命名不合规。

插件热更新是否可行、有哪些限制

LNPD 不支持运行时重载插件。修改 JS 文件后,必须重启 LNPD 进程才能生效。但它会在每次轮询前重新 require() 插件模块,所以如果你只是改了 run() 内部逻辑(没改导出结构),重启后就能用新逻辑。

实操建议:

  • 开发阶段用 systemctl restart node-problem-detector 最稳妥;别指望 touch 文件触发重载
  • 不要在插件里缓存全局状态(比如用闭包变量记上次检查结果),因为每次 require() 都是全新模块实例
  • 如果需要跨次运行的状态(如上次检查时间戳),必须写到磁盘(/var/lib/node-problem-detector/state/)或读取 /proc 等动态源
  • 注意文件权限:LNPD 默认以 node-problem-detector 用户运行,插件文件需对该用户可读

容易被忽略的地方:插件代码里用 console.log 输出的内容,默认不会进 journal 日志——得用 process.stderr.write() 或配置 LNPD 的 --logtostderr 才能看到调试信息。

text=ZqhQzanResources