Prhub

#51067 [Docker][KVConnector] Install mooncake from official wheels instead of a custom build

原始 PR 作者 zhewenl 合并时间 2026-08-06 02:58 文件变更 3 提交数 1 评论 3 代码增减 +26 / -47

执行摘要

发布镜像改用官方 mooncake wheel,移除 S3 自定义构建

PR body 明确说明:自定义 wheel 是 #42114 引入的,当时两个原因都已在 upstream 解决。其一,WITH_NVIDIA_PEERMEM=OFF 在 mooncake 0.3.11.post1 起变为运行时环境变量(mooncake-common/src/environ.cpp,在 rdma_context.cpp::exportDmabuf 中消费),已验证 0.3.11.post1/0.3.12.post1 wheel 包含该字符串而 0.3.10.post2 没有;其二,官方 aarch64 wheel 自 0.3.10.post2 起即内置 USE_MNNVL=ON(0.3.12.post1 wheel 中 engine.SUPPORT_MNNVL == True、22 个 NvlinkTransport 符号)。第三个阻碍(硬编码 libcudart.so.12)由 mooncake-transfer-engine-cuda13 项目解决。而 #46844 已完成 requirements 升级并教会 install-kv-connectors.sh 切换 cuda13 变体,Docker 路径未同步,导致发布镜像与 CI 镜像分离、每个发布镜像安装两次 mooncake。

值得精读。它展示了「上游能力成熟后移除临时 workaround」的典型节奏:#42114 引入的 S3 自定义 wheel 的三个阻碍分别被上游运行时参数、官方 aarch64 构建和独立 cuda13 wheel 项目解决,最终收敛为 PyPI 官方安装。特别值得关注的是 docker/Dockerfile 中 RUN 块错误传播的处理:在无 set -e 的 shell 块中用 && 串联保持失败致命,并配合注释解释原因,这是 Dockerfile 可靠性的好范例。

讨论亮点

核心交锋有两点。一是 Codex 的 P2 评论指出:在无 set -e 的 RUN 块中,nixl-cu 安装失败会被新增的 || true 版本探测和后续条件分支掩盖,最终以成功状态结束,导致镜像可能缺失正确 nixl_ep_cpp.so,建议用 && 串联或启用 set -e(评论对应提交 841c29fa1c)。作者在最终提交中改为 && 链并添加注释说明,问题已解决。二是 mgoin 指出 vLLM 默认 CUDA 13,文档默认安装命令应指向 mooncake-transfer-engine-cuda13;作者采纳并把文档默认命令改为 cuda13 变体。Harry-Chen 审核通过。

实现拆解

实现拆解

  1. docker/Dockerfile:移除自定义 wheel 安装块,并入官方 wheel 与 CUDA 13 变体切换。删除 MOONCAKE_WHEEL_AARCH64 / MOONCAKE_WHEEL_X86_64 两个 ARG 及原先整段 uv pip install "${WHEEL}" 的 RUN 块;在现有 INSTALL_KV_CONNECTORS=true 的 kv-connectors RUN 中,先强制重装匹配 CUDA 大版本的 nixl-cu${CUDA_MAJOR}(保证正确的 nixl_ep_cpp.so),再通过 importlib.metadata 探测已安装的 mooncake 版本,若 CUDA major 为 13 则先卸载 mooncake-transfer-engine 再安装同版本的 mooncake-transfer-engine-cuda13。该写法镜像 install-kv-connectors.sh 的既有逻辑,使两条安装路径行为一致。同时作者将 nixl 安装命令结尾从 ; 改为 &&,避免 RUN 块(无 set -e)以最后一条命令退出码作为整体状态时掩盖 nixl 安装失败(对应 Codex 的 P2 评论)。

  2. .buildkite/release-pipeline.yaml:清理 S3 定制 wheel 的 env 与 build-arg。删除 MOONCAKE_WHEEL_AARCH64_2_35MOONCAKE_WHEEL_AARCH64_2_39MOONCAKE_WHEEL_X86_64 三个 env 变量,以及 8 个(x86/aarch64 × CUDA 12.9/13.0 × Ubuntu 默认/24.04)发布镜像构建命令中合计 16 行 --build-arg MOONCAKE_WHEEL_*。此前按 glibc 区分 2_35/2_39 wheel 的原因(Ubuntu 24.04 兼容性)随自定义 wheel 一并作废。

  3. docs/features/mooncake_connector_usage.md:补充关键运行期契约。默认安装命令改为 mooncake-transfer-engine-cuda13(vLLM 默认 CUDA 13),并说明 CUDA 12 环境应装 mooncake-transfer-engine 以及装错 wheel 的失败症状(libcudart.so.<major>: cannot open shared object file);新增 WITH_NVIDIA_PEERMEM 环境变量说明:默认 1 走 ibv_reg_mr() 需要 nvidia-peermem 内核模块,置 0 走 DMA-BUF 路径,GB200 等无该模块的主机必须显式设置,并给出未设置时的报错定位(Failed to register memory <addr>: Bad address)。

  4. 验证方式:无自动化测试配套;作者以 docker build 加 mooncake connector 实测(WITH_NVIDIA_PEERMEM=0)验证 KV 传输全部成功(Num failed transfers=0)。

文件 模块 状态 重要度
docker/Dockerfile 镜像构建 modified 4.83
.buildkite/release-pipeline.yaml 发布流水线 modified 4.19
docs/features/mooncake_connector_usage.md 文档 modified 2.57

关键源码片段

docker/Dockerfile infrastructure

核心变更文件:删除 S3 自定义 mooncake wheel 的 ARG 与 RUN 块,新增 CUDA 13 变体切换逻辑并修复 nixl 安装失败被掩蔽的问题,直接影响所有发布镜像内容。

# kv-connectors 安装链:INSTALL_KV_CONNECTORS=true 时启用。
# 关键点:本 RUN 块没有 `set -e`,docker build 以最后一条命令的退出码
# 作为整体状态,所以必须用 && 串联,任何一步失败都应立即中断构建。
RUN if [ "$INSTALL_KV_CONNECTORS" = "true" ]; then \
    # 强制重装与 CUDA 大版本匹配的 nixl wheel,确保拿到正确的 `nixl_ep_cpp.so`    # 若这里失败,&& 链会直接让整个 RUN 失败,而不是被后续命令掩盖。
    uv pip install --system --force-reinstall --no-deps nixl-cu${CUDA_MAJOR} && \
    # 探测当前已安装的 mooncake 版本;读取失败时记为 "not found" 而非报错,
    #  CUDA 12 等不需要切换的场景保持静默。
    MOONCAKE_VERSION=$(python3 -c "import importlib.metadata as m; print(m.version('mooncake-transfer-engine'))" 2>/dev/null || true) && \
    # 默认官方 wheel 链接 libcudart.so.12,CUDA 13 镜像必须换成 cuda13 变体;
    # 两个包都内置 mooncake 模块,直接覆盖会冲突,因此先卸载再装同版本。
    if [ "${CUDA_MAJOR}" = "13" ] && [ -n "${MOONCAKE_VERSION}" ]; then \
        uv pip uninstall --system mooncake-transfer-engine 2>/dev/null || true; \
        uv pip install --system "mooncake-transfer-engine-cuda13==${MOONCAKE_VERSION}"; \
    fi; \
fi# mooncake 默认通过 nvidia-peermem 注册 GPU 内存用于 RDMA(WITH_NVIDIA_PEERMEM=1)。
# 未加载该内核模块的主机(如 GB200)必须以 WITH_NVIDIA_PEERMEM=0 运行。
# 刻意不写为 ENV:避免镜像覆盖 mooncake 自身的默认值,留给用户按主机条件决定。
# 症状参考:rdma_context.cpp 报 "Failed to register memory <addr>: Bad address"。

评论区精华

nixl-cu 安装失败可能被后续命令掩蔽(Codex P2) 正确性

Codex 指出:当 `INSTALL_KV_CONNECTORS=true` 且前面的 `uv pip install --force-reinstall --no-deps nixl-cu${CUDA_MAJOR}` 失败时,新增的 metadata 探测因 `|| true` 成功并成为 if 块返回的状态;CUDA 12 上条件为 false 返回 0,CUDA 13 上成功的 mooncake 切换也会掩盖失败。这会让 Docker 构建发布缺失正确 `nixl_ep_cpp.so` 的镜像。建议用 `&&` 串联或启用 `set -e`。

结论:作者采纳:最终提交中 nixl 安装命令以 `&&` 串联后续命令,并在注释中说明该 RUN 无 `set -e`,用 `&&` 保证失败保持致命。 · 已解决

文档默认安装命令应优先 cuda13 变体 documentation

mgoin 评论:vLLM 以 CUDA 13 为默认,文档应默认使用 `mooncake-transfer-engine-cuda13`。

结论:已采纳:最终文档默认安装命令改为 `mooncake-transfer-engine-cuda13`,并补充 CUDA 12 环境下应安装 `mooncake-transfer-engine` 的说明。 · 已解决

风险与影响

  1. 上游 wheel 大版本升级:从固定 S3 的 0.3.10.post2 变为 PyPI >= 0.3.12(#46844 已在 requirements 中设定),跨了 0.3.11/0.3.12 两个版本,构建选项、默认行为可能有差异;例如自定义 wheel 还用于 STORE_USE_ETCD=ON(master HA)等非默认构建,官方 PyPI wheel 是否覆盖这些场景需要在真实部署中验证。
  2. CUDA 13 变体切换可能静默跳过docker/DockerfileMOONCAKE_VERSION 探测失败时 || true 会静默继续,若在 CUDA 13 镜像上未探测到版本,cuda13 变体不会安装,最终以默认 wheel(链接 libcudart.so.12)发布,镜像启动 mooncake 时会 import 失败。当前安装链上该探测基本可靠,但缺少 CI 断言。
  3. WITH_NVIDIA_PEERMEM 默认行为变化:此前自定义 wheel 在构建期关闭 peermem,现在官方 wheel 默认 WITH_NVIDIA_PEERMEM=1。GB200 等未加载 nvidia-peermem 模块的主机若升级到新镜像而未设置该环境变量,KV 传输将报 Failed to register memory <addr>: Bad address。文档已覆盖,但属运行期行为变更。
  4. 构建链路无自动化测试:该改动没有配套的 CI 测试或镜像内容断言(例如验证 CUDA 13 镜像中 mooncake 包变体、验证 nixl 包存在),回归只能靠发布流水线人工发现。

对用户:从 vLLM 发布镜像消费 mooncake 的用户不再依赖 S3 自定义 wheel,安装链路统一走 PyPI,体验更简单;CUDA 13 用户自动获得 cuda13 变体,免去手工换包。对系统:发布镜像与 CI 镜像行为对齐,每个镜像少安装一次 mooncake(此前先装 PyPI 版本再被自定义 wheel 覆盖),镜像层数减少,S3 依赖消除。对团队:release-pipeline 的 env/arg 维护负担下降,文档明确了在 GB200 等主机上使用 mooncake 的前置条件,减少外部问题反馈。

上游 wheel 大版本升级 (0.3.10→0.3.12+) CUDA 13 变体切换可能静默跳过 WITH_NVIDIA_PEERMEM 默认行为变化 构建链路无自动化测试

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论