分享免费的编程资源和教程

网站首页 > 技术教程 正文

instagram如何实现持续部署?

goqiw 2024-09-03 21:07:31 技术教程 51 ℃ 0 评论

我们每天都要在Instagram改进后台代码30到50次,但工程师们只在极少数的情况下需要将这些修改上传到主服务器上进行部署,但大部分情况下代码可以自我改进以达到预期的效果,无须人为干涉。这可能听起来不可思议,但持续部署早已开始应用。这篇文章将讲述我们是如何实现持续部署,并让它协调地运行。

为什么这么做?

对我们来说,持续部署有很多优势:

  • 它使我们工程师任务量大大减少。现在那些工程师不必每天局限于固定时间来进行多次部署他们一天的集成工作,相反,我们可以在任何时间进行自动部署。这意味着不仅仅可以快速地重复进行修改测试,并且能自动部署到生产环境,所以我们的工作效率将大大提高。

  • 它使识别不良commit变得更加容易。原来需要十多个甚至上百个commits去找一个bug,现在库的范围能缩小到来两到三个,有时甚至能确定到某个具体commit环节。这对于工程师们来说是天大的福利,因为通过获得的数据反馈就能精确确定bug是何时被检测出来的,以确定在那个时间段正在部署哪个commiy,这样就可以确定问题所在,并进行调试了。

  • 由于不良commit能被准确定位并快速处理,整个系统就不会因为修改小部分而耽误了整体的运行,引起一些其他的问题或延迟。这样我们就可以干净利落地处理运行出现的问题了。

应用

我们在结构上使用迭代的方法,很大程度上让持续部署变为可能。我们不断修改当前机制,直到它达到持续部署的要求。下面是在使用持续部署前的工作原理以及之后的测试运行机制。

  • 使用持续部署之前是怎么工作的?

在使用持续部署之前,工程师需要特别将集成好的开发部分进行部署。在他们进行修改调试之后,必须亲自部署,不然直到下一个工程师这么做之前,这些修改无法在虚拟环境下进行测试。在全局测试之前,工程师希望能进行小规模的测试,所以他们先以一台机器进行部署,并进入那台机器检查运行记录,之后再进行所有终端的部署。所有部署由Fabric Script,一个基本的数据库和存储大量部署记录的叫”Sauron”的用户界面实现。

  • 进行金丝雀测试

持续部署的第一步就是进行金丝雀部署,其实也就是写脚本。和之前不同,连续部署将脚本应用到金丝雀机,跟踪记录部分客户的使用情况,并不断咨询使用者们的满意程度,以及决定是否进行全部部署。第二步就是对金丝雀机的一些基本分析:分析出一份脚本,收集并分类了每次请求后HTTP状态码,而且还需要适用硬编码率的阈值(比如,5xx的状态码小于0.5%,2xx的状态码不能小于90%)。然而,它只能警告用户数据是否在阈值以内。

我们已经有一个测试集,但只能在工程师的开发机器上运行。代码审阅者无法确定修改的环节最终在虚拟环境下的测试结果,因此他们只能盲目的通过测试,等待在虚拟环境下出现问题。所以我们只能设置好Jenkins,在主服务器上测试各个commit,并将结果记录到Sauron上。Sauron会记录最近一次无误的commit,所以在部署时会自动提示选择刚刚测试好的那个commit,而不是上次进行部署的。

和我们相似,Facebook用Phabricator(http://phabricator.org/)进行代码审阅,并结合了一个叫”Sandcastle”的持续集成系统。我们每次进行修改或更新时也使用Sandcastle进行测试并产生结果。

  • 最终达成自动化

为了达成自动化,我们必须先做好以下基础工作。首先加一些部署的状态(运行中,运行完成,错误和终止),并做好警告的脚本,以防之前的部署不是运行完成状态。我们还要在用户界面添加终止按钮,以便将状态变成“终止”,并让脚本偶尔检查状态并进行反馈。我们同时也加入了对于全部commit的记录;不像先前Sauron只记录最近一次无误的commit,现在Sauron需要记录在主服务器上每一个环节,而且可以随时查看每一个环节commit的测试状态。

接下来就是自动进行剩下的需要工程师们进行的决定。第一个决定是部署哪一个commit。一开始的算法一定是尽可能少地选择通过测试的commit,最多不可超过三个。如果每一个环节都无误,那么每次需要选择一个未经测试的新commit,最多两个连续还没有通过测试的环节。第二个决定是部署是否成功。如果超过1%主机未能成功部署视作部署失败。

现在来看,正常情况下进行部署简化成了一系列的“是”和“否”的选择(是否接受commit的修改,是否进行金丝雀测试,是否继续进行全部部署)。所以我们下一步要做的就是让系统自己回答这些问题,让Jenkins自己运行部署的脚本。一开始,用Jenkins的工程师们需要坐在他们的电脑前进行选择,现在他们根本不需要管理,直接让计算机自己决定。

出现的问题

现阶段,持续部署也并不是那么如意,还有很多问题有待我们解决。

  • 测试失败

工程师们经常进行修改,使测试终止,最终导致到下一步主服务器上的环节测试失败,让这些环节不能进一步部署。值班工程师需要留意这类问题,恢复引起问题的commit,等待恢复中测试通过,然后手动部署整个由于该问题积压的任务,才能继续持续部署。因为每次部署都只能进行一小部分环节,确实让持续部署的优势不再这么明显。这个问题反倒让测试环节变慢,而且不可靠。我们进行了各种优化,争取让12-15分钟的测试缩短到5分钟内,并修复下部测试结构不稳定的问题,让测试结果更加可靠。

  • 任务积压

尽管有所改进,我们依旧有很多需要部署的修改。任务积压大多是由于金丝雀测试失败(正确结果和非预期结果),但偶尔还有其他错误。当问题解决之后,自动部署会将每个环节一个个进行部署,因此,清理积压的任务是缓慢的,而且会推迟新的commit的部署。所以,一旦值班工程师发现了这个问题,他们会介入并将所有积压的任务一并进行部署,而失去了持续部署的优势。

为了改进,当出现任务挤压时,我们将环节按照逻辑分类,并按照分类,一次自动部署多个环节,缩短任务进程。算法设定好每次部署的时间(30分钟),并计算每一个等待部署的环节所需要的时间是否能在剩下的部署时间内完成,在这段时间内能进行几次部署(用硬编码的值),和一次部署能进行几个环节。计算出来最大值,但最大值不可超过三个。这样做让我们在有限时间内尽快多次进行部署,并在合理的时间内部署到每一个commit。

一个具体导致任务积压的原因是,当我们的下部结构增大时,部署速度下降。现在ssh代理固定了整个认证SSH连接的核心,Fab Master处理也固定了管理所有任务的核心;到达了这样的境地,所以解决方案指向了Facebook散布式的SSH系统。

指导原则

那么,如果你要做的东西与我们比较相似,你需要做什么呢?为了让我们的系统正常运行,下面是一些重要的原则,你也可以用到自己的系统里。

1. 测试:

测试集必须迅速,必须合理覆盖,但也不必须完美。这些测试需要经常进行:在编码审阅时,在应用修改时(或者报告错误的环节),以及在应用后部署前。

2. 金丝雀测试:

你需要自动化的金丝雀测试,防止错误的commit部署到所有终端上。谈不上完美,就算一串简单的数据和阈值就已经非常理想了。

3. 正常情况下的自动化:

你考虑所有情况,只需要把已知,常见的情况计算好就行。如果发现有异常,立马停止自动处理,进行人为干预吧。

4. 让用户的体验更舒适:

我认为这种自动化的瓶颈是它可能会让用户和工程师们感到无法控制。解决方法就是提供让用户可以随时看见哪项任务已经做好,哪项正在处理,或者理想状态下,将要处理哪项任务。当然,合理的停止机制也是必须的。

5. 做好失误部署的心里准备:

失误的修改不可避免,但没关系,你只需要尽快找出错误,并再测试即可。

以上是一些其他公司可以应用的建议。持续部署系统没必要非得复杂,只要从以上原则出发,简洁为重,步步精炼即可。

下一步

这个系统目前来说运行正常,但未来的挑战将不会间断,下面是一些我们希望克服的问题:

  • 保证部署速度

Instagram正在迅速发展,伴随而来的是更多修改与更新。我们需要保证部署的速度不会降低,让每次进行部署的commit量控制到最小。一种解决的可能性是应用传送通道,并把部署分成多个阶段。

  • 在Landcastle基础上增加金丝雀测试

随着提交修改的速度的加快,测试失败以及任务堆积会影响更多的开发者。我们想阻止不良commit上传到主服务器并进行部署,所以我们想让金丝雀测试作为Landcastle的一部分来进行应用。在测试通过后,Landcastle会测试生产流量的改变,并依据金丝雀阈值来决定这个commit通过还是需要修改。

  • 更多数据

我们想进一步提高金丝雀测试的错误检测能力,我们决定收集并检查更多的数据,比如检查每一个函数响应代码。我们同时也摒弃了先前静态的阈值,而从对照组的计算机上收集实验数据,并和金丝雀测试收到的数据加以对比。

  • 优化检测系统

如果能减小那些没有被测试出来的不良commt对全局的影响,那就再好不过了。我们可以不像原来那样先对一个机器测试,再应用全部;现在在单个测试和全体应用之间增加多个阶段(分成好几个集或者区域),再进行下一步之前检查是否合格。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表