跳转至

SOP —— /projects 共享存储纳管(LSF 执行节点 + 提交节点)

  • 主题:给 LSF 节点补齐 /projects(EDA 作业共享目录),并纳入部署器阶段1 的受管挂载项, 避免手工挂载造成漂移。
  • 变更日期:2026-10-07
  • 触发来源:slurm_ins《EDA 集群存储与服务拓扑巡检报告》(2026-10-06 实测 / 10-07 复核) §二 G1 与 §三「项目落点」表 → 落点 lsf_ins HANDOFF §3 #5。
  • 交付物:本目录(projects_mount/),含本文档与 backup/README.md。

一、背景

从统一提交节点 .28(hpc-submit)提交、脚本内引用 /projects 的作业,落到执行节点 (.25–.27)后因路径不存在而失败——三台执行节点缺该挂载。取证结论:

主机 角色 /projects 变更前状态
.23 / .24 master-01/02 无挂载、无 fstab(MXJ=0 不接作业,无需求)
.25 / .26 / .27 lsf-work-01~03 无目录、无挂载、无 fstab
.28 hpc-submit 有挂载但 /etc/fstab 无记录(手工挂载,重启即丢)

宿主机 .249 早已导出 /data/nfs/projects(rw,async,no_subtree_check,no_root_squash, 允许 192.168.31.0/24),前置条件具备。

本环境 NFS 挂载由部署器阶段1(stages/nfs_share.py)统一管理(三态探测 + fstab 持久化 + 漂移检测)。若用 ssh/脚本手工挂载,部署器无法感知该挂载项,--drift 会漏检、复跑也不会收敛 ——因此本次改部署器而非手工操作。

二、目标

变更完成后应达到的可验证状态:

  1. .25–.27 三台执行节点:/projects 已挂载(192.168.31.249:/data/nfs/projects,nfs4,rw), 且 /etc/fstab 有持久化条目;
  2. .28:补齐 /etc/fstab 条目(不重挂,服务不中断);
  3. /projects 成为部署器阶段1 的受管项:--drift 可检测其漂移,复跑幂等(第二次零变更);
  4. 端到端:从 .28 提交引用 /projects 的作业落到执行节点后能正常访问该路径。

三、前置条件

  • 宿主机 .249 已导出 /data/nfs/projects(外部依赖,本工程不代建);
  • 操作机具备免密 sudo(sudo -n exportfs -v 可用);节点侧已装 nfs-utils(阶段0 负责);
  • 节点 SSH 免密(root);.25–.27 上无 RUN 作业(本次不动 LSF 守护,仅挂载,风险低);
  • 配置文件中 nfs.projects_* 四项齐备(缺一即整项不纳管)。

四、影响范围

项 内容
主机 .25、.26、.27、.28(4 台);.23/.24 不在范围内(MXJ=0 不接作业)
组件 /etc/fstab(追加挂载行)、新增挂载点 /projects;部署器阶段1 实现体与配置
停服 否。/projects 原为不存在路径,挂载不影响运行中的进程;.28 仅追加 fstab 行,不重挂
窗口 无窗口要求;单次执行实测约 61 s(4 台并发探测 + 变更)
在跑作业 变更前 .25–.27 无 RUN 作业(本次不重启 LSF、不动守护,作业中断面为零)

依据巡检报告 §五 验收判据,本次只做「补目录」;报告里同批的「修挂载」 (.21/.25/.26/.27 的 /mnt/lustre)归属 lustre 项目(lustre_ins HANDOFF §3.1 #14), 不在本次范围。

五、分步操作

实现体:deploy/lsf/stages/nfs_share.py(NfsShareModule);配置: deploy/lsf/config/lsf_deploy.yaml。以下为等价操作序列。

步骤 1:阶段1 挂载项配置化(实现体扩展)

原实现把挂载项硬编码为两组(lsf / home):

@property
def _pairs(self):
    return [(self.lsf_mp, self.lsf_export), (self.home_mp, self.home_export)]

改为按节点返回受管项,并支持每项独立挂载选项:

def _mounts_for(self, node):
    mounts = [("lsf", self.lsf_mp, self.lsf_export),
              ("home", self.home_mp, self.home_export)]
    if (self.projects_export and self.projects_mp
            and node.get("name") in self.projects_hosts):
        mounts.append(("projects", self.projects_mp, self.projects_export))
    return mounts

probe() / execute() 的循环、pre_check() 的导出检查、写测试均改走该方法; 新增 _opts_for(key) 与静态判定 _opts_satisfied()。

坑(本次实测):.28 的 /projects 实挂选项里 actimeo=30 已被内核展开为 acregmin=30,acregmax=30,acdirmax=30,字符串比对会判「选项漂移」→ 触发无谓重挂 (对提交节点是中断风险)。故 _opts_satisfied() 对 actimeo=N 与三者展开形式做等价判定。 (首次实现把方向写反——遍历实挂值展开,而非判定期望值——被 dry-run 清单抓到: .28 出现 opts_projects 待变更项,修正后仅剩 fstab_projects。)

步骤 2:配置新增(生产配置 + 样例 + 校验白名单)

nfs:
  # …… 原有 server / export_cidr / export_opts / lsf_* / home_* / mount_opts 不变
  projects_export_path: /data/nfs/projects
  projects_mountpoint: /projects
  projects_mount_opts: "rw,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev"
  projects_hosts: [lsf-work-01, lsf-work-02, lsf-work-03, hpc-submit]
  • 选项口径与 .28 既有挂载一致:用 hard 而非 lsf/home 的 soft——作业目录若遇 NFS 抖动, soft 可能静默返回错误数据,比「卡住」更危险;
  • projects_hosts 按节点 name 限定纳管范围(与既有 lsf.noexec_hosts 同款用法); 两台 master 因 MXJ=0 不接作业而不纳入,避免在管理节点引入 hard 挂载;
  • 同步更新 config/lsf_deploy.yaml.example 与 utils/config_validate.py 的 KNOWN_KEYS (否则配置校验会把新字段报成「幽灵字段」)。

步骤 3:备份节点 /etc/fstab(高危动作前置)

写入 fstab 属高危(写坏影响开机引导),动手前抓快照:

TS=$(date +%Y%m%d-%H%M%S)
for h in 25 26 27 28; do
  mkdir -p "projects_mount/backup/remote/192.168.31.$h/etc"
  ssh root@192.168.31.$h cat /etc/fstab \
    > "projects_mount/backup/remote/192.168.31.$h/etc/fstab.bak.$TS"
done

预期:4 个文件非空(.25–.27 各 19 行、.28 18 行)。清单见 backup/README.md。

步骤 4:预演(零副作用)

cd deploy/lsf
.venv/bin/python main.py -c config/lsf_deploy.yaml --dry-run --stage nfs

预期变更清单(实测):

- 192.168.31.25: mount_projects / opts_projects / fstab_projects
- 192.168.31.26: mount_projects / opts_projects / fstab_projects
- 192.168.31.27: mount_projects / opts_projects / fstab_projects
- 192.168.31.28: fstab_projects            ← 仅补 fstab,不重挂

失败判断:若 .28 出现 opts_projects,说明选项等价判定失效(会无谓重挂),先修实现体再执行。

步骤 5:执行阶段1

.venv/bin/python main.py -c config/lsf_deploy.yaml --stage nfs

节点侧等价命令(以实现体为准,逐项幂等):

# 写入 fstab(先剔除同名旧行,再追加)
ssh root@192.168.31.25 "awk -v p=/projects '\$2 != p' /etc/fstab > /tmp/fstab.ksf && \
  cat /tmp/fstab.ksf > /etc/fstab && rm -f /tmp/fstab.ksf"
ssh root@192.168.31.25 "echo '192.168.31.249:/data/nfs/projects /projects nfs \
  rw,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev 0 0' >> /etc/fstab"
# 挂载(高危:覆盖挂载点)
ssh root@192.168.31.25 "mkdir -p /projects && mount -t nfs \
  -o rw,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev \
  192.168.31.249:/data/nfs/projects /projects"

预期:状态: success,耗时约 61 s,日志无 mark_failed。 失败判断:任一台挂载失败 → 实现体即中止并返回失败(失败阈值 1 台);按第 7 章回滚后重跑。

六、验证

# ① 幂等复跑:应「状态已一致,无漂移(全跳过)」
cd deploy/lsf && .venv/bin/python main.py -c config/lsf_deploy.yaml --stage nfs

# ② 独立漂移检测:全阶段无漂移,退出码 0
.venv/bin/python main.py -c config/lsf_deploy.yaml --drift; echo "rc=$?"

# ③ 实机挂载与持久化
for h in 25 26 27 28; do
  ssh root@192.168.31.$h 'findmnt -n -o TARGET,SOURCE /projects; grep -c projects /etc/fstab'
done

# ④ fstab 语法校验(0 parse errors / 0 errors)
ssh root@192.168.31.25 "findmnt --verify"

实测结果(2026-10-07):

检查项 结果
幂等复跑 阶段1「状态已一致,无漂移(全跳过)」
--drift 全阶段无漂移,rc=0
4 台挂载 均 192.168.31.249:/data/nfs/projects(nfs4,rw),容量 1.8T / 用 38%,与 .28 一致
fstab 条目 4 台各 1 条
fstab 语法 .25:0 parse errors, 0 errors(2 条 warning 属 /mnt/lustre,非本次范围)

端到端作业验收(G1 描述的失败场景):

ssh root@192.168.31.28 "source /data/nfs/lsf/lsf/conf/profile.lsf; \
  echo 'hostname; df -h /projects | tail -1; ls /projects | head -3; echo PROJECTS_ACCESS_OK' \
  | bsub -o /data/nfs/lsf/.proj_probe.out -n 1"

实测:作业 1047 从 hpc-submit 提交,执行位 lsf-work-03,输出含 192.168.31.249:/data/nfs/projects ... /projects、cad/custom/design、PROJECTS_ACCESS_OK, DONE。

坑(本次实测):作业输出路径若写 /tmp/x.out,落在执行节点本地盘,提交节点读不到 (首次验证 cat 报文件不存在);输出须写共享路径(如 /data/nfs/lsf/、家目录 NFS)才能取回。

七、回滚

备份位置:projects_mount/backup/,台账见 backup/README.md(含部署器 4 个文件与 节点 4 份 fstab 快照)。

回滚步骤(先节点侧、后部署器侧):

# ① 卸载并还原 fstab(逐台)
for h in 25 26 27 28; do
  ssh root@192.168.31.$h "umount /projects"
  ssh root@192.168.31.$h "cat > /etc/fstab" \
    < projects_mount/backup/remote/192.168.31.$h/etc/fstab.bak.20261007-084852
done

# ② 回退部署器(实现体 + 配置 + 校验)
cd projects_mount
cp -p backup/deploy/lsf/stages/nfs_share.py.bak.20261007-084443 \
      ../deploy/lsf/stages/nfs_share.py
cp -p backup/deploy/lsf/config/lsf_deploy.yaml.bak.20261007-084443 \
      ../deploy/lsf/config/lsf_deploy.yaml
cp -p backup/deploy/lsf/utils/config_validate.py.bak.20261007-084443 \
      ../deploy/lsf/utils/config_validate.py

回滚后验证:findmnt /projects 无输出(4 台);--drift 恢复为「仅 lsf/home 两组受管」且无漂移。 注意:umount /projects 属高危——若 .28 上有进程正在使用该路径会失败,须先确认无占用。

八、风险说明

风险 说明与缓解
写坏 /etc/fstab 致开机异常 变更前抓 4 台快照(步骤 3);findmnt --verify 语法校验通过;回滚一条命令还原
无谓重挂中断 .28 服务 actimeo 等价判定保证 .28 只补 fstab 不重挂(dry-run 清单已核实)
hard 挂载遇宿主机故障卡住 与 .28 既有口径一致、且 .25–.27 的 /tools 已是 hard;作业目录用 hard 是刻意选择(避免 soft 静默返回错误数据)。宿主机 .249 与 Slurm 共用,其可用性由既有运维覆盖
纳管 hpc-submit 越出原范围 该节点原已有挂载但缺 fstab(重启即丢),补齐属修正既有缺陷;本次不重挂、不中断服务
与 Slurm 侧重复管理 节点 /tools、/mnt/lustre 由 slurm 侧管理,本次不触碰;/projects 只由 LSF 部署器管理,无交叉

来源:/home/rain/Documents/LSF/lsf_ins/projects_mount/SOP.md | 最后更新:2026-10-07 08:56(由 build/sync.py 同步,请勿在站点侧修改)