返回 登录
0

Instagram 的持续部署实践

原文: Continuous Deployment at Instagram
作者: Michael Gorven
翻译: 孙薇
责编: 钱曙光,关注架构和算法领域,寻求报道或者投稿请发邮件qianshg@csdn.net,另有「CSDN 高级架构师群」,内有诸多知名互联网公司的大牛架构师,欢迎架构师加微信qshuguang2008申请入群,备注姓名+公司+职位。

在Instagram,我们每日部署后端代码的次数达30-50次,只要有工程师将修改内容提交到主服务器,部署就会进行,而且在大多情况下无需人工介入。这听起来也许很疯狂——特别是在我们这样规模下,不过效果的确很好。本文会描述这个系统的实现方式,以及让它顺利运行的方式。

为什么这样做?

对我们来说持续部署优点众多:

  1. 让工程师们效率更高:每天执行部署的次数无拘于固定的几次,在任何时候想要部署都能执行。这意味着我们所浪费的时间更少,迭代变更的速度更快。

  2. 更容易找出不良提交:无需在数十乃至数百个提交中寻找故障起因——范围被锁定在单个、最多两到三个提交上。对之后才找到问题并回头 debug 的需求,这种做法也是非常奏效的。可通过出现问题的指标或数据来定位准确的故障起始时间,并找出在该时段内所部署的变更提交。

  3. 能够快速检测到不良提交并将之处理掉,从而摒弃在主服务器上造成无法部署的混乱情况,更不会耽误到其它不相关修改的提交工作。因而我们总是能快速将重要的修复更新部署完成。

实现

这种实现的成功在很大程度上取决于构建的迭代方式:这个系统不是另行构建并突然切换过去的,而是在现有机制上慢慢发展起来,最终实现了持续部署。

之前的工作方式

在持续部署实现之前,工程师都是随机部署变更的。他们会载入变更的内容,如果想要快速部署变更,就会立即提交上线;如果不着急,就等其他工程师的变更也载入后一同上线。工程师们需要知道如何预先执行小范围内的测试:他们会先针对一台机器实验,登录那台机器并查看日志,然后再运行针对整体机群的二次提交上线。这些都是通过 Fabric 脚本来实现的,我们有一套名为“Sauron”的基础数据库与 UI 来存储提交上线的日志。

Canary 与测试

第一步:加入 canary 部署,在 canary 测试机器上提前写入简单的脚本,引导执行所需的工作。我们不再针对一台机器执行单独上线,而是将脚本部署到 canary 机器、跟踪日志、询问是否该继续执行整机群部署。接下来对 canary 机器执行一些基础分析:通过脚本收集各个请求的 HTTP 状态代码,对其分类并使用硬编码嵌入百分比阈值(比如5xx 不足0.5%,至少90% 2xx等),不过这种做法只会在阈值超出时对用户发出警告。

我们已经有了测试套件,但只在工程师自己的开发机器上运行。在审查代码时,该提交是否通过测试只能听信开发者的一面之辞,我们无法知道最终提交到主服务器上的测试结果。因此我们安装了 Jenkins 对提交到主服务器上的新变更执行测试,并向 Sauron 报告结果。Sauron 会持续追踪通过测试的最新提交,并在上线时建议加入这类提交,而不是加入实际最新的提交。

Facebook 使用 Phabricator 进行代码审查,有一个叫做 Sandcastle 的持续集成系统可以与 Phabricator 良好集成。每当创建或更新 diff 时,我们会通过 Sandcastle 来运行测试,并将结果发给 diff。

自动化

为了实现自动化,我们先要奠定一些基础:为上线增加状态(运行中、完成、故障),设定脚本在前一个上线提交未达到“完成”时发出警告;还在 UI 界面上增加了中止按钮,可将状态修改为“终止”;并设定脚本不定期检查状态、作出反应;此外我们还增加了完整的提交追踪机制:不再只是通过 Sauron 了解最新通过测试的提交,而是对主服务器上的各个提交进行记录,并获取具体每个提交的测试状态信息。

图片描述

然后,我们将剩余所有需要人工执行的决策全部自动化,包括:

第一个决策是:上线哪些提交。起初的算法是选择那些通过测试的提交,每次上线的提交数量尽可能少——不超过3个。如果每次提交都通过了测试,那么每次只会选取一个新的提交;如果有测试没有通过,最多会有连续两个提交。

第二个决策是:上线是否成功。如果有超过1%的主机无法部署,这次上线就会被认为是失败的。

当一切正常时,这时候执行上线仅需回答数次“是”,包括选取系统建议的提交、开始 canary 测试,继续整个机群的部署。因此我们将回答过程自动化,让 Jenkins 运行上线脚本。起初的实现需要工程师监控,直到后来不再需要人工监控。

问题

在这个阶段的持续部署中,过程并不是完全平滑的,其中有几个问题。

测试故障

经常会有变更测试出错,导致后续的提交测试卡住,测试无法进行,造成部署中断。因此需要有人随时待命,注意到这类情况,恢复出错的提交,等待测试通过,然后在自动化运行继续前,手动提交整个日志。这种问题抵消了持续部署的最大优势之一,使得每次上线仅能提交极少几个变更。这里的问题在于测试速度太慢,同时缺乏可靠性。我们进行了各种各样的优化,让测试时间从12-15分钟缩短到5分钟,然后修复了造成测试缺乏可靠性的基础架构问题。

工作积压

尽管做了这些优化,我们定期还是会有需要部署的变更积压下来。最常见的原因是 canary 测试故障(包括漏报和误报),间或还有其他问题,在问题解决之后,自动化才能继续每次部署提交一个变更的工作;因此,在载入新变更之后,需要有一段时间用来清理积压的任务,这会带来严重的延迟。此时,我们经常需要有待命人员介入,立即对所有的积压任务执行部署,这种做法抵消了持续部署的另一个最大优势。

为了改进这个问题,我们在选择提交的逻辑中实现了处理积压任务的逻辑,在出现积压时自动部署多个任务。这个算法是基于:设定一个目标时间(30分钟)来部署每次提交任务。针对队列中的各个提交任务,系统会计算达成目标时间所剩余的时间,在该时间内能够完成的提交上线数量(使用硬编码值),以及每次上线必须部署的提交数量。系统会选取提交/上线的最大值,但每次不超过3个。这样一来每次所提交的上线任务就能达到合理范围内的最大量,从而在合理的时间内完成各个提交任务。

积压任务有一个原因就是:随着基础设施的规模增长,上线速度逐渐变慢,瓶颈在于 ssh-agent 与整个 SSH 连接的验证核心挂钩,而 fab 主进程又与管理所有任务的核心挂钩。这里的解决方案是:切换到 Facebook 的分布式 SSH 系统上。

指导性原则

想要实现与我们类似的部署,需要做些什么?下面的几个指导性原则让我们的系统运作良好,你可以试用看看。

  1. 测试: 测试套件速度要快。需要有合适的覆盖范围,但无需尽善尽美。需要经常执行测试:代码审查时、变更载入前(在故障时最好停止载入)及载入后。

  2. Canary: 需要可自动化执行的 canary 测试,以免在部署到整机群时出现不良提交。这个测试无需完美,即便只是一套简单状态与阈值就够用了。

  3. 让常例自动化: 无需自动化所有场景,只需将已知的常例自动化即可。如有异常发生,请停止自动化进程并请求人工介入。

  4. 让人员感到舒适: 我认为这类自动化的一大障碍就是大家感觉不在状况、失去控制时。明确来说,系统需要提供良好的可视化界面,包括完成的工作、正在进行的工作,最好还要包括即将进行的工作,此外还需要良好的中断停止机制。

  5. 预期不良部署: 不良变更会出现,但不是什么大问题,只需快速检测到并执行回滚。

以上这些都是其他公司也能实现的一些东西,持续部署系统无需复杂,从简单的系统开始,注重上面几条原则,再进行完善即可。

下一步

目前对我们来说这个系统运行良好,但后续我们还会面对一些挑战,还有一些想要执行的优化。

  • 保持快速执行:Instagram 正在迅速成长,同样地提交率也会继续增长。我们需要执行快速上线,以便保持每次上线所提交的变更数量不会太多。一种可能是将上线拆分为多个阶段,实现流水线作业。

  • 增加 canary 测试:随着提交率增加,canary 失败与任务积压会影响到越来越多的开发者。我们希望将不良提交扼杀在 canary 测试阶段,不让其影响到主服务器;因此我们将 canary 作为 Landcastle 实现的一部分。在测试通过后,Landcastle 才会在生产环境中测试变更;如果未能通过 canary 阈值,则不会载入。

  • 更多数据:我们想要改善 canary 的故障自检出能力,正计划收集并统计更多状态,比如预览功能的响应代码。我们也在测试从一系列控制机器上收集状态,并与 canary 状态(而不是当前的统计阈值)相比较。

  • 提高检测:降低未被 canary 测试捕获的不良提交所带来的影响。不再采用单台机器测试,然后部署到整个机群上的方式,而是在之间加入了更多阶段(集群或区域),在继续之前检查指标水平。

由CSDN重磅打造的2016中国云计算技术大会(CCTC 2016)将于5月13日-15日在北京举办,大会特设“中国Spark技术峰会”、“Container技术峰会”、“OpenStack技术峰会”、“大数据核心技术与应用实战峰会”等四大技术主题峰会,以及“云计算核心技术架构”、“云计算平台构建与实践”等专场技术论坛。80+位一线互联网公司的技术专家将到场分享他们在云计算、大数据领域的技术实践,目前大会剩票不多,欲购从速。详情请点击CCTC 2016大会官网

评论