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

怎么写一个能被 LNPD 加载的自定义检测插件
LNPD 不会自动扫描任意 JS 文件,它只认 plugins/ 目录下符合命名和导出规范的模块。你写的插件必须导出一个带特定字段的对象,否则启动时直接忽略,连日志都不会打。
实操建议:
- 插件文件必须放在
/var/lib/node-problem-detector/plugins/(或你启动 LNPD 时用--plugin-dir指定的路径) - 文件名必须匹配
xxx.js或xxx.mjs,且不能以.或_开头 - 必须默认导出一个对象,含
name(字符串)、run(函数)、intervalSeconds(数字)三个字段 -
run()必须返回一个 Promise,resolve 值为{problems: []}格式,problems是数组,每个元素至少有severity和problem
常见错误现象: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 才能看到调试信息。










