15 KiB
MVP Roadmap(V1 → V2 → … → 训练平台)
本文档在 specs/mvp/milestones.md 的草稿基础上做扩展与细化:把目标拆成可迭代的版本(MVP v1/v2/…),保证每个版本都能独立运行、可验证验收,并且在上一版本基础上演进。
总目标(North Star):产出一套**基于 Native Ray 集群(无 K8s 底座)**的训练平台,面向多用户,支持
verl各类训练/评测/Serving 工作负载,提升集群利用率,并通过可观测系统实现资源统计、监控告警,最终形成运维 SOP 并可接入运维智能体做自动化运维。
0. 关键原则(贯穿所有版本)
- 版本可独立运行:每个版本都能从“空环境”按文档跑起来(不依赖未来能力)。
- 验收可客观验证:每个里程碑必须有明确的 DoD(Definition of Done)与可复现步骤。
- 强制产物落盘:模型/数据/日志/ckpt 必须可追踪、可复用、可审计(基于共享存储/NFS)。
- Head 不参与计算:Head 只承担控制面(GCS/Dashboard/Job server),避免训练抢占控制面资源。
- 按 submission id 组织作业:作业输出目录与 Ray submission id 绑定,方便检索、回收、归档。
- “先把 RL 跑稳”,再扩 workload:先 PPO(已验证),再 GRPO/SFT/Serving。
0.1 里程碑总览(建议交付顺序)
| 版本 | 定位 | 关键交付 | 核心验收点 |
|---|---|---|---|
| v1 | 可复现实验闭环 | Ray 集群 + PPO 跑通 + 持久化 | driver 不在 head;产物落盘 |
| v1.1 | 实验工程化 | JobSpec 模板 + 新增 1 个 workload | 可回归、可定位、可扩展 |
| v2.0 | 服务化入口 | API + Ray Jobs SDK | API 提交/查询/停止可用 |
| v2.1 | 节点纳管 | SSH 注入 + 资源池/标签 | 节点上线/下线、gang 约束 |
| v3.0 | 平台雏形 | 队列 + 超时 + 最小多用户 | pending→running 自动调度 |
| v3.1 | 可扩展平台 | 自定义代码/reward + 多版本 | 多版本并存、插件可用 |
| v4.0 | 可运营平台 | Prom/Grafana + W&B | 资源核算/告警/归档 |
| v4.1 | 可交接平台 | SOP + 自动化运维接口 | 非开发可按 SOP 运维 |
| v5.0 | 长期形态 | Serving + Pipeline | 训练→发布推理闭环 |
1. 当前基线:MVP v1(已完成/已验证)
1.1 目标
在单机(或同一宿主机)用 3 个容器跑通:
- Ray head(无 GPU,CPU=0/GPU=0)
- 2 个 Ray worker(每个 4 GPU)
- 通过 head 上的
ray job submit提交verlPPO(total_epochs=1) - 通过 entrypoint 自定义资源强制 driver 在 worker 上
- 数据/模型/日志/ckpt 全部持久化
1.2 交付物(repo 中已存在)
- 脚本与 compose:
src/mvp/v1/ - 行动与验收文档:
specs/mvp/v1/v1_action.md - 共享目录约定:
shared/datasets、shared/hf、shared/jobs等(与 NFS 对齐)
1.3 验收口径(摘要)
ray job list的driver_info.node_ip_address∈ worker IP,且 ≠ head IP- 训练输出落在
/mnt/shared/jobs/<submission_id>/... - checkpoint 按
save_freq产生(避免爆磁盘)
2. MVP v1.1(Hardening + 多 workload 可行性验证)
目标:把 v1 从“实验脚本”升级成“可长期回归的最小系统”,并验证更多 workload 的可行性边界。
2.1 主要能力
- Workload 扩展(可选顺序):
- PPO(回归金标)
- GRPO on Ray(可运行验证)
- SFT on Ray(可运行验证:
llamafactory或verl相关 SFT 路径)
- 作业模板化(最小实现):
- 统一 JobSpec(YAML/JSON)描述:workload 类型、资源(nnodes/n_gpus_per_node)、数据、模型、输出目录、超时
- 仍然用
ray job submit,但把 entrypoint 组装逻辑标准化
- checkpoint 策略与磁盘保护:
- 默认
save_freq≥ 10(或按训练总 steps 的比例) - 明确保留策略(至少提供“保留最后 N 个 ckpt”的配置建议/脚本)
- 默认
- “失败可定位”:
- 统一收敛日志入口(Ray job logs + hydra 日志目录 + 关键参数快照)
- 失败时能定位:是资源不足 / NCCL / 数据 / 模型 / 配置错误
2.2 验收(DoD)
- 同一套脚本在同一台机器能连续跑 3 次 PPO 回归,产物目录不互相覆盖
- 至少新增 1 个 workload(GRPO 或 SFT)可以跑通 “启动→训练→落盘” 闭环
- 作业目录内包含:
config/submit_cmd.txt(或 job spec 快照)logs/(可追踪)checkpoints/(按策略生成)
3. MVP v2.0(Control Plane 服务化:API + Ray Jobs SDK)
目标:从“人跑脚本”升级为“服务提交任务”。依然是 Native Ray 集群,但引入一个最小控制平面服务。
3.1 系统形态
- Control Plane(建议部署在 head/CPU 机器):
- FastAPI 服务(REST)
- Job 管理:用 Ray Jobs Python SDK 提交/查询/停止(不再依赖 CLI 文本解析)
- 节点视图:读取 Ray state(nodes, actors, placement groups)
- Data Plane:
- 仍然是预先启动的 worker 节点加入集群(先不做 SSH 动态纳管也可)
3.2 API(MVP 级别)
POST /v1/jobs:提交 JobSpec(ppo/grpo/sft)GET /v1/jobs:列表(含状态、资源、开始/结束时间)GET /v1/jobs/{id}:详情(含输出目录、driver node)POST /v1/jobs/{id}:stop:停止作业
3.3 验收(DoD)
- API 提交 PPO,返回 submission id;输出目录为
/mnt/shared/jobs/<submission_id>/... - API 查询 job 状态与 driver node(必须是 worker)
- 停止 job 后,资源释放、状态可见
4. MVP v2.1(SSH 纳管 + 资源池 + Gang 约束)
目标:对齐你草稿里“SSH 纳管”的约束与需求:控制面能纳管 GPU 节点,形成可运营的资源池。
4.1 节点纳管(SSH Provisioner)
- 控制面保存 NodeSpec(ip/user/port/labels/gpu_count)
- 通过 SSH 执行:
ray start --address=<head>:6379 --resources=...ray stop(drain/下线)
- 维护节点状态机:
pending → online → draining → offline
4.2 资源池与 gang(All-or-nothing)
- 资源池最小模型:
- pool 标签(如
pool_a、h20、ib_domain_1) - 提交 job 时指定 pool 约束
- pool 标签(如
- Gang 约束(MVP 实现方式):
- job spec 明确
trainer.nnodes+trainer.n_gpus_per_node - 提交前检查 Ray 可用资源是否满足,不满足则进入 pending 队列(见 v3.0)
- job spec 明确
4.3 验收(DoD)
- 通过 API 注册 2 个 worker(SSH 注入 ray start)后,
ray status可见节点上线 - 通过 API 下线节点,节点被标记不可调度且不再分配新 job
- gang 不满足时 job 不提交(或提交后一直 pending),满足后可运行
5. MVP v3.0(调度与多用户:队列 + 超时 + 最小权限)
目标:平台开始“像个平台”:多用户、队列、超时、审计。仍然不做复杂配额/公平调度。
5.1 作业队列(简单但可用)
- FIFO 队列:无优先级
- “资源满足就调度”:谁先满足谁先跑(可接受非严格 FIFO)
- job 超时:Ray 原生不支持统一 timeout(草稿已指出),因此控制面需:
- 记录 start_time
- 定期扫描超时 job →
stop
5.2 多用户最小闭环
- 认证(MVP):token 或 basic auth(先不做复杂 RBAC)
- 归属与隔离(文件层):
/mnt/shared/users/<user>/datasets//mnt/shared/users/<user>/models//mnt/shared/jobs/<submission_id>/记录 user/metadata
5.3 验收(DoD)
- 2 个用户可各自提交 job,能看到自己的 job 列表与输出目录
- 超时策略可触发(模拟短 timeout),job 被停止且状态标记为 timeout
- 队列在资源不足时保持 pending,资源释放后自动运行
6. MVP v3.1(可扩展性:自定义代码/Reward、多版本 VERL)
目标:把“平台内置 workload”升级成“用户可提交自定义代码与 reward”,并支持多版本并存。
6.1 自定义代码提交(最小实现)
两种方式二选一(建议先做 A):
- A:
working_dir指向 NFS 上的代码快照目录(用户自己准备/上传) - B:上传 zip(控制面落到 NFS 并解压为 code snapshot)
6.2 多版本 VERL 并存
约束前提:基础镜像保持同一个(生产环境容器由算力平台创建时已固定镜像标签)。
目标:在同一 Ray 集群内,不同 job 可以使用不同版本的 verl(例如不同分支/commit 或用户魔改版)。
已确认优先方案(A):必须通过 Ray Job 的 runtime_env.env_vars 透传 PYTHONPATH,让 job 粒度优先 import 指定代码快照。
建议方案(以 NFS 为中心,最小可行实现):
- 在共享存储上以“不可变快照”的方式存放代码版本(推荐 commit hash 命名):
${SHARED_ROOT}/common/code/verl/<commit>/...${SHARED_ROOT}/users/<user>/code/verl/<commit>/...(用户魔改版)
- JobSpec 增加
code_path(指向上述目录),控制面在提交 job 时注入(必须走 runtime_env):runtime_env.env_vars.PYTHONPATH = "<code_path>:$PYTHONPATH"(把 code_path 放最前面,确保 import 优先级)
示例(概念性,实际以 ${SHARED_ROOT} 为准):
CODE_PATH="${SHARED_ROOT}/common/code/verl/<commit>"
ray job submit \
--address="http://127.0.0.1:8265" \
--submission-id="<submission_id>" \
--runtime-env-json='{"env_vars": {"PYTHONPATH": "'"${CODE_PATH}"':$PYTHONPATH"}}' \
-- \
python3 -m verl.trainer.main_ppo ...
需要验证的关键点(作为 v3.1 的 DoD 之一):
- 同时运行两个 job:
- jobA 使用
<commitA>,jobB 使用<commitB> - 互不影响,且各自训练/日志/ckpt 正常
- jobA 使用
- job 粒度是否能做到“依赖隔离”(至少做到
verl版本隔离;第三方依赖冲突可先假设镜像内一致)
备注:当前 v1 的做法是容器内全局
pip install -e /workspace/verl,这会让所有 job 默认使用同一份verl。要实现多版本并存,必须让 job 的 import 优先使用code_path(或为每个 job 单独创建 venv/安装 wheel;后者更重,建议后置)。
6.3 自定义 reward function
- JobSpec 支持
reward_fn_path(Python 模块路径) reward_fn_path可指向共享存储中用户自定义代码目录(例如${SHARED_ROOT}/users/<user>/code/...)- 约束:代码必须在 job runtime 中可 import(由
working_dir/PYTHONPATH或 runtime_env 保障)
- 约束:代码必须在 job runtime 中可 import(由
- 控制面校验模块可导入(basic lint/安全白名单可后置)
6.4 验收(DoD)
- 同时运行两个 job:使用不同的
verl代码版本(或用户魔改版本),互不影响 - 用户可在 JobSpec 中替换 reward function 并跑通一个最小训练闭环
7. MVP v4.0(可观测性:Prometheus/Grafana + W&B 集成)
目标:平台可运营:能回答“谁在用多少资源、跑了多久、利用率如何、是否空占 GPU”。
7.1 指标与监控
- Ray 指标接入 Prometheus(节点/任务/actor)
- GPU 指标:nvidia exporter 或 DCGM exporter
- Dashboard:Grafana(至少 3 张核心面板)
- 集群总 GPU/CPU 使用率、空闲率
- 每 job 的 GPU 时间、峰值显存、运行时长
- 节点健康(心跳/掉线)与告警
7.2 W&B(或等价)集成验证
- 最小可行:单机 self-host W&B server 可用性验证
- JobSpec 支持启用/关闭 W&B,并传入 project/run name
7.3 验收(DoD)
- Grafana 上能看到集群与 job 资源视图
- 某个 job GPU 利用率异常(模拟)能触发告警规则(邮件/IM/日志即可)
- W&B 指标能按 job 维度归档(至少 PPO 能上报)
8. MVP v4.1(运维化:SOP + 自动化运维接口)
目标:把平台变成“可交接”的系统:运维动作标准化,并为智能体留出接口。
8.1 SOP 与自动化入口
- SOP 文档:
- 节点上线/下线
- 故障定位(Ray session、Ray job、NCCL、OOM)
- 资源回收(停止 job、清理 ckpt)
- 自动化接口(最小):
/v1/ops/drain_node/v1/ops/restart_ray_head(谨慎:需要保护与权限)/v1/ops/cleanup_job_artifacts
8.2 验收(DoD)
- 按 SOP,非开发人员可完成一次“节点上线→跑任务→下线→清理”
- 自动化接口至少能完成 1 个高频动作(如清理/停止/下线)
9. MVP v5.0(Serving 与 Pipeline,偏长期)
目标:训练-部署一体化:支持 model serving,并在平台内串联训练→评测→发布。
9.1 Serving
- Ray Serve(或等价)部署模型推理服务
- Serving 与训练共用模型库与权限(按 user/project)
9.2 Pipeline(草稿里标为高级)
- Pipeline 是对多个 job 的封装(训练→merge→eval→publish)
- 可先实现最小 DAG(两步串联)作为验证
9.3 验收(DoD)
- 训练产物一键发布为一个可访问的推理 endpoint
- Pipeline 能自动串联并产出最终 artifact(可回滚/可追踪)
10. 并行技术验证(建议尽早做)
这些属于“跨版本”风险项,建议在 v1.1 ~ v2.0 期间尽早做:
10.1 网络(IB / RoCEv2)
- 确认环境是否支持 IB(H100)或 RoCEv2(H20)
- 跑最小 NCCL 通信验证(all-reduce / bandwidth)
- 将必要的 NCCL 环境变量注入到 job runtime_env
10.2 Ray + 多节点容器约束
- 多容器同宿主机时的 Ray node_ip/临时目录冲突规律(已踩坑,需固化规范)
- 端口范围与防火墙策略(Ray worker 端口、dashboard、metrics)
11. 已确认的约束与假设(来自讨论结论)
这些会直接影响 v2.1(SSH 纳管)与后续多用户/存储设计:
- 最终形态仍以“每节点容器”运行(不是裸机 systemd)。
- H20 开发环境:我们可在宿主机用
docker compose自建容器,并通过 SSH 进入容器调试/纳管。 - H100 生产环境:容器由算力平台创建/回收;平台侧控制面只能 SSH 进入这些容器 做纳管(执行
ray start/stop、注入 env 等)。
- H20 开发环境:我们可在宿主机用
- 认证:内部 token 即可(MVP 阶段不对接 SSO)。
- 存储:只考虑 NFS。
- 开发环境:NFS/共享目录可通过宿主机 bind mount 提供给容器。
- 生产环境:所有容器挂载相同 NFS,容器内共享根路径为
/private/(需要在实现时把“共享根路径”做成可配置项,而不是写死/mnt/shared)。
- 网络拓扑约束:暂不做按 IB 域/机架/拓扑的强约束调度(第 10.1 仍需验证 IB/RoCE 是否可用与配置方式,但调度不引入拓扑维度)。
- 共享目录分层:在
users/<user>/...之外增加一个可读写的common/目录用于共享数据/模型/代码:${SHARED_ROOT}/common/datasets/${SHARED_ROOT}/common/models/${SHARED_ROOT}/common/code/- 权限(MVP):先默认“所有内部 token 用户可读写”,后续再细化只读/受控写。
12. 仍需你确认/讨论的问题(剩余不确定项)
runtime_env.env_vars注入对“子进程/训练框架内部启动进程”的覆盖范围是否足够?- 需要确认
verl/sglang等子进程是否继承 driver 的环境变量(通常会继承,但建议在 v3.1 验收时明确验证)。
- 需要确认