部署需要在速度和可靠性之间达到谨慎平衡。在Slack,我们重视快速迭代、快速反馈循环,以及对客户反馈的响应速度。我们拥有数百名工程师,他们都在努力提高工作效率。在公司成长的同时也保持这些价值观,就意味着我们的部署系统需要不断完善。为了适应工作量,我们必须加大可视性和可靠性的投入。本文将概述我们的部署流程以及一些使我们达到目标的主要项目。
Slack的每一个PR都需要代码review和所有的测试通过。一旦满足这些条件,工程师就可以将他们的代码合并到master中。但是,合并后的代码只在北美工作时间内部署,以确保我们有足够的人员来应对任何意外问题。
我们每天会进行大约12次计划内部署。在每次部署过程中,我们会指定一名工程师作为部署指挥官,负责将新的build推出到生产环境中。这是个多步骤的过程,确保构建缓慢推到线上,这样我们可以在错误影响到所有人之前发现错误。如果错误激增,这些构建可以回滚,如果我们在发布后发现问题,可以很容易地进行热修复。
创建一个发布分支
每个版本开始时都会有一个新的发布分支,这是我们的Git历史记录中的一个点,我们可以在这个点上标记发布,同时我们也可以在这里对在发布过程中发现的问题进行修复。
部署到staging版
下一步是将构建部署到Staging服务器上,并运行自动冒烟测试。staging是一个不接受公共流量的生产环境。我们在staging环境中进行额外的手动测试,因为与只在开发环境中进行测试相比,它能更大程度保证代码更改能正常工作。
部署到狗粮环境和金丝雀环境
向生产领域的推广首先从狗粮环境开始,这是一套服务于我们内部Slack工作区的主机。由于我们自己也是非常活跃的Slack用户,所以狗粮环境部署能帮我们发现很多问题。一旦我们确信核心功能没有变化,就会将构建部署到金丝雀环境上,大约有2%的生产流量路由到该环境。
基于百分比的推广到生产中
如果各种指标保持稳定,并且没有警报,我们将继续以百分比为基础的方式向生产环境推广。我们以10%、25%、25%、50%、75%和100%的增量来分解部署,以便慢慢地将生产流量暴露在新的构建中,同时给我们时间来调查是否有任何尖峰或异常。
如果在部署过程中出了问题怎么办?
修改代码总是会带来风险,但我们通过让训练有素的部署指挥员,观察各种指标并与推送代码的工程师进行协作。
万一有问题,我们的目标是尽早发现问题。我们会调查问题,找出导致问题的PR,还原它,在还原的过程中需要精挑细选,然后进行新的构建。然而有时我们无法找到问题。在这种情况下,恢复服务至关重要,这时我们会立即回滚到之前的版本中,然后再开始调查问题的原因。
基石
快速部署
上面描述的工作流程在事后看来可能很明显,但我们的部署系统经历了多次迭代,才能达到这个目标。
当公司规模很小的时候,我们的整个应用程序可以在10个Amazon EC2实例上运行,而部署只是快速rsync到所有服务器。在推到生产环境之前,只有一个过程:staging环境。构建完成后,在staging系统上进行验证,然后直接rsync到所有的生产服务器。这个系统很容易理解,任何工程师都可以随时部署自己的代码。
但随着客户数量的增加,运行应用程序所需的基础设施数量也在增加。很快,基于推送的部署模式就无法应对。每增加一台服务器,就会增加部署时间。即使像并行rsyncs这样的策略也有其局限性。
最终,我们通过切换到完全并行的拉模式系统解决了这个问题。当Consul key更改的信号发出后,每台服务器都会并发地拉当前构建,而不是使用同步脚本将新的构建推送到服务器上。这使我们能够在继续扩大规模的同时保持高速的部署速度。
原子部署
另一个为分层部署铺平道路的项目是原子部署。
在原子化部署之前,每次部署都会引起一系列的错误,因为将新文件复制到生产服务器上的过程并不是原子化的。这就导致了一个小时间窗口,在该窗口中,新函数的调用点会出现。当这些调用站点被调用时,它们会返回内部错误,表现为API请求失败和网页无法展示。
围绕这个问题的团队通过使用热目录和冷目录解决了这个问题。热目录将为生产流量提供服务,而冷目录正在准备中。在部署期间,新的代码会被复制到未使用的冷目录。然后,一旦服务器的活动进程被耗尽,我们就会瞬间切换目录。
重视可靠性
在2018年,我们遇到了一个问题,就是尽可能快的部署速度伤害了我们产品的稳定性。我们有一个非常强的部署系统,然而围绕着部署的流程必须要进化。随着我们成为一家更大的公司,在全球范围内为越来越多的关键任务协作提供动力,可靠性成为了我们的核心。
对可靠性的需求促使我们对部署系统进行了全面的改造,从而形成了前面描述的基于百分比的部署系统。在幕后,我们继续使用快速部署和原子部署,但我们改变了部署方式。整个系统按层级更改,再加上更好的监控和工具,让我们有能力在BUG影响到所有用户之前就发现并减轻BUG。
然而这也不是最终形态,我们还在通过更好的工具和自动化来不断改进这个系统。敬请关注未来更多关于这些方面的文章。
原文
https://slack.engineering/deploys-at-slack-cd0d28c61701
参考阅读:
JDK 14发布,空指针错误改进正式落地
新项目用 Rust 还是 Go ?
如何快速定位 Redis 热 key?
dubbo-go 1.4.0 版本发布,支持 K8s 注册中心、rest 协议
从lstio的角度谈微服务的一些误区
可轻松管理大内存,JDK14外部内存访问API探秘
本文由高可用架构翻译。技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。
高可用架构
改变互联网的构建方式
长按二维码 关注「高可用架构」公众号