93 lines
5.3 KiB
Markdown
93 lines
5.3 KiB
Markdown
# 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>` 方式:
|
||
- 管理员 token 来自环境变量 `MVP_INTERNAL_TOKEN`(admin)。
|
||
- 业务用户 token 由管理员通过 API 下发并持久化到 SQLite。
|
||
- 用户隔离策略:
|
||
- 非管理员用户只能查询/取消/拉取日志 **自己的 task**;跨用户访问返回 404(不泄露存在性)。
|
||
- 训练产物落盘隔离:Ray job 目录统一写入 `/private/users/<user_id>/jobs/<ray_submission_id>/...`。
|
||
|
||
### 2) task_id / submission_id 带用户名
|
||
- 新任务 ID 规则:`mvp2-<user>-<workload>-<YYYYMMDD-HHMMSS>-<suffix>`
|
||
- Ray submission id(attempt)规则:`<task_id>--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/<uid>/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(或平台侧守护)并补齐健康检查与告警。
|
||
|