# MVP v2.5 迭代总结(已落地) 本文档总结 v2.5 在 v2.0/v2.1/v2.2…基础上完成的能力、实现点、验收方式与已知限制,便于回顾与后续版本迭代对齐。 ## 目标与边界 v2.5 的核心目标: - 引入 **User Management(用户管理)**:基于 token 的鉴权与任务级隔离(“只隔离 jobs”)。 - 引入 **Stateless Ray Node Pool(无状态 Ray worker 池)**:worker 不依赖平台下发 head 地址,自动发现并连接/自愈。 - 保持 **TaskSpec(v1.1 同款 YAML 格式)不扩展**:本迭代不支持 reward function、自定义 verl 代码等。 明确不做(v2.5 约束): - 不支持 TaskSpec 扩展(例如 `reward_fn_path` 等)。 - 不支持用户自定义 verl/hf/dataset 的隔离或自定义路径:**统一使用 `/private/common/...`** 的公共资源。 - 用户隔离仅覆盖 **任务与产物目录**(jobs),不覆盖 HF cache、datasets 等公共缓存。 ## 关键能力(对外表现) ### 1) 多用户鉴权与任务隔离 - API 仍使用内部 `Authorization: Bearer ` 方式: - 管理员 token 来自环境变量 `MVP_INTERNAL_TOKEN`(admin)。 - 业务用户 token 由管理员通过 API 下发并持久化到 SQLite。 - 用户隔离策略: - 非管理员用户只能查询/取消/拉取日志 **自己的 task**;跨用户访问返回 404(不泄露存在性)。 - 训练产物落盘隔离:Ray job 目录统一写入 `/private/users//jobs//...`。 ### 2) task_id / submission_id 带用户名 - 新任务 ID 规则:`mvp2----` - Ray submission id(attempt)规则:`--aNN`,因此自然包含用户名。 - 作用:Dashboard/日志/落盘目录可读性更强,便于按用户追踪和审计。 ### 3) “无状态 worker 池”与 head 地址发现 - Head 在共享存储写入 **head 地址文件**(例如 `head.json`),worker 通过 watchdog: - 轮询发现 head 地址 - 自动 `ray start --address ...` 加入集群 - 掉线后自动重连(watchdog 自愈) - 达成效果:在生产环境中,即使 worker 容器由算力平台创建(只提供 SSH 纳管),也能通过共享存储实现连接与自愈。 ### 4) 任务调度:队列 + Ray Job 提交 + 状态回传 - API 提交任务后进入 SQLite 队列,由后台 scheduler 逐个提交到 Ray(默认 `max_running_tasks=1`)。 - Scheduler 持续轮询 Ray job 状态并回写任务状态(RUNNING/SUCCEEDED/FAILED/CANCELED)。 - 资源不足的“可重试失败”处理: - 针对 VERL 的 fail-fast(`Total available GPUs ... is less than total desired GPUs ...`)或集群资源不足, 任务进入 `PENDING_RESOURCES` 并设置 `next_run_at`,按 `retry_interval_s` 周期重试。 ## 关键实现点(工程化落地) ### 存储与目录约定(容器内视角) - 共享根路径统一为 `/private`(对齐生产挂载)。 - v2.5 强约束:TaskSpec 的以下字段必须以 `/private/common/` 开头: - `code_path` / `train_file` / `val_file` - 公共目录(示例): - `/private/common/hf`:HF 缓存 - `/private/common/datasets`:训练数据(必要时通过 symlink 指向已有缓存目录复用下载) - `/private/common/db/mvp.sqlite3`:队列与用户信息(SQLite) - `/private/common/logs`:API / watchdog 日志 - `/private/users//jobs/...`:用户作业产物(隔离) ### Ray 拓扑与“head 不跑训练” - Head 启动为管理节点(CPU/GPU=0),避免训练任务落到 head。 - Worker 节点具备 GPU(示例:2 个 worker * 每个 4 GPU)。 - driver 通过 `entrypoint_resources`(例如 `worker_node: 1`)强制落 worker。 ### 部署脚本与可重复执行 提供完整脚本链路,覆盖: - 清理 legacy 环境、起停容器、启动 Ray head - head discovery publisher、worker watchdog 启动与状态检查 - 数据/模型/代码准备(幂等、可复用已有下载) - 启动 API server(并支持 RESET_DB) - API 方式连续提交 PPO/GRPO/SFT 并等待完成 代表性脚本: - `src/mvp/scripts/run_all_v25_api.sh`:v2.5 happy-path 端到端(含重建集群、准备资源、起 API、提交 3 类任务) - `src/mvp/scripts/run_e2e_v25_cases.sh`:在 happy-path 基础上增加鉴权/隔离/输入校验/资源不足/取消等用例 ## 验收与测试(已通过) ### 单元测试(本机 venv) - `.venv/bin/python -m pytest` - 覆盖率阈值:>= 90% ### 远端端到端(h1) - 在 `argus@h1:/home2/argus/infra/mvp/src/mvp/scripts` 执行: - `MVP_INTERNAL_TOKEN=mvp-dev-token RESET_DB=1 ./run_e2e_v25_cases.sh` - 结果:happy-path(PPO/GRPO/SFT)完成,且异常/边界用例验证通过(鉴权、跨用户隔离、输入校验、资源不足转 PENDING_RESOURCES、取消任务等)。 ## 已知问题与后续建议 - `max_running_tasks=1` 会让队列中的任务在前序 RUNNING 时保持 QUEUED,这在“资源不足”边界测试里需要显式清空/取消前序任务,或接受该行为作为设计的一部分。 - 当前仍是 SQLite 单点;后续若要 HA/水平扩展,可在 v2.6+ 引入更强的持久化与多副本(例如 Postgres/etcd)。 - API server / watchdog 目前以脚本方式守护;后续可进一步统一为 systemd/supervisor(或平台侧守护)并补齐健康检查与告警。