在 Slack,我们重视快速迭代、快速反馈和对客户的及时响应。同时,我们也拥有数百人的工程师团队,大家一直在努力提高工作效率。公司在不断壮大的同时始终坚持这些价值理念,这意味着我们在不断完善部署系统。我们必须对更高的可视化和可靠性进行投入,以适应正在进行的大量工作。
这篇文章主要阐述我们的流程和一些主要项目,正是这些让我们取得今天的成就。
我们怎样开展部署工作?
在 Slack,每一次 PR 都需要经过代码评审和所有测试。一旦这些条件被满足,工程师就可以将他们的代码合并到主分支上。但是,合并后的代码只能在北美工作时间部署,以确保我们有足够的人力来处理任何意外问题。
我们每天会进行近 12 次计划内的部署活动。每次部署期间,我们会指定一名工程师全权负责,他负责将新的构建发布到生产环境。这个过程有很多详细步骤,可以确保构建缓慢部署,以便在错误产生更大影响前检测它们。
如果出现大量错误,这些构建也能回滚。如果在发布后检测到问题,也能轻松地发布修补程序。
这是我们管理部署的图形化界面
1. 创建一个发布分支(branch)
每个版本都从一个新的发布分支开始,这是我们 Git 历史中允许我们标记发布的一个点。如果在生产环境发现问题,我们也能在这里完成修补程序。
2. 部署到临时生产环境
下一步是将构建部署到临时生产环境的服务器,并运行自动 smoke test。同时,临时生产环境也是生产环境,但它不接受外部流量。
我们还会在临时生产环境中做更多的手动测试,因为与只在开发环境中进行测试相比,这样能让我们对代码可以正确工作更有信心。
3. 部署到 dogfood 和 canary 环境
发布到生产环境的第一步是发布到 dogfood 环境,它是一组服务器,为我们的一些内部 Slack workspaces 提供服务。自己尝鲜,我们自己就是非常活跃的 Slack 用户,dogfooding 能帮助我们及早发现问题。
一旦,我们确信核心功能没有受到不良影响,构建就会部署到 canary,其中大约有 2%的生产流量会路由到 canary。
4. 按百分比发布到生产环境
如果各种曲线图保持稳定,没有异常提醒,我们将继续以百分比的节奏将构建发布到生产环境。我们会将发布量划分为 10%、25%、50%、75%和 100%等五个阶段,以便可以将生产流量缓慢地引入新版本,同时给我们留下时间来调查是否有任何特别的波动或异常。
如果部署过程出现问题如何应对?
代码变更总会有风险,但我们会让经验丰富的部署指挥官掌控每一个新版本的部署过程,观察图表了解情况,和发布代码的工程师协调沟通,来管理风险。
如果在部署过程中出现问题,我们的目标是尽早发现。先对问题调查,找出哪次的代码提交导致问题,回滚,然后在回滚后的代码基础上再完成新构建。不过,有些问题是只有发布到生产环境后才能发现的。在这种情况下,恢复服务显得至关重要。所以在开展问题调查前,我们会立即回滚到上一个可以正常工作的构建。
Building blocks
快速部署
在大家看来,上面描述的工作流程似乎并无新意,但是我们的部署系统经历多次迭代后,才演化到现在样子。
当公司规模还很小的时候,10 个 Amazon EC2 实例就能运行我们所有的应用程序,一次部署意味着对所有服务器做一次快速 rsync 而已。
因此,以前在生产环境前面只有一层:临时生产环境。构建将在临时生产环境终进行验证,然后直接发布到所有生产服务器。这个系统简单易懂,任何工程师都可以随时部署自己的代码。
但是,随着客户数量的增长,运行应用程序所需的基础设施数量也在快速增加。很快,我们基于推送的部署模型就无法处理添加的服务器数量了。每增加一台服务器,都会增加部署时间。即使是使用并行 rsyncs 这样的办法也有其局限性。
最后,我们切换到完全并行的基于拉模式的系统上,解决了这个问题。
我们不再使用同步脚本将新的构建推送到服务器上,而是在发出了 Consul 密钥更改的信号后,每台服务器都会同时 pull 构建。即使规模不断扩大,这也能让我们保持高速度的部署。
原子部署
另一个为分层部署铺平道路的项目是原子部署。
在原子部署前,每次部署操作都会导致一系列的错误,因为将新文件复制到生产服务器的过程不是 atomic。在这个过程中,它会产生一个比较小的时间窗口,在这个窗口中,新函数的调用点已经有了,而实际的实现函数还不可用。当调用这些调用点时,它们会返回内部错误,最终表现为失败的 API 请求和受损的 web 页面。
为解决这个问题而组织起来的团队最终使用冷热目录的方法解决了它。热目录用于处理生产流量,而冷目录则用于准备上线。在部署期间,新代码将被复制到未被使用的冷目录中。然后,等服务器上的所有活动进程都完全退出,我们就立即切换目录。
重新聚焦可靠性
2018 年,我们遇到一个问题,即不顾一切地快速部署,这只会对我们产品的稳定性造成损害。我们有一个非常强大的部署系统,公司也对它投入很大成本,但与部署有关的流程也有必要随之发展。随着我们的公司规模越来越大,在全球范围内为越来越多的关键任务协作提供支持,可靠性就成为重中之重。
对更安全部署的需求促使我们对部署系统进行彻底检查,由此引发的行动最终促成前面描述的基于百分比的部署系统。在底层,我们继续使用快速部署和原子部署,但我们改变了部署方式。这个系统以层的方式发布更新,再加上非常好用的监控系统和工具,让我们能在有缺陷的情况下,在对用户产生影响前找到问题,并减轻影响。
但是,我们还没有做到完美。通过更好的工具和自动化,我们不断改进这个系统。
特别感谢
本文讨论的工作包含以下同事的努力和项目:
原子部署:Saroj Yadav、Chase Jenkins、Jamie Scheinblum
部署系统的图形化界面:Andrew Morrison、Zack Sultan、Jonathan Chang
快速部署:Paul Hammond、Joe Smith
基于百分比的部署:David Stern、Harrison Page、Travis Crawford、Patrick Bogen
Dogfood Tier:Derek Smith、Jamie Scheinblum、Eve Killaby
工作流和流程:Pooja Rana、Karen Xu
英文原文:
评论