多主机数据面变更分批与失败阈值 — 规划设计¶
本文件是规划设计稿,本轮不含代码实现。评审通过后另开一轮实施与实测。
1. 现状与问题¶
编排入口 deployer.py 的 _run_steps() 目前是「按模块串行、模块内部遍历全部主机」:
| # | 问题 | 证据 |
|---|---|---|
| 1 | 目标格式化(mkfs.lustre)属数据面不可逆动作,却按配置一次性全量下发,无批次、无失败阈值 |
cmd_bootstrap / cmd_add_oss / cmd_add_ost / cmd_add_mdt 均直接 _run_steps(steps) |
| 2 | 失败即终止,但半程状态无自动收敛 | _run_steps 原文注释:「编排终止于 …(前序模块已变更的不会自动回滚)」 |
| 3 | 无批间健康确认,也无「该主机是否正被调度占用」的批前复核 | modules/target_format.py 按主机顺序遍历,无停顿与就绪判定 |
按 deployment-tool-engineering 的判据:变更落在数据面且不可逆时,未分批即阻断。当前工程处在该阻断状态。
2. 目标¶
- 多主机变更按批次推进,批次规模与批内并发可配置
- 批间做健康确认,判定用状态量而非固定
sleep - 失败容忍阈值可配置,超阈值即停后续批次,且「停 / 回滚」由配置决定、不留临场判断
- 单主机场景退化为一批,条款同样适用
3. 配置设计(拟新增 rollout 段)¶
rollout:
# 数据面变更(mkfs.lustre 等不可逆、清空类动作)
data_plane:
batch_size: 1 # 每批主机数;数据面固定逐台,0 视为非法
max_concurrency: 1 # 批内并发度
pause_after_batch_sec: 30 # 批间最小停顿,与健康确认共同生效
failure_threshold: 1 # 允许失败台数,超过即触发 on_threshold_exceeded
health_gate: true # 批间是否做健康确认
on_threshold_exceeded: abort # abort(停后续)| rollback(可恢复项回滚)
# 控制面变更(服务启停、配置下发等可重入动作)
control_plane:
batch_size: 0 # 0 = 不限(一批推完)
max_concurrency: 5
pause_after_batch_sec: 5
failure_threshold: 0
health_gate: false
on_threshold_exceeded: abort
config_validate 需同步新增校验:
data_plane.batch_size必须 ≥ 1,填 0 → BLOCK(数据面不允许全量下发)failure_threshold≥ 0,且不得 ≥ 该批主机数(否则阈值形同虚设)→ WARNon_threshold_exceeded∈{abort, rollback},其它值 → BLOCKhealth_gate: false且pause_after_batch_sec: 0→ WARN(等于无批间保护)
4. 实现接入点¶
4.1 关键取舍:分批的粒度¶
现有编排是「模块串行、模块内部遍历主机」。若要在「每台主机上跑完整模块链」的意义上分批,需要把编排改成「批次外层循环 × 主机子集」,并要求每个模块支持「仅处理指定主机子集」——多数模块当前从 config_data 自行取主机列表,需要新增 hosts 覆盖入口。这是一次较大的重构。
建议分两步走:
| 步骤 | 内容 | 风险 |
|---|---|---|
| 第一步(先行) | 只在含不可逆动作的模块(target_format)内部实现分批 + 阈值 + 批间健康确认;编排层把失败上报即可 |
低,不动全局编排 |
| 第二步(演进) | 把编排改为批次外层循环,模块统一支持 hosts 子集参数 |
中,需逐模块回归 |
4.2 数据面「回滚」的真实语义¶
mkfs.lustre 不可逆,磁盘级无回滚手段。因此数据面超阈值后的正确行为是:
- 停止后续批次(不做无谓推进)
- 输出「已变更 / 未变更」主机清单,标注不可逆项
- 对可恢复项(fstab、挂载单元、配置文件)执行回滚
- 保留现场,等待人工决策
即 on_threshold_exceeded: rollback 对数据面只能是「停 + 可恢复项回滚」,不能承诺磁盘级回滚。此语义必须写进 SOP 与日志,避免误判。
4.3 批间健康确认(用状态量,不用固定 sleep)¶
数据面每批完成后的就绪判据:
- 该批主机的 target 出现在
lctl dl且状态为UP(复用utils/lustre_state.get_online_targets,不另写判据) - MDT 侧能通过
lfs df看到新 target 的容量条目 - 未就绪则按
pause_after_batch_sec间隔重试,超过上限即判该批失败
4.4 批前可用性复核¶
每批开始前复核该批主机是否可动:
- Slurm:
scontrol show node <host>的State不含ALLOCATED/MIXED,或该节点已DRAIN - LSF:
bhosts <host>无运行作业 - 任一不满足即把该主机移出本批(不阻塞其它主机),并在报告中标记
5. 验收判据¶
| # | 判据 | 判定方式 |
|---|---|---|
| 1 | dry-run 输出按批分组,标注批次号与批内主机 | 人工核对输出 |
| 2 | 单批失败达阈值后,后续批次未启动 | 构造失败用例(如某批设备不可用) |
| 3 | 连续执行两次,第二次零变更、全跳过 | 幂等复跑 |
| 4 | 批间就绪判定使用状态量,无固定 sleep | 代码走查 |
| 5 | rollout 段字段全部被实现体引用,且有校验 |
配置校验输出 |
6. 未决项¶
- 当前拓扑不足以做真实失败演练:只有 1 个 OSS、1 个 MDT,无法验证「批间失败停止」。需先扩到 ≥2 台 OSS,或接受「单主机退化为一批」的降级验证(仅能验证单批失败即停)。
- 批次粒度需在实施前定稿:按主机分批(4.1 第一步)还是改为按模块分批。
- 阈值语义:用绝对台数还是比例;建议绝对台数(小规模集群更直观),大规模时再引入比例。
来源:
/home/rain/Documents/lustre_ins/tuning-fix-and-rollout-plan/batch-rollout-plan.md| 最后更新:2026-09-24 12:43(由build/sync.py同步,请勿在站点侧修改)