03 路线C 混合模式
Plan C 调度策略详解
Plan C 调度策略详解
抢占、优先级、动态迁移的实操细节。
一、优先级层级设计
平台上所有工作负载按 4 级优先级归入调度器:
| 级别 | 类型 | 抢占其他 | 被抢占 | 计费 |
|---|---|---|---|---|
| P0 | Plan A 长租客户(保障月租) | 抢 P2/P3 | 不可 | 定价 1.0× |
| P1 | Plan B 保障 API + 内部关键服务 | 抢 P2/P3 | 不可 | 定价 1.0× |
| P2 | Plan A 抢占实例 + 弹性训练 | 抢 P3 | 可(30s grace) | 3-4 折 |
| P3 | Plan B 抢占 API + 批量任务 | 无 | 可(无 grace) | 3-5 折 |
核心约束:
- P0 ≡ P1 权重相等(都是保障级)
- P0/P1 总量之和不能超过物理容量 80%(预留 20% 弹性)
- P2/P3 只跑在剩余容量上
二、调度状态机
客户请求 or 系统任务
│
┌──────▼──────┐
│ 路由层判断 │ 分优先级 P0-P3
└──────┬──────┘
│
┌──────▼──────┐
│ 容量检查 │
└──────┬──────┘
│
┌─────────────┼─────────────┐
│ 空闲卡足够 │ 空闲卡不足 │
│ │ │
直接分配 尝试抢占 排队等待
│
├─▶ 若为 P0/P1 → 抢占 P2/P3
├─▶ 若为 P2 → 抢占 P3
└─▶ 若为 P3 → 排队三、抢占流程(P0 抢 P2 示例)
T=0s P0 客户提交长租订单,指定 8 卡
T=1s 调度器发现容量不足
T=2s 查找可抢占的 P2 实例
T=3s 选中一台 P2 训练任务
T=4s 给该任务发 SIGTERM + PreemptionEvent
T=5s 任务保存 checkpoint 到 S3
T=25s 任务成功保存
T=30s 调度器强制 kill 剩余进程
T=35s 释放 8 卡
T=40s P0 客户开始使用关键点:
- 30 秒 grace period 是硬约束
- 未完成的 P2 任务时长不收费
- P2 客户可选 auto-restart(下轮 P2 时自动恢复)
四、动态容量灌注(空闲卡→MaaS)
当集群空闲卡数超过阈值时:
if idle_gpus > 5% total_capacity:
→ 自动扩容 Plan B 保障实例 (P1)
if idle_gpus > 15% total_capacity:
→ 扩容 Plan B 抢占实例池 (P3)
if idle_gpus > 30% total_capacity:
→ 触发市场化竞价(P2 Spot 拍卖)冷却机制(防抖动):
- 每次 scale 后至少等待 5 分钟才能再 scale
- 每小时最多 4 次 scale 操作
五、竞价市场设计(Plan A 抢占)
参与方:
- 平台底价(H800 每卡时 10 元)
- 客户出价(可高于底价)
- 空置率算法自动调价(30% 空置 → 底价 -20%)
匹配规则:
- 每 15 分钟撮合一次
- 出价高者先得
- 保底价:始终 ≥ 3 折
- 客户可预约(提前 24 小时锁价)
客户视角:
当前底价:H800 @ 12 元/卡时(-40% vs 标准价)
您的出价:15 元
状态:已匹配,运行中
预计中断时间:可能被 P0 抢占,历史平均运行 4.2 小时六、Plan B 抢占市场设计
针对 token 计费的抢占:
产品形态:
- API 请求头传
X-Priority: spot - 客户接受:3-4 折价格 + 可能 30s 中断 + 无 SLA
- 平台会:在容量紧张时优先杀这些请求
保护措施:
- 中断时已生成 token 不计费
- 客户可自动重试到保障级
- 每个 API key 每天 spot 用量有上限(防滥用)
七、跨产品线抢占
场景:Plan B P3 抢占实例被 Plan A P0 抢占
流程:
- P0 订单进来 → 需要 8 卡
- 集群里有 P3 MaaS 实例 → 优先抢占
- 通知 P3 客户:当前请求中断
- 30 秒内保存进行中的推理状态
- 释放 GPU 给 P0
客户视角:
- P3 客户看到:
request preempted, retry with X-Priority: standard - P0 客户看到:
resource allocated in 40s
八、公平性保证
避免出现:
- 单个 P2 客户被反复抢占(连续 3 次)
- 单个 P3 客户长期得不到资源(starvation)
- P0 客户长期挤占 P2 的正常配额
保护措施:
- P2 抢占次数上限:单实例 24 小时内最多被抢 3 次
- P3 排队保证:排队 >30 分钟自动升级到 P2 免费尝试
- P0/P1 硬上限:总容量 80%,超过部分即使排队也不给 P0
九、监控指标
| 指标 | 目标 | 告警阈值 |
|---|---|---|
| P0 SLA 达标率 | 99.9% | < 99.5% 告警 |
| P2 平均运行时长 | ≥ 4 小时 | < 2 小时告警 |
| P3 抢占率 | ≤ 10%/小时 | > 20% 告警 |
| P2 抢占次数 | ≤ 3/24h/实例 | > 5 告警 |
| 卡池整体利用率 | ≥ 80% | < 60% 告警 |
| 空闲卡阈值触发次数 | 稳定 | 频繁变动告警 |
十、失败案例预防
案例 1:AWS Spot Instance 频繁中断
- 教训:客户失去信任 → 我方绝不做"每小时被抢占 3+ 次"的产品
- 预防:抢占实例只卖训练客户和批量任务,明确"不适合在线服务"
案例 2:Kubernetes 优先级抢占死锁
- 教训:多个 P0 互相抢占 → 集群僵死
- 预防:P0/P1 总容量硬上限 80%,永远保留 20% 弹性
案例 3:GPU KV cache 残留导致数据泄露
- 教训:抢占实例结束后 KV cache 没清干净
- 预防:
nvidia-smi -r强制复位 + 清 shared memory
十一、SLA 承诺条款
P0 长租客户 SLA:
- 月度可用性 ≥ 99.9%
- 计划维护提前 7 天通知
- 故障赔偿:小时数 × 2 倍月单价
P1 MaaS 保障 API SLA:
- 月度可用性 ≥ 99.9%
- P99 TTFT ≤ 800ms
- P99 TPOT ≤ 60ms
- 未达标:按未达标时长退款
P2 / P3 无 SLA:
- 白纸黑字写明"可被抢占"
- 未完成 token / 卡时不计费
- 客户接受这个 tradeoff
十二、实施节奏
- 阶段 1(M1-M3):只做逻辑分区,无真实抢占;靠人肉运维决定谁跑哪
- 阶段 2(M4-M6):引入 Volcano + 优先级;先在测试集群跑
- 阶段 3(M7-M9):生产上线简单抢占(P0 抢 P3 单向)
- 阶段 4(M10-M12):完整抢占 + 竞价市场
关键教训:抢占调度绝不激进上线。每上一个新特性 dry-run 至少 30 天,看真实数据后再切换生产。