Prhub

#7606 [env] fix: Update ascend image build workflow

原始 PR 作者 yyyy2000 合并时间 2026-08-31 09:03 文件变更 3 提交数 2 评论 0 代码增减 +130 / -63

执行摘要

Ascend 镜像改两阶段推送,规避 Quay GC 销毁中间镜像

PR body 直接说明了根因:'The automatic garbage collection mechanism of the QUAY image registry causes the ARM image to be destroyed before the AMD image finishes building on Ascend.' 在原流程中,先完成构建的架构以 tmp-* 临时 tag 存放在正式仓库 quay.io/ascend/verl,等待另一架构构建期间会被 Quay GC 清理,导致多架构 manifest 合并时引用已失效的 digest。由于 ARM 与 AMD 构建耗时差异大,该问题表现为随机性的 CI 失败。

建议镜像发布与 CI 维护同学精读该 PR:两阶段推送、digest 传递、防 GC tag、凭据隔离的组合是容器镜像 CI 的通用最佳实践。对一般训练框架使用者无需关注。后续可改进的点:将临时仓库迁移到组织级命名空间以消除单点依赖;为 merge 阶段补充 DIGESTS 为空时的显式失败断言;统一 a2/a3 的临时 tag 命名风格。

讨论亮点

该 PR 没有任何 review 评论,wucong25 直接 APPROVED,未产生讨论线程。值得注意的设计结论以代码注释形式固化在 workflow 中:临时仓库必须设为 Public,否则 merge 阶段匿名读取 digest 会返回 401;构建与合并阶段分别使用独立的仓库凭据,正式仓库与临时仓库的登录完全隔离。这两点是后续维护者最容易踩的坑。

实现拆解

  1. 新增临时仓库环境变量:两个 workflow 的 env 段各自新增 QUAY_TEMP_REPO: quay.io/yezib/verltest,与正式仓库 QUAY_REPO 分离,中间产物不再进入正式仓库。
  2. 构建阶段改造为 digest 输出build-push-digestbuild-push-digest-v080 两个 job 中,docker/build-push-action@v6tags: 直接写 tag 改为 outputs: type=image,name=...,push-by-digest=true,name-canonical=true,push=true,只向临时仓库推送 digest;随后新增 "Tag digest to prevent GC" 步骤,用 docker buildx imagetools create 立即为 digest 打 tmp-a2-*(a2)或 tmp-*(a3)临时 tag,并在注释中说明 "Quay.io 约 1 小时自动清理未打 tag 的 digest"。
  3. 合并阶段区分源与目标仓库:merge job 新增 SOURCE_IMAGE=QUAY_TEMP_REPOTARGET_IMAGE=QUAY_REPO 两个环境变量,digest 列表从临时仓库拼接,imagetools create 合并多架构 manifest 后写入正式仓库;注释提醒 "临时仓库需为 Public,否则匿名读取 digest 会 401",即 merge 阶段不依赖临时仓库凭据。
  4. 清理阶段凭据隔离:删除临时 tag 的步骤单独用 QUAY_USERNAME_TMP / QUAY_PASSWORD_TMP 登录,通过 crane(go-containerregistry v0.20.2)执行 crane delete,与正式仓库凭据完全分离,删除失败以 || true 容忍。
  5. 文档顺手清理docs/ascend_tutorial/zh/dev_guide/performance/perf_tuning_on_ascend.rst 删除一行笔误的 ++actor_rollout_ref.ref.megatron.override_transformer_config.use_flash_attn=True 重复配置,与主变更无直接关系。
  6. 测试与验证:无配套单测;验证依赖下次 Ascend 镜像构建实际运行,属于 "workflow 即测试" 模式。
文件 模块 状态 重要度
.github/workflows/docker-build-ascend-a2.yml 镜像构建 modified 4.96
.github/workflows/docker-build-ascend-a3.yml 镜像构建 modified 4.56
docs/ascend_tutorial/zh/dev_guide/performance/perf_tuning_on_ascend.rst 文档 modified 1.18

关键符号

QUAY_TEMP_REPO build_main build_v080

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 临时仓库依赖个人命名空间quay.io/yezib/verltest 为个人账号仓库,构建链路强依赖其可用性、配额与凭据有效期;该 namespace 一旦被清理或凭据轮换且未同步更新 workflow,会导致发布中断。
  2. GC 策略差异未验证:方案假设临时仓库不会被 Quay GC 干扰,但 PR 未说明两个仓库的 GC 策略差异,若临时仓库同样触发 GC,竞态只是被转移而非消除。
  3. 临时 tag 清理容忍失败crane delete || true 失败时不会告警,临时 tag 会逐渐累积,长期占用仓库配额。
  4. digest 传递依赖 runner 临时目录:merge job 通过 runner.temp 的 artifact 传递 digest 文件,上游失败时 DIGESTS 可能为空字符串,imagetools create 将失败,且没有重试机制。
  5. 新 secrets 依赖QUAY_USERNAME_TMP / QUAY_PASSWORD_TMP 若未在仓库 secrets 中配置,workflow 会在登录步骤直接失败。

影响范围集中在 Ascend a2/a3 容器镜像的发布 CI 流程,不触碰任何训练、rollout 或模型代码路径。对镜像使用者完全无感:对外 tag 与镜像内容不变,只是中间产物的存放位置与推送时序改变。对团队而言,消除了发布流水线中的随机性失败,提升 Ascend 镜像发布的可靠性;同时引入了对个人 Quay 命名空间和新增 secrets 的运维依赖,需要团队内同步维护。该 "两阶段推送 + 防 GC tag + 凭据隔离" 的模式可复用到其他镜像仓库(如 Docker Hub 的自动清理场景)。

依赖个人命名空间临时仓库 临时 tag 清理容忍失败 GC 策略差异未验证 夹带无关文档改动

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论