已关闭
[RFC]: 推理大EP场景下支持DP域缩容运行 #575
yilunh创建于  9月8日关闭于  9月17日
yilunh
9月8日 创建

摘要

部分 DP rank 失效时,Motor 不再默认整实例隔离 / 重拉起 / Scale P2D。在引擎 FT、external-lb、EPLB 冗余专家等条件满足时,Controller 只移除故障原始 DP rank,存活 rank 重建通信域后继续服务,Coordinator 只消费投影后的服务视图。

1. 动机

当前容错主路径是:故障 → 隔离实例 → EngineRelaunch / Pod 重调度 / Scale P2D。对「单卡或单 DP rank 死、其余 rank 仍可集体恢复」的场景过重,恢复时间长,健康 Pod 被一起扰动。

DP 缩容要解决:

  1. 硬件(MindCluster)与软件(vLLM FT status)两路证据,统一落到原始 DP rank。
  2. 只对权威待删 rank 做累计缩容;失败立刻走原重配置,不重试 apply。
  3. 缩容窗口内摘流,成功后只发布存活 endpoint;可选回收已收空 Pod。

2. 架构结论

角色 做什么 不做什么
FaultManager 聚合软硬件故障、判断首达来源与 5 秒相关性窗口、构建 ScaleDownContext、选择并启动策略、失败后升级 不执行缩容事务、不解释引擎 Mask、不用硬件映射 rank 直接生成 apply 参数
DpScaleDownStrategy 单轮事务;内部执行 FtGate、拓扑校验、guard、状态等待、摘流、一次 apply、轮询、commit/abort 与发布 不补发、不换 request_id,不维护真实专家拓扑
FtRuntimeStore 阶段、generation、dead_committed、门禁/引擎快照 不改 Instance.endpoints
ServingOverlay DEL 摘流 / ADD·SET 过滤已提交死 rank 不改权威拓扑
NodeManager EngineFtService 本 Pod 选 endpoint、查 status、apply、freeze suicide、finalize 不做跨 Pod 决策
Coordinator 路由投影后的实例 不参与容错决策
引擎 通信域重建 / EPLB 与算子兼容性的最终可行性 不驱动 Motor 策略升级
┌──────────────────────────── 故障感知 ────────────────────────────┐
│                                                                  │
│  MindCluster 硬件故障信息                  vLLM FT status         │
│            │                                      │              │
│            ▼                                      ▼              │
│  Motor ResourceMonitor              NodeManager EngineFtManager  │
│            │                                      │              │
└────────────┴──────────────────┬───────────────────┴──────────────┘
                               ▼
┌──────────────────────── Motor Controller ────────────────────────┐
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │ FaultManager                                               │  │
│  │ • 聚合故障、冻结 ScaleDownContext                           │  │
│  │ • 决策优先级:快恢 → DP 缩容 → 原有 fallback                 │  │
│  │ • 选择并启动策略,不执行 apply                               │  │
│  └────────────────────────────┬───────────────────────────────┘  │
│                               ▼                                  │
│                   FaultManager FT 快照分类                        │
│          ┌────────────────────┼────────────────────┐             │
│          ▼                    ▼                    ▼             │
│  全 U、无 D             完整 U+D             不完整/全 D          │
│          │                    │             等待/整实例重配置     │
│          ▼                    │                                  │
│  FastRecovery.is_applicable() │                                  │
│    ├─ true → 执行快恢          │                                  │
│    │           ├─ 成功 → 结束  │                                  │
│    │           └─ 失败 → 整实例重配置                              │
│    └─ false → 等待 D/超时重配置 │                                  │
│                               ▼                                  │
│  ┌────────────── DpScaleDownStrategy:单轮事务 ───────────────┐   │
│  │  FtGate(内部步骤)                                        │   │
│  │      ↓                                                    │   │
│  │  候选 rank 与 DP/Pod 拓扑校验                              │   │
│  │      ↓                                                    │   │
│  │  guard 全部参与的 NodeManager(request_id + lease)        │   │
│  │      ↓                                                    │   │
│  │  循环查 survivor status → 摘流 → 一次 apply → 轮询         │   │
│  │      ├─ 成功:finalize(commit) → 发布存活视图              │   │
│  │      └─ 失败:finalize(abort) → 返回 FaultManager fallback │  │
│  └───────────────┬─────────────────────────────┬─────────────┘  │
│                  │                             │                │
│                  ▼                             ▼                │
│       FtRuntimeStore                   ServingOverlay           │
│       phase / dead_committed           DEL 摘流                 │
│       gate / engine_statuses            ADD/SET 存活视图         │
│                                                                 │
│  缩容失败                                                        │
│             └────────► InstanceReconfiguration                  │
└──────────────────┬─────────────────────────────┬────────────────┘
                   │                             ▼
                   │                         Coordinator
                   ▼
       NodeManager EngineFtManager
                   │
                   │ GET status / POST apply
                   ▼
             vLLM FT API
                   │
                   ▼
          vLLM-Ascend / vLLM 数据面
          通信域重建 / EPLB / 最终可行性判断

图中的 FaultManager → DpScaleDownStrategy 不是绕过接口的组件调用,也不是另一条 apply 通道,只表示策略中心完成优先级判断后选择并启动该策略。全 active DP 均为 UNHEALTHY 且无 DEAD只是调用 is_applicable() 的必要非充分条件;当前占位返回不适用。快恢内部协议可独立演进,但失败只能进入整实例重配置。FtGate 不是独立服务或独立组件,而是DpScaleDownStrategy.execute() 内部的第一阶段;它被画进事务边界,是为了表达“门禁失败直接回原 fallback”。

职责边界:

  • motor/controller/fault_tolerance/dp_scale_down.py:领域模型(FtPhase、ScaleDownContext、FaultNormalizer、TopologyResolver、FtRuntimeStore)
  • motor/controller/fault_tolerance/strategy/dp_scale_down.py:有副作用的单轮执行器
  • motor/node_manager/core/engine_ft_service.py + 四条 NM API:本机引擎适配

3. 状态机与服务视图

3.1 阶段

DISABLED → NORMAL → DECIDING → WAITING_ENGINE_FAULT → SCALING_DOWN → POST_SCALE_CLEANUP → SCALED_DOWN_RUNNING ,失败进入 RECONFIGURING,再走冻结的原 fallback。

NORMAL
  │ 权威故障候选
  ▼
DECIDING
  │ 门禁、拓扑、guard 通过
  ▼
WAITING_ENGINE_FAULT     (首轮已 apply-ready 时可跳过,仍停在 DECIDING)
  │ survivor 全部 apply-ready
  ▼
SCALING_DOWN
  │ 引擎全部恢复 healthy
  ▼
POST_SCALE_CLEANUP
  │ commit 并发布成功
  ▼
SCALED_DOWN_RUNNING
  │ 新一轮 survivor 故障
  └──────────────────────────────────────► DECIDING

DECIDING              ──门禁/拓扑失败───────────┐
WAITING_ENGINE_FAULT  ──状态异常/超时───────────┼──► RECONFIGURING
SCALING_DOWN          ──failed/查询异常/超时────┘       │
                                                        ▼
                                                  原始 fallback

事务窗口(DECIDING / WAITING_ENGINE_FAULT / SCALING_DOWN / POST_SCALE_CLEANUP)抑制旧的 partial-loss 整实例 shutdown。SCALED_DOWN_RUNNING 心跳只忽略 dead_committed;新 stale survivor 仍进正常故障决策。RECONFIGURING 不保护。

3.2 权威拓扑 vs 服务视图

Instance.endpoints 启动后不可变。存活集合只由 runtime 表达:

serving = original_dp_ranks - dead_committed - pending_removed_ranks

提交前 pending 不并入 dead_committed。连续缩容仍用原始编号,例如 {0,1,2,3} → {0,2,3} → {0,2},禁止把 2 改名为 1。

ServingOverlay:

  • 摘流:Coordinator DEL 当前已发布视图(连续轮已不含既往 dead_committed,避免 identity 校验失败)
  • 成功:ADD 只含存活 endpoint;EventPusher 的 READY/RESUME/周期 SET 走同一投影,防止全量刷新把死 rank 加回
  • can_serve 仅在 NORMAL / SCALED_DOWN_RUNNING 且 serving_published=true

4. 故障归一化

4.1 软件

对齐 vLLM:healthy / unhealthy / dead。executor 已死上报 DEAD → 权威待删 rank;peer 感知故障上报 UNHEALTHY → 仅这些 survivor 可收 apply。UNHEALTHY 本身不是待删集合。Mask 只观测,不反推 rank。

上游 vLLM external-LB 模式把 engine_ranks_managed 初始化为全局 dp_rank,并以该值生成engines[].id。因此 Motor 的请求目标 Endpoint.id 和响应 engines[].id 必须严格相等:缺少目标 ID、出现重复/未知 ID,或仅返回一条但 ID 不匹配,都按协议失败进入原 fallback,不能把本地 rank 当全局 rank 做隐式兼容。EngineFtManager 按其管理的 Endpoint ID 选择并校验对应条目,
同时用该全局 ID 去重上报;轮询上报路径和事务查询路径必须遵守同一身份契约。

4.2 硬件

node + 该实例在节点上的全部 pod_ip + npu_name 联合匹配 Endpoint.device_infos.device_id,endpoint id 即原始 DP rank。同一故障在各 Pod 的映射先取并集;空卡名映射该节点上属于该实例的全部 DP;未知卡名格式不猜测,走原策略。多卡同 fault_code 用 (fault_code, npu_name[, node_name]) 区分。

可映射的 L4–L6 推迟旧 separate_instance,由缩容策略同步摘流,避免 EventPusher 异步 DEL 与成功 ADD 竞态。形成匹配 U+D 后缩容失败直接整实例重配置;无法完整映射或实例非 ACTIVE 时不进入相关性等待,继续原 ScaleP2D / 重配置路径。

4.3 优先级(有限、不循环)

故障进入 FaultManager
        │
        ├─ TokenReinference 等既有更高优先级特殊策略
        │
        ▼
归一化当前 active DP 的 FT 快照
        │
        ├─ 全部 UNHEALTHY、无 DEAD
        │        │
        │        ▼
        │  EngineFastRecoveryStrategy.is_applicable(...)
        │        ├─ true  → 执行快恢
        │        │             ├─ 成功 → 结束
        │        │             └─ 失败 → 整实例重配置
        │        └─ false → 等待 DEAD;收集超时则整实例重配置
        │
        ├─ 完整 UNHEALTHY + DEAD(至少各一个,可有多个 DEAD)
        │        └─ 快恢不适用 → DpScaleDownStrategy
        │                              ├─ 成功 → 缩容运行状态
        │                              └─ 失败 → 整实例重配置
        │
        ├─ 全部 DEAD / 快照不完整且超时 → 整实例重配置
        └─ 快照不完整且未超时 → 等待后续 FT 上报

快恢执行中不可被缩容抢占,且快恢失败后直接整实例重配置,不再尝试 DP 缩容。全 active DP 均为UNHEALTHY 且不存在 DEAD,只是调用快恢 is_applicable() 的结构性前置条件,不等价于一定可快恢,当前仅占位实现;设备类型、错误码等充分条件由快恢实现自行判断。当前 is_applicable() 恒为 false,因此只会继续等待DEAD,或在软件状态收集超时后进入整实例重配置。

DP 缩容只接受完整的 UNHEALTHY + DEAD 组合:DEAD 是权威待删除 rank,UNHEALTHY 是可接收 apply的 survivor;两类集合并集必须覆盖当前全部 active DP。硬件映射结果只用于验证 FT 框架是否感知到了同一故障,不直接进入 removed_dp_ranks。连续缩容没有人工轮数上限,天然受“至少存在一个新 DEAD 且至少保留一个 survivor”的拓扑约束。整实例重配置复用terminate_instance_for_recovery(),不走 PodLifecycle。Relaunch 成功保留 dead_committed;整实例重建成功清空缩容历史。

4.4 Controller 故障感知入口与相关性计时

Controller 不直接轮询 vLLM business port。当前故障信息通过以下入口汇聚到 FaultManager:

  1. 引擎 FT 状态:NodeManager EngineFtManager 周期查询当前角色引擎的 GET /v1/fault_tolerance/status,将新的 UNHEALTHY / DEAD 状态通过 POST /controller/report_software_fault 上报。
  2. 引擎进程死亡:NodeManager Daemon 通过本地 ProcessSupervisor 发现 EngineCore / executor 子进程退出后,独立于 EngineFtManager 的状态响应上报 ENGINE_DEAD + endpoint_id。因此,即使 FT status 接口已不可访问,只要本地进程死亡监控仍工作,Controller 仍可取得软件 DEAD 候选。
  3. 硬件与节点故障:Motor Controller 内的 ResourceMonitor 消费 MindCluster / Ascend Device Plugin 暴露的 Node 与 ConfigMap 故障信息,更新卡级或节点级硬件故障。这里的 ResourceMonitor 是 Motor 的监听适配组件,不是 MindCluster 内部组件。
  4. NodeManager 心跳与 partial-loss:用于判断实例 / Pod 生命周期和 endpoint 集合完整性;它本身不凭缺失 endpoint 猜测 removed_dp_ranks,不能单独启动 DP 缩容。只有后续软件 DEAD 或可映射硬件故障形成权威 rank,才进入缩容事务。

故障上报写入 FaultManager 后会刷新实例故障级别并 notify_all() 唤醒策略中心;策略中心仍以strategy_center_check_interval(默认 10 秒)做兜底扫描。FaultManager 分别记录硬件首达时间、软件状态收集起点,以及每个 rank 首次出现 UNHEALTHY / DEAD 的时间;这些是进程内相关性证据,不写入etcd。软硬件处理规则如下:

软件 FT 先到
  └─ 直接按 FT 快照决策,不等待硬件:
       全 UNHEALTHY → is_applicable;完整 U+D → 缩容;不完整 → 收集/超时

可映射 L4-L6 硬件故障先到
  ├─ 映射 DP 已在 dead_committed → 标记该硬件故障已处理,不启动恢复
  ├─ 5 秒内出现匹配的 FT 快照
  │    ├─ 全 UNHEALTHY → is_applicable
  │    └─ 完整 U+D,且硬件映射 DP 在 DEAD 中 → 缩容
  └─ 5 秒仍未出现匹配 FT 感知 → 整实例重配置

硬件故障无法映射到 DP / 实例非 ACTIVE
  └─ 不进入相关性等待,保持原 ScaleP2D / 重配置策略

5 秒 hardware_ft_correlation_window_sec 是“硬件先到后等待 FT 框架感知”的 Controller 决策窗口,不是 apply 重试,也不等价于 DpScaleDownStrategy 的恢复 deadline。只有 FaultManager 已取得完整 U+D快照并选择缩容后,策略才 guard NodeManager 并进入 dp_scale_down_config.execution_deadline_sec:它会重新查询当前状态,吸收尚未进入首份上下文、但已在引擎侧变为 DEAD 的 rank,将其从 survivor 移入本轮累计待删集合;剩余 survivor 必须全部为可 apply 的 UNHEALTHY。若 survivor 仍 HEALTHY / recovering 则只轮询,若 survivor 为空、出现失败状态、查询异常或 deadline 到期则本轮失败并整实例重配置。

EngineFtManager 只在引擎首次 readiness 成功后启动,默认每 1 秒轮询一次。进入运行期后,status 接口首次超时或连接失败即作为该 Endpoint 的 DEAD 证据上报。

5. 单轮事务

  1. 去重:本轮候选已是 dead_committed 子集且阶段已是 SCALED_DOWN_RUNNING → 成功返回;否则失败。
  2. FtGate:enable_dp_scale_down、引擎 FT、ft_capability.scale_down_supported、external-lb、关闭引擎 auto recovery、enable_eplb 且 num_redundant_experts > 0、至少一名 survivor。Motor 不把 fused MC2 作为门禁,也不把冗余专家数当成可删 DP 预算;算子与实际专家槽位是否支持本轮缩容由引擎在 apply 后最终判断。
  3. 组 NodeManager:按完整 endpoint 拓扑分组。可路由 survivor 走 status/apply;仅 headless 的参与者只 guard/finalize。拓扑缺失失败封闭。
  4. guard:对全部参与 NM(含仅 headless / 仅死 rank 的 Pod)POST /node-manager/fault-tolerance/guard,携带本轮 request_id 与内部 lease_sec。NM 记录当前事务主;同一 id 可续租,另一 id 在冻结未到期时拒绝。lease 由两段 recovery 窗口 + HTTP/poll 余量算出,不是客户开关。
  5. 确认 apply-ready 并吸收迟到 DEAD:仅向当前可路由 survivor 查 status。若某 survivor 已变为 dead,将其加入本轮累计待删集合、重建 NodeManager 分组并继续检查;剩余 survivor 必须全部为 unhealthy 且无 ft_state 才可下发。healthy 或 unhealthy+recovering 只轮询不下发;failed、缺失、引擎 id 与 Endpoint.id 不匹配、全部 rank 均 DEAD 或 deadline 到期则失败。此阶段可能进入 WAITING_ENGINE_FAULT,但不重复 apply。
  6. 摘流 → 一次 apply:同一 request_id,body 含累计 removed_dp_ranks 与 dp_master_ip=min(survivor).ip;dp_store_port 由 NM 本地补齐。HTTP 202 只表示接收。任一 NM 未接受即本轮失败。
  7. 轮询成功:全部 survivor healthy 且 ft_state 空 → finalize(commit)(按 request_id 校验,否则视为 stale)→ Daemon 把 retired ranks 写入心跳 / EngineFtManager / 进程死亡过滤 → 写入累计 dead_committed → 若开了扩容开关则 PodLifecycle.stop_recyclable_pods → SCALED_DOWN_RUNNING → ServingOverlay.publish。
  8. 失败:finally 里对未 commit 的 NM 做一次 finalize(abort)(过期/错 id 会被 NM 拒绝,避免解冻新事务),再交给冻结 fallback。

提交后的失败语义:

  • finalize(commit) 表示引擎缩容结果已经提交,后续 Controller 状态持久化、Pod stop 或 Coordinator 发布失败均不回滚引擎,也不重放 apply。
  • Coordinator 发布失败时保留 SCALED_DOWN_RUNNING、serving_published=false 和 last_error,此时 can_serve=false;后续由 EventPusher 的 SET 使用 ServingOverlay 收敛,发布成功后再恢复可服务。
  • stop_recyclable_pods 是 best-effort 的一次性通知。stop 失败不改变缩容成功结论、不由 Motor 重试,Pod 的最终回收和补充由 MindCluster 负责。

策略抢占:更高优先级故障替换进行中的策略时,FaultManager 先 stop(),并同时等待逻辑 is_finished() 与执行器 Future.done(),避免旧事务 finally abort 与新事务 guard 重叠。

FaultManager       DpScaleDownStrategy       NodeManager       vLLM FT API       Coordinator
    │                       │                     │                  │                 │
    │ 选择策略并传入上下文  │                     │                  │                 │
    ├──────────────────────►│                     │                  │                 │
    │                       │ FtGate + 拓扑校验   │                  │                 │
    │                       │───────────────┐     │                  │                 │
    │                       │◄──────────────┘     │                  │                 │
    │                       │ guard(request_id,   │                  │                 │
    │                       │       lease_sec)    │ 记录事务主并冻自杀│                 │
    │                       ├────────────────────►│                  │                 │
    │                       │                     │                  │                 │
    │                       │ status 循环至       │ GET status       │                 │
    │                       │ apply-ready         │ 引擎 id == 全局  │                 │
    │                       ├────────────────────►├─────────────────►│                 │
    │                       │                     │◄─────────────────┤                 │
    │                       │◄────────────────────┤ DP rank          │                 │
    │                       │                     │                  │                 │
    │                       │ DEL 当前服务视图    │                  │                 │
    │                       ├────────────────────────────────────────────────────────►│
    │                       │                     │                  │                 │
    │                       │ apply(scale_down)   │ POST apply       │                 │
    │                       ├────────────────────►├─────────────────►│                 │
    │                       │                     │◄─────────────────┤ HTTP 202        │
    │                       │◄────────────────────┤ accepted         │                 │
    │                       │                     │                  │                 │
    │                       │ status 轮询         │ GET status       │                 │
    │                       ├────────────────────►├─────────────────►│                 │
    │                       │◄────────────────────┤                  │                 │
    │                       │                     │                  │                 │
    │                       ├─ 全部 healthy ─────►│ finalize(commit) │                 │
    │                       │                     │ 登记 retired     │                 │
    │                       │ [可选] stop 收空 Pod│                  │                 │
    │                       │ ADD 存活服务视图    │                  │                 │
    │                       ├────────────────────────────────────────────────────────►│
    │                       │                     │                  │                 │
    │                       └─ failed/dead/超时 ─►│ finalize(abort)  │                 │
    │                       │                     │ 拒 stale request_id               │
    │◄──────────────────────┤ failed,执行原 fallback               │                 │

Controller 重启:etcd 只持久 phase/generation/original_dp_ranks/dead_committed/fallback_strategy。中断在 DECIDING|WAITING_ENGINE_FAULT|SCALING_DOWN 的事务恢复为 RECONFIGURING 并走原 fallback,重启后不重放 apply。

已知一致性窗口:当前顺序是 NodeManager finalize(commit) 在前、Controller 更新并持久化 dead_committed 在后。若 Controller 恰好在两者之间退出,NodeManager 内存中可能已经登记 retired rank,而 Controller 尚未提交对应 runtime。恢复时必须按中断事务处理:进入原 fallback,禁止凭旧 runtime 重复 apply。该窗口不通过持久化全部引擎状态消除,需在联调中注入 Controller 重启验证。

6. NodeManager 契约

内部派生开关:enable_dp_scale_down_proxy = enable_fault_tolerance && enable_dp_scale_down。
它由 Controller 统一配置下发到 NodeManager,不是客户需要额外填写的第三个开关;关闭则四条路由 404,行为与现网一致。

方法 路径 作用
POST /node-manager/fault-tolerance/status 本机活跃 endpoint_ids → 引擎 FT status;engines[].id 必须等于请求的全局 DP rank
POST /node-manager/fault-tolerance/apply 仅 instruction=scale_down;注入 dp_store_port
POST /node-manager/fault-tolerance/guard body:request_id + lease_sec∈(0,3600];同 id 续租,异 id 且仍冻结则 502
POST /node-manager/fault-tolerance/finalize body:request_id + commit + retired ids;id 不匹配视为 stale,不解冻新事务

心跳:缩容关闭时仍要求完整 endpoint 集合;开启后用「期望集合精确相等」,允许且仅当本地 rank 全部已 commit 时上报空集合。commit 后的 retired id 同时从心跳、FaultReporter 和进程死亡上报中过滤。

注册与实例组装:NodeManager 注册信息携带引擎 FT capability,包括是否支持 scale_down 以及门禁所需的静态能力。Controller 组装实例时要求同一实例各 Pod 的 FT capability 一致;信息缺失或不一致时失败封闭,不进入缩容编排。

7. 配置

均在 fault_tolerance_config,对 Prefill/Decode 一视同仁。Controller 不因打开缩容而改引擎 EPLB 等原生配置;当前联调不启用 fused MC2,且 Motor 不再读取它作为缩容门禁。

项 默认 含义
enable_fault_tolerance true 总开关
enable_dp_scale_down false Controller 缩容编排
enable_dp_scale_down_proxy 内部派生 NM 代理 FT;由总 FT 与缩容开关共同决定,客户不单独配置
enable_dp_scale_up false 暂定内部名称;当前仅表示缩容成功后允许 stop 已收空 Pod、交给集群补充资源,不表示 Motor 已实现 DP rank 扩容事务
dp_scale_down_config.request_timeout_sec 5.0 Controller→NodeManager 单次 FT 请求超时,也参与内部 guard lease 计算
dp_scale_down_config.poll_interval_sec 1.0 apply-ready 与 apply 结果状态轮询间隔
dp_scale_down_config.execution_deadline_sec 30.0 apply 前状态收敛、apply 后执行收敛各自的等待上限

查询:GET /controller/fault_tolerance/status。总开关或缩容关闭时返回 phase=DISABLED。

典型成功态响应中的实例 runtime 如下;实际接口可返回多个实例,排障时重点查看 phase、本轮 request_id、累计删除集合、服务发布状态和最近错误:

{
  "instance_id": 7,
  "phase": "SCALED_DOWN_RUNNING",
  "original_dp_ranks": [0, 1, 2, 3],
  "request_id": "<scale-down-request-id>",
  "dead_committed": [1],
  "pending_removed_ranks": [],
  "alive_dp_ranks": [0, 2, 3],
  "fallback_strategy": "<original-fallback>",
  "gate": {
    "allowed": true,
    "reason_codes": []
  },
  "engine_statuses": {},
  "serving_published": true,
  "last_error": null,
  "can_serve": true
}

失败排查规则:gate.reason_codes 表示静态准入失败原因;last_error 表示编排、引擎或发布阶段最近一次失败;引擎缩容已提交但发布尚未收敛时,应看到 phase=SCALED_DOWN_RUNNING、serving_published=false、can_serve=false。

8. 测试与验收建议

已有 DT 覆盖:runtime 状态、FtGate、FaultManager 升级链、ServingOverlay、PodLifecycle、NM 代理 API、EventPusher 投影、心跳合约。

建议验收矩阵:

类别 故障注入/条件 期望结果
软件普通 rank 非 0 DP DEAD,survivor UNHEALTHY apply 一次;只删除目标 rank;发布存活视图;推理恢复
软件故障且服务空闲 故障 rank DEAD,survivor 持续 HEALTHY 无法形成完整 U+D,不启动缩容事务、不 DEL、不 apply;状态收集超时后整实例重配置
软件 rank 0 DP rank 0 DEAD 从 survivor 选新 dp_master,通信域恢复,原始 rank 不重编号
连续缩容 连续两轮删除不同 rank 第二轮 apply 携带累计 dead_committed;SET 不把历史死 rank 加回
Pod 部分收空 同 Pod 仍有存活 DP 不 stop Pod
Pod 全部收空 本地 DP 全部 committed,enable_dp_scale_up=false 不 stop Pod,维持缩卡不缩 Pod
Pod 全部收空并允许补容 本地 DP 全部 committed,enable_dp_scale_up=true stop 一次;Motor 不重试;MindCluster 回收/补充 Pod
仅 UNHEALTHY,快恢适用 全 active DP 均 UNHEALTHY、无 DEAD,is_applicable=true 执行快恢;成功结束,失败直接整实例重配置,不再尝试缩容
仅 UNHEALTHY,快恢不适用 全 active DP 均 UNHEALTHY、无 DEAD,is_applicable=false 不猜 rank、不 apply;等待 DEAD,软件收集超时后整实例重配置
软件多 rank 故障 多个 DEAD,其余 active DP 均 UNHEALTHY 一次 apply 携带全部 DEAD;若策略查询发现新的 DEAD,则吸收后继续,survivor 为空则整实例重配置
硬件先到且及时感知 可映射 L4–L6 卡故障;5 秒内出现完整 U+D,且映射 DP 属于 DEAD 用软件 DEAD 生成 apply 参数;硬件 rank 只用于相关性校验
硬件先到但未感知 可映射 L4–L6 卡故障;5 秒仍无匹配 FT 快照 整实例重配置,不启动缩容
硬件故障已缩容 映射 DP 已在 dead_committed 标记硬件事件已处理,不重复恢复
硬件不可映射 未知卡名/拓扑缺失,或同轮存在无法完整映射的硬件事件 不进入缩容,走原策略;空卡名按既有节点/Pod 级语义映射其覆盖的全部 DP
静态门禁 缺引擎 FT、external-lb、scale-down 支持、EPLB、冗余专家,或 auto recovery 冲突 拒绝缩容,记录 gate reason,走 fallback;fused MC2 关闭不构成拒绝原因
引擎失败 apply 非 202、failed/dead、查询异常或超时 不重试 apply,finalize(abort) 后走 fallback
Controller 中断 SCALING_DOWN 或 NM commit/Controller commit 窗口重启 不重放 apply,恢复为 RECONFIGURING 并走原 fallback
特性关闭 enable_dp_scale_down=false NM FT 路由 404;心跳、partial-loss、发布和故障策略与基线一致

每个 E2E 用例至少保存:故障注入命令和目标 rank、引擎与 Controller 状态时间线、apply body/HTTP 202、dead_committed、Coordinator endpoint 集合、Pod stop 情况以及恢复后的推理结果。性能验收分别记录特性关闭时的基线开销、特性开启但无故障时的 status 查询开销,以及故障检测到恢复发布的分阶段时延;不在 RFC 固化单次环境的性能数值。

9. 上游协议依据

  • vLLM core_client.py:external-LB 下由全局 dp_rank 构造 engine_ranks_managed,FT status 的
    engines[].id 继承该全局 rank。
  • vLLM fault_tolerance/api_router.py:POST /v1/fault_tolerance/apply 使用后台任务并返回 HTTP 202;
    202 表示请求被接收,不表示缩容已经完成,最终结果必须通过 GET status 轮询。
  • 本 RFC 的 Motor 分层以此为准;scale_down 指令本身仍以最终采用的 vLLM/vLLM-Ascend PR 和构建为准。

参考链接:

likedislike
ascend-robotascend-robot成员
9月8日 添加了label:rfc
Yyilunh
9月8日 修改了issue 的描述
Yyilunh
9月8日 修改了issue 的描述
wangyang
wangyang成员
9月9日 评论:

👋 您好,感谢向 mindie-motor 提交 Issue!
🎉 我们已收到您的反馈,感谢你对开源社区的支持!

📅 处理时效 维护团队将在工作日 24 小时内查看并回复您的问题。
🔍 自助排查(推荐优先查看) 在等待回复期间,您可以先查阅仓库README以及历史 Issue 中相似问题的解决方案,多数问题可快速解决。
💡 为了更快定位问题,请您确保 Issue 包含:

清晰的问题描述
可复现的操作步骤
相关日志、截图或环境信息
我们会尽快跟进,感谢您的理解与配合!

likedislike
Yyilunh
9月13日 修改了issue 的描述
Yyilunh
9月14日 关联了pull request:[Feature] 推理大EP场景下支持DP域缩容运行
wangyangwangyang成员
9月17日 关闭了 issue
wangyangwangyang成员
9月17日 issue状态由 TODO 改变为 CLOSED
ascend-robotascend-robot成员
9月17日 添加了label:resolved
Yyilunh
9月22日 修改了issue 的描述