近期 Zeabur 因受到 zbpack v1 既有基础设施淘汰的影响,正在向所有用户推送新一代构建系统(zbpack v2)的更新。升级过程中已知造成了一些兼容性的问题,这里会说明问题的缘由、处理方式,以及如果你遇到这个问题时,可以如何缓解这个问题。
Zeabur 背后的编译基础设施是这样运作的:
“registry v1”是使用 distribution/distribution 的 registry 构建的,由于其造成的种种问题,促使我们迁移到自行设计的 registry v2 方案:
blob unknown
的错误并拒绝上传 manifest,进而导致启动时无法拉取镜像distribution/distribution
倾向做全局 blob 去重,导致我们无法在不读取所有 manifest 的情况下,了解哪些 blobs 是用不到的。官方提供的垃圾清理(garbage collection)工具要求停机运行(stop-the-world),在 Zeabur 如此大的 registry 规模下无法运作,导致 R2 累积了非常大量的 blobs,并因此造成相当严重的性能问题我们将 registry v2 设计成“构建 OCI image”后“直接推送到 R2 bucket”,接着再使用 Cloudflare Workers,编写一个可以将 bucket 中 OCI image 结构转换成符合 OCI Distribution Specification 中 Pull API 的只读 API。这样一来,除了性能可以获得极大提升、可以最大化 multipart 上传的效率,也可以避免因 registry 造成的种种问题。与此同时,我们将 blob 的去重限定在仓库内部,因此可以做到“删除一个仓库就能回收其对应的 blobs”,极大简化内部维护且无需 stop-the-world。
不过从上面的描述中,也能看到 registry v2 的推送流程有着相当大的变化。这部分已经在 zbpack v2 中得到实现,但 zbpack v1 由于其复杂的推送流程,以及高度依赖 buildkit CLI 进行 image 的构建,导致实现这部分较为困难。因此近一个月,我们让属于 zbpack v1 的项目继续使用 zbpack v1(registry v1)编译,仅当用户反馈 zbpack v1 无法启动时,才手动切换到 zbpack v2。
但当 registry v1 越来越不堪重负,出错频率节节攀升,导致类似工单越来越多时,我们不得不考虑将 zbpack v1 负责 image 的部分,转换到 zbpack v2 上。
细心的开发者应该注意到 zbpack (v1) 的 GitHub Repo 从 Archived 转回维护状态,并提交了很多与 Dockerfile 相关的更新。实际上,这部分就是在为 zbpack v1 转接到 zbpack v2 的兼容层做准备。
我们希望维持 zbpack v1 既有的 Dockerfile 生成功能,但在生成 Dockerfile 后不使用 zbpack v1 内置的构建逻辑,而是切换到 zbpack v2。因此,我们将 v1 现有的 Dockerfile 生成功能改为公开函数,并让构建服务使用这个函数产出 Dockerfile,再传递到运行 zbpack v2 的编译机器上。
不过 zbpack v1 毕竟最初是设计在编译机器上运作的,有诸多部分需要进行实现或转接:
因此,我们实现了 zbpack v1 兼容层,移植 zbpack v1 编译机器对 zbpack v1 调用的处理。绝大部分显而易见的问题(如代码读取),我们在全量推送前都已经解决,并在测试机器上进行内部测试时,没有遇到判断失误的状况,同时也有派驻 on-call 工程师持续关注推送带来的影响。然而在实际推送到所有机器上时,却发现了诸多新兼容层没有考虑到的问题。举例来说:
ZBPACK_
开头的变量失效ZBPACK_DOCKERFILE_NAME
行为与先前不一致考虑到部分情境没有其对应的测试环境,以及评估回退版本造成的影响可能更大,我们在 on-call 时遇到这些问题,决定将错就错,快速运行“修正”“测试”“推送”的流程,同时也向客户提供 workaround 以缓解问题。我们在 8/26 - 8/27 这段期间很快地实现完整的 zbpack 兼容层、实现了 plan type 和 plan meta 的展示,并为 registry v2 设计了中国大陆的 CDN 来加速下载。
非常感谢所有反馈这些问题的客户,让我们发现兼容层没有涵盖到的边缘情况,并促使我们研究并修正。
上文提出的问题,兼容层均已实现或修正。如果有其他不完整的部分,也请提工单让我们的工程师处理。
目前已知的问题如下:
PORT=对外端口
(如 PORT=8080
)来缓解这个问题概观本次事故,内核原因有几个:
如果您是此次受影响的客户,我们可以提供按影响时长折算的 credit 进行补偿。未来我们在推送这部分功能时会更加谨慎,也非常感谢所有发现兼容层问题的客户。