执行摘要
- 一句话:自动化 Docker Hub 发布镜像流程
- 推荐动作:建议 DevOps 和 CI 工程师精读此 PR,尤其是 review 中关于 shell 脚本错误处理、竞争条件和依赖管理的讨论。这些模式在自动化发布流程中非常典型,值得借鉴。发布负责人应关注 PyPI 上传问题是否被后续修复。
功能与动机
以前发布 Docker 镜像需要人工从 Buildkite 注解中复制命令执行,容易出错且遗漏了 Ubuntu 24.04 镜像。docker manifest rm 在首次发布时因缺少 || true 导致失败。本 PR 旨在完全自动化发布流程,减少人工操作失误,并统一镜像发布方式。
实现拆解
-
创建自动化发布脚本(.buildkite/scripts/publish-release-images.sh):180 行的 Bash 脚本,负责从 ECR 拉取已构建好的各架构镜像,用 latest 和 v$VERSION 标签重新标记,推送到 Docker Hub,然后创建多架构 manifest 并推送。脚本支持 CUDA 13.0(默认)、CUDA 12.9、Ubuntu 24.04(两种 CUDA 版本)、ROCm 和 CPU 变体。CPU 镜像处理使用 docker manifest inspect 检查是否存在,若不存在则跳过并警告,避免静默失败。
-
调整 Buildkite Pipeline 配置(.buildkite/release-pipeline.yaml):在 Publish release images 分组之前新增一个 block 步骤 block-publish-release-images,要求操作员手动确认后才能进行发布。该 block 依赖于所有多架构 manifest 创建步骤、ROCm 构建和发布版本输入,同时通过 allow_failure: true 依赖两个 CPU 构建步骤,等待它们完成但不阻塞整个 pipeline。实际发布步骤 publish-release-images-dockerhub 在 block 解封后执行,调用上述脚本。此外还为两个 CPU 构建步骤添加了 key: 标识,便于依赖引用。
-
简化注解脚本(.buildkite/scripts/annotate-release.sh):删除了原先打印 Docker pull/tag/push/manifest 命令的 93 行内容,仅保留 wheel 下载说明和一条提示(说明镜像发布已自动化)。原脚本中 ROCM_BASE_CACHE_KEY 等不再需要,一并移除。
-
修复 PyPI 上传脚本依赖(.buildkite/scripts/upload-release-wheels-pypi.sh):在创建 sdist 前安装 requirements/build/cuda.txt,确保 setup.py 的运行依赖(如 torch)可用。但这一改动在 review 中被指出可能引入 CUDA 工具链依赖冲突,尚未完全解决。
关键文件:
.buildkite/scripts/publish-release-images.sh(模块 发布脚本;类别 infra;类型 core-logic): 新增的自动化发布脚本核心,实现了从 ECR 拉取、打标签、推送、创建 manifest 的完整流程,支持所有镜像变体。
.buildkite/release-pipeline.yaml(模块 Pipeline 配置;类别 config;类型 configuration): Pipeline 配置新增了 block gate 和自动化发布步骤,调整了 CPU 构建步骤的依赖关系,是自动化发布能在 CI 中正确运行的关键配置变更。
.buildkite/scripts/annotate-release.sh(模块 注解脚本;类别 infra;类型 core-logic): 移除原先打印 Docker 命令的 93 行内容,仅保留 wheel 下载信息,简化了发布注解的输出。
.buildkite/scripts/upload-release-wheels-pypi.sh(模块 上传脚本;类别 infra;类型 core-logic): 添加了 sdist 构建依赖安装,但 review 中指出该改动可能引入 CUDA 工具链依赖问题,后续需关注。
关键符号:未识别
关键源码片段
.buildkite/scripts/publish-release-images.sh
新增的自动化发布脚本核心,实现了从 ECR 拉取、打标签、推送、创建 manifest 的完整流程,支持所有镜像变体。
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
# 获取发布版本号,并去掉可能的 v 前缀
RELEASE_VERSION=$(buildkite-agent meta-data get release-version --default "" | sed 's/^v//')
if [ -z "${RELEASE_VERSION}" ]; then
echo "ERROR: release-version metadata not set"
exit 1
fi
COMMIT="${BUILDKITE_COMMIT}"
# 登录 ECR
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/q9t5s3a7
# ---- CUDA 13.0 (default) ----
docker pull "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-x86_64"
docker pull "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-aarch64"
# 标记并推送 x86_64 镜像
docker tag "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-x86_64" "vllm/vllm-openai:latest-x86_64"
docker tag "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-x86_64" "vllm/vllm-openai:v${RELEASE_VERSION}-x86_64"
docker push "vllm/vllm-openai:latest-x86_64"
docker push "vllm/vllm-openai:v${RELEASE_VERSION}-x86_64"
# 标记并推送 aarch64 镜像
docker tag "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-aarch64" "vllm/vllm-openai:latest-aarch64"
docker tag "public.ecr.aws/q9t5s3a7/vllm-release-repo:${COMMIT}-aarch64" "vllm/vllm-openai:v${RELEASE_VERSION}-aarch64"
docker push "vllm/vllm-openai:latest-aarch64"
docker push "vllm/vllm-openai:v${RELEASE_VERSION}-aarch64"
# 先清理旧 manifest(第一次失败时忽略)
docker manifest rm "vllm/vllm-openai:latest" || true
docker manifest rm "vllm/vllm-openai:v${RELEASE_VERSION}" || true
# 创建并推送多架构 manifest
docker manifest create "vllm/vllm-openai:latest" "vllm/vllm-openai:latest-x86_64" "vllm/vllm-openai:latest-aarch64"
docker manifest create "vllm/vllm-openai:v${RELEASE_VERSION}" "vllm/vllm-openai:v${RELEASE_VERSION}-x86_64" "vllm/vllm-openai:v${RELEASE_VERSION}-aarch64"
docker manifest push "vllm/vllm-openai:latest"
docker manifest push "vllm/vllm-openai:v${RELEASE_VERSION}"
评论区精华
风险与影响
- 风险:
- 版本号格式依赖:虽然修复了 v 前缀问题,但仍依赖于操作员在输入版本时的一致性。若输入不带 v 的版本,CPU 构建和发布脚本仍可能因标签不匹配失败(但当前脚本已统一处理)。
- CPU 镜像发布失败时静默跳过:当 CPU 镜像不存在时,publish 脚本会跳过并发出 WARNING,但不会导致 pipeline 失败。操作员可能忽略此警告,导致版本发布缺失 CPU 镜像。
- PyPI 上传依赖问题:
upload-release-wheels-pypi.sh 中安装 cuda.txt 可能导致 sdist 构建失败,从而影响 PyPI 发布流程。该问题在 PR 中未修复,需后续关注。
- 夜间构建过滤隐式依赖:publish 步骤过滤夜间构建依赖于 Buildkite 的 transitive filter 语义,若 block 步骤被过滤掉则后续步骤自动消失,但显式添加
if 条件会更安全。当前未显式添加,存在未来因 pipeline 结构变化而意外被包含的风险。
- 影响:
- 对发布流程:从手动复制命令变为自动化执行,大幅降低人为失误的概率。操作员只需在 block 步骤确认即可,流程缩短且更可靠。
- 对团队效率:发布工程师无需在 Buildkite 和终端之间切换,减少了约 5 分钟的机械操作时间。
- 对系统影响:无运行时影响,仅影响 CI/CD 流水线。
- 对镜像完整性:增加了 Ubuntu 24.04 镜像的发布支持,填补了之前的缺失。
- 风险标记:CPU 镜像跳过风险, 版本格式依赖, PyPI 依赖问题, 夜间构建过滤隐式依赖
关联脉络
参与讨论