首页
/ Project NOMAD 磁盘信息采集器迁移指南:从主机级采集脚本到 disk-collector Sidecar 容器

Project NOMAD 磁盘信息采集器迁移指南:从主机级采集脚本到 disk-collector Sidecar 容器

2026-09-08 11:36:07作者:毕习沙Eudora

Project NOMAD 的 "Command Center"(管理后台)需要展示宿主机磁盘用量与可用空间,这一数据曾由运行在宿主机上的后台脚本负责采集。由于该方法在主机重启、进程被杀等场景下表现脆弱,项目引入了独立的 disk-collector sidecar 容器取而代之。migrate-disk-collector.md 正是对这一迁移过程的权威说明:它解释了迁移原因、演示了如何手工修改 compose.yml,并提供了自动化的迁移脚本。

读完本文,你将理解新旧两种磁盘采集架构的本质差异,掌握 disk-collector 服务在 compose 中的完整配置语义,并能用一行命令(或完全手工)安全地完成迁移。

为什么需要迁移:主机级采集方案的四个缺陷

旧方案(collect_disk_info.sh)是在宿主机上以 nohup 方式运行的无限循环脚本:每 300 秒执行一次 lsblkdf,把结果写成 /tmp/nomad-disk-info.json,再由 admin 容器通过 bind mount 读取该文件。这套设计存在以下问题(摘自 migrate-disk-collector.md):

  • 进程易失:主机进程可能崩溃或被 kill,导致磁盘信息陈旧甚至缺失,没有任何自愈机制。
  • /tmp 在重启后被清空:主机重启会清空 /tmp,此时 Docker 会在原挂载点上创建一个目录而非文件,bind mount 直接失效,admin 容器无法读取任何内容。
  • 与主机强耦合:必须在宿主机上维护一个常驻进程,限制了后续部署形态的灵活性(例如更自由地分发、迁移安装方式)。
  • 独立于容器生命周期:主机进程不受 compose 栈统一管理,难以随栈启停、更新或回滚。

新的 disk-collector sidecar 正是针对以上问题设计的:磁盘采集逻辑进入容器化组件,随 compose 栈统一编排,通过只读挂载宿主根文件系统持续工作,不再依赖 /tmp 上的任何文件。

为什么 NOMAD 需要这份磁盘信息

磁盘信息在 NOMAD 的 "Command Center" 中用于展示磁盘使用情况与可用容量。如文档所述,它不是核心功能的关键依赖,但为两类用户提供了显著更好的体验:

  • 存储空间有限、需要随时关注剩余容量的用户;
  • 不熟悉命令行与 Linux 管理的用户——他们可以在图形界面中直接看到磁盘状态,无需登录宿主机执行 df

从源码看,这份数据的消费链路位于 admin/app/services/system_service.ts:admin 的 getSystemInfo() 会读取容器内 /storage/nomad-disk-info.json(该路径即宿主机 /opt/project-nomad/storage 的挂载点),将 JSON 解析为 NomadDiskInfoRaw 结构(包含 diskLayoutfsSize),随后通过 calculateDiskUsage() 计算每个物理磁盘的占用比例,最终由 /api/system/info 等接口提供给前端 UI 渲染。所以,迁移的关键约束是:新的采集方必须把文件写到同一个位置(/opt/project-nomad/storage/nomad-disk-info.json,admin 容器才能无感地继续读到数据。

为什么用独立的 sidecar 容器

新方案把采集逻辑放进单独的容器,而不是并入 admin 主容器或留在主机上,主要基于三点考量(migrate-disk-collector.md):

  1. 稳定性(Stability):采集器与 admin 主容器彼此隔离,任一容器故障都不会拖垮对方。
  2. 安全性(Security):admin 容器已通过 Docker socket、存储目录与 host.docker.internal 拥有较高的宿主机访问能力,未来 NOMAD 还可能引入多用户与更多网络暴露。将磁盘采集(即便只是只读访问宿主机文件系统)隔离到功能范围极小的独立容器中,可以显著收窄宿主机文件系统暴露面。
  3. 模块化(Modularity):既然磁盘信息不是核心功能,把它做成 sidecar 后,不需要此功能的用户可以直接不运行该容器,admin 与其他服务完全不受影响;sidecar 自身的迭代也不必改动 admin 镜像。

从项目镜像编排也能印证这一点:sidecar 采用与 Prometheus node-exporter 相同的 /:ro,rslave 只读宿主根挂载模式,无需 privilegedSYS_ADMIN 等扩展能力(见 migrate-disk-collector.sh 中的设计说明),从设计上就把权限诉求压到最低。

迁移脚本做了什么:六步全流程拆解

自动化迁移脚本 migrate-disk-collector.sh 会修改 /opt/project-nomad/compose.yml 以新增服务并移除旧的 bind mount,然后重启完整 compose 栈。执行前脚本会先做一组前置检查(必须以 bash 运行、具备 sudo 权限、Docker 已安装且运行中、存在 compose 文件),并要求交互式确认。整体流程分为六步:

步骤 动作 脚本实现要点
1 停止旧主机进程 读取 nomad-collect-disk-info.pid 记录并 kill 对应进程(见 stop_old_host_process
2 备份 compose.yml 生成带时间戳的备份 compose.yml.bak.<yyyyMMddHHmmss>(见 backup_compose_file
3 移除 admin 服务上的旧 bind mount sed 删除包含 /tmp/nomad-disk-info.json 的 volume 行(见 remove_old_bind_mount
4 插入 disk-collector 服务块 awk 在顶层 volumes: 键之前插入服务定义(见 add_disk_collector_service
5 拉取镜像并重启栈 docker compose -p project-nomad pull + up -d,重建成 admin 容器以丢弃旧挂载(见 restart_stack
6 验证容器运行 检查名为 nomad_disk_collector 的容器处于 running 状态(见 verify_disk_collector_running

其中每一步都内置了幂等与失败保护:若旧 bind mount 已不存在则直接跳过;若 disk-collector 服务已存在则跳过插入;任一步失败都会输出明确提示并中止,且备份文件会保留以便回滚。脚本结束时会提示:sidecar 每 2 分钟更新一次数据,首个采集周期约在启动后 5 秒内完成,届时 /api/system/info 即可返回磁盘数据。

手工迁移:compose.yml 增改对照

如果你不希望运行迁移脚本,也可以完全手工完成同样的改动。文档与脚本共同给出的最终配置结构如下(该配置与当前仓库中的 management_compose.yaml 中的 disk-collector 服务一致):

  disk-collector:
    image: ghcr.io/crosstalk-solutions/project-nomad-disk-collector:latest
    pull_policy: always
    container_name: nomad_disk_collector
    restart: unless-stopped
    volumes:
      - /:/host:ro,rslave  # Read-only view of host FS with rslave propagation so /sys and /proc submounts are visible
      - /opt/project-nomad/storage:/storage

同时在 admin 服务的 volumes删除这一行旧的 bind mount:

      - /tmp/nomad-disk-info.json:/app/storage/nomad-disk-info.json

配置参数逐项解读

配置项 作用与语义
image ghcr.io/crosstalk-solutions/project-nomad-disk-collector:latest sidecar 镜像地址,随更新流程跟随 latest 标签拉取
pull_policy: always —— 每次拉起前强制拉取最新镜像,确保与升级流程联动
container_name nomad_disk_collector 固定容器名,验证与日志排查均依赖该名称
restart: unless-stopped —— 异常退出自动重启(除非被显式停止),与 admin 等服务的重启策略保持一致
volumes 第一项 /:host:ro,rslave 只读挂载宿主机根文件系统到容器内 /hostrslave 传播使 /sys/proc 等子挂载点可见,这是读取真实宿主机视图的关键,且无需扩展权限
volumes 第二项 /opt/project-nomad/storage:/storage 将 NOMAD 存储目录挂到容器 /storage,采集结果直接写入宿主机存储目录下的 JSON 文件

关于第二条 volume 有一条重要的实操提醒(见 management_compose.yaml):如果你重新定位过存储目录,必须把这里的主机路径与 admin 服务、NOMAD_STORAGE_PATH 设置成完全一致(路径区分大小写),否则 UI 中显示的磁盘用量会指向错误的位置。迁移文档也明确建议:执行任何修改前先备份 compose.yml

Sidecar 内部的采集逻辑与文件格式

理解 sidecar 如何产出数据,有助于排查迁移后的问题。容器镜像基于 alpine:3.20,仅额外安装 util-linux(提供 lsblk)与 bash(见 sidecar-disk-collector/Dockerfile),镜像体积与攻击面都被刻意压到最小。

核心循环位于 collect-disk-info.sh,每 120 秒执行一轮:

  1. 磁盘布局采集lsblk --sysroot /host --json -b -o NAME,SIZE,TYPE,MODEL,SERIAL,VENDOR,ROTA,TRAN--sysroot 指向只读挂载的宿主根,-b 强制以字节为单位输出,JSON 结构对应管理端解析的 diskLayout.blockdevices
  2. 文件系统用量采集:读取 /host/proc/1/mounts(PID 1 即宿主机 init 进程,代表宿主机根挂载命名空间),逐行解析真实文件系统,并用 df -P -B1 获取字节精度的 size/used/available/use。注释中专门解释了为何不读取 /host/proc/mounts——它是指向 /proc/self/mounts 的软链,反映的是容器自身的命名空间,而非宿主机的挂载表。
  3. 过滤伪文件系统与噪声:跳过 tmpfs/devtmpfs/squashfs/overlay/proc/sysfs/cgroup 等虚拟文件系统,也跳过 Docker 为单文件注入的 bind mount(如 /etc/resolv.conf),避免虚假容量。若宿主挂载表不可读,则退化为直接对 /storage 执行 df 作为兜底。
  4. 原子写盘:先写临时文件 nomad-disk-info.json.tmp,再 mv 覆盖目标文件,避免读取方拿到半截 JSON。启动时若目标文件不存在,还会先写入一个合法的空占位结构,保证 admin 容器首次解析不报错。

最终 JSON 结构与旧脚本(collect_disk_info.sh)保持一致:

{
  "diskLayout": { "blockdevices": [ ... ] },
  "fsSize": [ ... ]
}

admin 端读取后,calculateDiskUsage() 会按 type === 'disk' 过滤物理磁盘,对同一设备在多个挂载点重复出现的情况按最大 size 去重(这是 Docker bind mount 造成的常见重复),再为每块磁盘汇总分区用量并计算 percentUsed。前端 useDiskDisplayData.ts 最终把这份数据渲染成磁盘与可用空间的直观展示。

迁移后如何验证

脚本第 6 步自带了容器级验证:docker ps --filter "name=^nomad_disk_collector$" --filter "status=running"。除此之外,你还可以按以下顺序确认整个链路正常:

# 1. 容器在跑
docker ps --filter name=nomad_disk_collector

# 2. 查看采集日志(能看到 "Disk info updated successfully.")
docker logs nomad_disk_collector

# 3. 确认 JSON 文件已由 sidecar 写入宿主机存储目录(由容器内 /storage 映射而来)
cat /opt/project-nomad/storage/nomad-disk-info.json

# 4. 确认 admin 容器内也能读到同一文件(admin 的 /app/storage 映射同一目录)
docker exec nomad_admin cat /app/storage/nomad-disk-info.json

文件存在且内容含 diskLayout/fsSize 后,调用 /api/system/info 即可在响应中获得经过 calculateDiskUsage 计算后的磁盘数组;脚本提示首个采集周期约在 sidecar 启动后 5 秒内完成,若容器状态异常,可直接用 docker logs nomad_disk_collector 排查(这也是脚本验证失败时给出的首要排查命令)。

不运行迁移脚本时的注意事项

迁移文档特别强调:若你自定义过 compose.yml 或 NOMAD 的存储布局(非默认路径),请优先手工迁移而非运行自动化脚本。原因是脚本第 4 步依赖在顶层 volumes: 键前插入服务块这一假设,并且会自动重启整个 compose 栈;对存储路径做过重新定位的用户,需要按 management_compose.yaml 中三处联动(admin volume、NOMAD_STORAGE_PATH、disk-collector volume)的要求保持路径完全一致。无论走脚本还是手工,先备份 compose.yml 都是不可省略的第一步——脚本在第 2 步会自动生成带时间戳的备份,手工操作时请自行完成等价备份。

迁移完成后,Project NOMAD 的磁盘信息展示将由一个随 compose 栈统一编排、只读访问宿主、无需特权模式的轻量 sidecar 持续供给,彻底摆脱对宿主机后台进程与 /tmp 临时文件的依赖——这也是项目为更灵活的后续部署形态提前铺平的一条路。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391