尽管采用过程主要遵循顺序流程,但部分阶段是并行进行的,以便加快进度。
下面我们将探讨在基于 Arm 的主机上引导构建基础设施时面临的挑战: 初始目标
最初的目标其实很简单:为 Arm 构建一个服务,并使用现有的部署平台将其部署到基于 Arm 的主机上。但这个看似简单的目标,却揭示出基础设施各层对 x86 的高度依赖。 主机准备
构建与部署服务之前,必须确保主机可支持 Arm。这意味着从最底层开始。
第一步是构建 Arm 兼容的主机镜像,包含操作系统、内核及 Uber 核心基础设施依赖的各类主机级软件。
每个组件都必须被重构、测试并验证,以确保在 Arm 硬件上稳定运行。一旦主机镜像准备完毕,我们就可以将 Arm 主机集成进服务器集群,为下一步构建服务打好基础。 构建服务
一旦 Makisu 和整个 Buildkite 栈在基于 Arm 的主机上运行起来,我们迈出了下一个重要步骤:通过为容器镜像设置分布式构建流水线来推进构建设置。
这个新的流水线将构建过程多路复用到 Arm 和 x86 主机上,在每个架构上本地运行 Makisu。
镜像构建完成后,流水线会触发最后一步,使用多架构容器 manifest 将 x86 和 Arm 镜像合并为一个统一的多架构容器镜像。
图 3:分布式容器镜像构建流程该架构优势显著:
无需整体迁移至 Bazel,节省人力成本
原生支持无法交叉编译的工作负载
避免交叉编译的性能开销,缩短构建时间,帮助我们满足构建延迟的 SLA 要求
但缺点也存在:构建成本翻倍——因为需要为两种架构分别构建容器镜像。
截至本文撰写时,我们每周要进行超过 40 万次容器镜像构建,这种额外成本很快变得非常可观。但即便如此,从单位经济效益来看,向 Arm 架构过渡仍然物有所值。
此外,多架构构建支持渐进式迁移策略,因为同一个镜像标签可以同时部署在 Arm 和 x86 主机上。 首批服务上线
有了多架构镜像构建能力后,下一步是部署支持 Arm 的无状态和有状态平台。
在 Uber,我们在逐步引入生产环境变更时非常谨慎,逐步扩大变更范围,因此构建了基于架构的调度约束和回滚机制。
例如,如果部署的镜像仅有 x86 版本,系统将自动放弃 Arm 调度约束并回滚到 x86 主机。这确保了稳定性。
最终,我们成功在 Arm 主机上部署并运行首批服务,证明了 Arm 与 x86 可共存于 Uber 的生产环境中。 02/结论