Kubernetes 镜像推广器的现代化重写

概述

Kubernetes 官方容器镜像(从 registry.k8s.io 拉取的镜像)的发布依赖于一个名为 kpromo(也称为 image promoter)的自动化工具。它负责将镜像从暂存区复制到生产环境、进行签名、跨区域镜像复制签名,并生成来源证明(Provenance)。作为一个对 Kubernetes 发布流程至关重要的基础设施组件,其稳定性和性能直接关系到整个生态系统的可靠性。2026年,Kubernetes 社区对该工具的核心进行了彻底的、用户无感的现代化重写,旨在解决长期积累的技术债务,并大幅提升其性能和健壮性。

核心概念

  • kpromo (Image Promoter):Kubernetes SIG Release 维护的核心工具,用于安全地将容器镜像从暂存注册中心推送到生产注册中心。它是一个关键的 供应链安全 组件。
  • k8s.gcr.io / registry.k8s.io:历史上及当前用于分发 Kubernetes 官方容器镜像的生产注册中心。
  • GitOps 工作流:推广过程基于 Git 仓库中的 YAML 清单文件(声明所需镜像),通过 Pull Request 进行审查和合并,自动化工具根据清单执行操作。
  • SLSA (Supply chain Levels for Software Artifacts):一个框架,用于确保软件供应链的完整性。kpromo 在推广时会生成 SLSA 来源证明,以提升发布的可审计性和安全性。
  • Cosign:一个基于 Sigstore 项目的工具,用于对容器镜像进行无密钥签名和验证,是 Kubernetes 供应链安全策略的一部分。
  • 阶段化重写 (Phased Rewrite):一种将大型重构分解为多个可独立发布、验证和回滚的小步骤的策略,旨在最小化风险。

实践

重写背景与目标

重写前,推广作业经常耗时超过 30 分钟,并因速率限制而失败。核心推广逻辑已演变为一个难以扩展和测试的“大泥球”。社区的目标是进行一次“隐形”重写:在完全改变内部架构的同时,对外部用户(使用 kpromo 命令和 YAML 清单)保持 100% 向后兼容。

分阶段重写过程

整个重写过程被分解为九个独立阶段,每个阶段都通过独立的 Pull Request 和发布版本交付,确保了平稳过渡:

  1. 阶段1:速率限制 - 重写速率限制逻辑,实现自适应退避。
  2. 阶段2:接口抽象 - 将注册中心操作和认证逻辑置于清晰的接口之后,便于测试和替换。
  3. 阶段3:管道引擎 - 构建新的管道引擎,将推广过程分解为不同的阶段。
  4. 阶段4:来源验证 - 为暂存镜像添加 SLSA 来源验证。
  5. 阶段5:扫描与 SBOM - 集成漏洞扫描和软件物料清单(SBOM)支持。此时发布 v4.2.0,新管道引擎默认启用并在生产环境进行验证。
  6. 阶段6:分离签名与复制 - 将镜像签名与签名复制分离为独立的管道阶段,解决了导致生产环境失败的主要速率限制竞争问题。
  7. 阶段7:移除旧管道 - 完全删除旧的代码路径。
  8. 阶段8:移除遗留依赖 - 删除审计子系统、已弃用的工具和端到端测试基础设施。
  9. 阶段9:删除大泥球 - 移除旧的单体核心及其支持包。此阶段在 v4.3.0 发布,彻底清除了遗留代码。

新管道架构

重写后的推广管道由七个清晰分离的顺序阶段组成:

阶段功能描述
Setup验证参数,预热 TUF 缓存。
Plan解析清单,读取注册中心,计算需要推广的镜像。
Provenance验证暂存镜像上的 SLSA 证明。
Validate检查 cosign 签名;对于空运行(dry-run)模式则在此阶段终止。
Promote在服务器端复制镜像,保留摘要(digest)。
Sign使用无密钥的 cosign 对推广后的镜像进行签名。
Attest使用专用的 in-toto 谓词类型生成推广来源证明。

性能优化

在新架构基础上,一系列优化措施使性能得到了数量级的提升:

  • 并行化注册中心读取:将计划阶段(Plan)的耗时从约 20 分钟降低到约 2 分钟。
  • 两阶段标签列表:首先仅检查源仓库,跳过大量无签名的历史镜像,将 API 调用次数减半。
  • 源端优先检查:在复制签名到所有镜像之前,先检查主注册中心是否存在,将稳态下的工作耗时从约 17 小时减少到约 15 分钟。
  • 超时与重试:为每个网络操作设置独立超时,并自动重试瞬态失败,防止管道挂起。
  • 连接复用:跨操作复用 HTTP 连接和认证状态,减少冗余的令牌协商。

SRE 覆要

与可靠性、可观测性的关联

  • 可靠性:此次重写本身就是一次提升可靠性的大型工程。通过解决性能瓶颈(速率限制、慢速 I/O)和增加健壮性(超时、重试),显著降低了发布作业的失败率,保障了 Kubernetes 核心发布流程的连续性。
  • 可观测性:虽然文中未详述,但管道的阶段化使得对推广过程每一步的监控和故障定位变得更加清晰。独立的签名复制作业(Prow Job)也使该流程的可观测性得到提升。
  • 事件响应:分阶段发布和默认配置的切换(v4.2.0 -> v4.3.0)为团队提供了清晰的回滚路径。在发布 v4.2.0 后迅速发现并修复了两个生产环境回归问题,体现了在关键基础设施中实施“金丝雀发布”或“渐进式交付”的重要性。

最佳实践与常见反模式

最佳实践:

  1. 分阶段、向后兼容的重构:对于关键路径组件,应采用“绞杀者模式”或类似策略,逐步替换旧系统,保持接口稳定,避免“大爆炸”式重写带来的高风险。
  2. 投资于性能与健壮性:主动识别并解决已知的性能瓶颈(如 I/O 竞争、连接建立开销)和稳定性问题(如缺乏超时、重试),是提升 SRE 绩效的关键。
  3. 自动化与 GitOps:坚持使用声明式清单和自动化流水线来管理关键操作(如镜像发布),确保可审计性和可重复性。
  4. 社区驱动与透明化:通过跟踪 issue、PR 和项目看板公开整个重写过程,有助于凝聚共识、获得贡献并管理期望。

常见反模式:

  1. 技术债务累积:允许代码库因历史原因而持续臃肿,最终导致维护成本激增,阻碍新功能开发和稳定性提升。
  2. 对基础设施组件进行不透明的大规模变更:缺乏阶段化验证和回滚策略的激进变更,极易引发重大生产事故。
  3. 忽视性能优化:在规模化的生产环境中,低效的代码会直接转化为更高的成本和更低的可靠性(如超时失败)。

相关指标

此次重写显著改善了以下潜在的 SLI(服务水平指标),从而有助于达成更严格的 SLO(服务水平目标):

  • 推广作业成功率:通过更健壮的错误处理和速率限制来提升。
  • 推广作业执行时间:通过并行化、优化和连接复用来大幅降低。
  • 镜像从暂存到生产可用的端到端延迟:包括验证、复制、签名等所有环节的总耗时。
  • 生产环境 Kubernetes 版本发布周期时间:作为底层工具,其可靠性直接影响上层发布流程的效率。

本案例是 SRE 在维护关键基础设施时,如何通过工程手段持续投资于可靠性、性能和可维护性的一个优秀范例。它展示了即使对于“看不见”的底层工具,一次深思熟虑的重写也能为整个系统带来深远的积极影响。相关架构和原理可参考 kubernetes-image-promotion 和 sre-reliability-engineering。