Shipyard:Slack 新一代 EC2 平台的设计思路
过去几年,Slack 持续改造其 Amazon EC2 实例的运行方式。此前的工作重点包括:从单一 Chef 栈迁移到更具韧性的多栈架构,引入带版本的 cookbook 发布流程;随后又通过拆分生产环境、基于信号的 Chef 执行机制和更智能的发布方式,降低变更失败的影响范围。
这些改进提升了大规模 EC2 体系的可靠性和可控性,但也暴露出一个更根本的问题:持续更新长期运行的 EC2 实例,已经逐渐触及上限。
在旧模式下,服务级部署并不容易;基础设施漂移难以完全避免;跨多个层级协调变更会持续增加复杂度。容器能解决一部分工作负载的问题,但并非所有系统都能轻松迁移到容器中。
因此,Slack 构建了 Shipyard:一个面向 EC2 的新一代平台,试图把不可变基础设施、渐进式发布和自动化安全控制等现代部署实践,直接带到 EC2 实例管理中。
Shipyard 提供了什么
Shipyard 的核心思想,是把基础设施视为可部署的产物,而不是不断被修改的长期实例。它将系统重心从传统配置管理,转向构建流水线、可部署镜像和自动化安全机制。
多架构与多操作系统支持
Shipyard 从设计之初就支持多种 CPU 架构,包括 AMD64 和基于 ARM 的 Graviton 实例;同时支持 Ubuntu、RHEL、Amazon Linux 等操作系统。
这种灵活性允许团队在成本、性能和兼容性之间做取舍,而不需要为不同架构或系统维护多套平台实现。
它尤其适合那些不容易迁移到容器的工作负载,例如基础设施组件、Kubernetes 工作节点,以及出站网络栈等。
基于指标的发布与安全控制
每个服务都与 Slack 的部署编排系统 Gondola 集成,以支持渐进式发布和基于指标的自动化安全检查。
当服务健康信号异常时,发布可以自动暂停;必要时也可以回滚到此前已知可用的版本。这让 EC2 层面的变更能够获得类似现代应用发布平台的安全边界。
快速且可预测的实例启动
Shipyard 采用类似容器的分层镜像方式:
- 共享的基础镜像提供通用基础设施组件;
- 服务专属镜像构建在该基础之上。
这样可以尽量减少实例启动时需要执行的工作,使实例能够在不同区域中更快、更一致地上线。
简化配置管理
Shipyard 的一个重要架构变化,是重新定义配置管理工具的职责。
过去,实例会定期运行 Chef 任务,检查并重新应用配置。这样做可以把手工修改或异常变更恢复到期望状态,但也意味着实例会在后台持续变化。
在新模式下,配置更多发生在明确的生命周期阶段,例如镜像构建和实例初始配置。配置工具主要用于部署服务,而不是不断修改整个系统。
这种方式减少了后台负载,降低了意外覆盖的风险,也让系统行为更容易推理:实例不会在运行过程中被持续改写。
实时资产清单与集群可见性
Shipyard 配套了一个名为 Peekaboo 的资产清单系统,用于接近实时地查看 EC2 集群状态。
相比把 Chef Server 作为事实依据,Peekaboo 直接使用云事件和实例元数据,提供跨环境的遥测能力。它还可以跟踪非 Shipyard 部署的实例,从而在一个地方展示整个 EC2 集群。
Peekaboo 基于 AWS EventBridge、OpenSearch 和 Lambda 构建,并提供:
- 用于浏览集群的 UI;
- 用于系统集成的 API;
- 用于快速检查的命令行工具。
通过集中这些信息,团队可以减少猜测,在统一位置查看和管理 EC2 实例。
短生命周期、持续刷新的实例
为了保持实例安全并尽量接近真正的不可变,Shipyard 中的每个 EC2 实例都有有限生命周期,并会按计划自动轮换。
这意味着集群始终保持较新的状态,潜在漏洞的暴露时间更短;团队也会更多关注替换实例,而不是在原实例上做就地修改。
Golden Base Images:slack-zero
Shipyard 的基础是一套共享基础镜像,名为 slack-zero。它由 Slack 的计算平台团队构建,并与安全、监控团队协作维护。
slack-zero 包含:
- 操作系统基线与加固;
- 网络与服务发现配置;
- 监控与安全代理;
- 通用工具和基础系统配置。
可以把 slack-zero 理解为类似基础 Docker 镜像的角色:它为所有服务提供标准化、可信任的基础,同时允许服务团队在其上定制自己的运行环境。
基础镜像被视为不可变但短暂存在的产物。当安全补丁、监控更新或网络改进需要进入基础层时,平台会生成新的 slack-zero 镜像。下游服务镜像随后可以基于新基础镜像重建,以继承最新修复和改进。
为什么选择 AWS Image Builder
Slack 使用 AWS Image Builder 构建 slack-zero,而不是继续使用 Packer。其主要原因包括:
- 生命周期管理:通过生命周期策略自动清理旧 AMI,帮助降低存储成本。
- SSM 参数发布:每个新的
slack-zero镜像都会更新一个 SSM 参数,标记账户中最新可用的 AMI。服务流水线读取该参数,确保基于最新基础镜像构建。 - 事件驱动自动化:当
slack-zero镜像成功完成构建后,EventBridge 和 Lambda 会自动触发服务负责人账户中的下游流水线,重建依赖镜像。 - 内置测试:AMI 发布前,Image Builder 会启动临时实例并运行验证测试,确保镜像在分发前经过检查。
这些能力让平台基础层可以持续演进,同时降低服务团队的接入负担。
服务镜像
每个服务团队会基于 slack-zero 构建自己的 AMI。这样既能继承平台组织维护的标准组件,也能控制自己的运行环境。
服务镜像流水线通常定义:
- 安装哪些软件;
- 服务如何配置;
- 实例初始化时需要执行哪些服务相关动作。
由于大多数配置已经被烘焙进镜像,实例启动会更快且更一致,也能减少配置漂移,让集群行为更可预测。
这种模式将不可变基础镜像与服务专属层结合起来,在平台稳定性和团队灵活性之间取得平衡。
镜像构建与实例配置
Shipyard 将实例准备过程拆成两个阶段:构建和实例配置。
在构建阶段,系统安装软件包,并写入跨环境一致的配置。这样每个实例启动时,都已经处于一个准备好的、已知可用的状态。
环境相关配置则在实例启动时应用,例如:
- 密钥;
- 区域配置;
- 部署元数据。
这个阶段被设计得尽量轻量,通常只包括写入配置、获取密钥和启动服务。
将安装软件包等重操作提前到构建阶段后,实例可以在数秒内进入可用状态,而不是等待数分钟。这对扩容、滚动发布和自动替换实例都很关键。
部署与集群更新
当团队需要发布变更时,会构建新的 AMI,并通过部署流水线推出。Shipyard 不会在现有实例上打补丁,而是通过受控替换来更新集群,使状态保持一致且可预测。
这种方法把 EC2 实例管理推进到更接近现代应用交付的模式:
- 变更以镜像形式交付;
- 发布通过渐进式流程推进;
- 风险通过健康信号和自动化机制控制;
- 实例通过替换而不是原地修改完成更新。
对 EC2 运维模式的转变
Shipyard 的价值不只是替换一套工具,而是改变了 Slack 对 EC2 运维的基本假设。
过去,EC2 实例往往是长期运行、持续被配置管理工具修正的对象。现在,它们更像是由流水线生产、带有版本、可以逐步发布和回滚的基础设施产物。
这让那些暂时无法容器化的工作负载,也能获得不可变基础设施、快速启动、可观测资产清单和发布安全控制带来的收益。
