我是LinkedIn的SRE,我把LinkedIn搞挂了

1,703 阅读12分钟
原文链接: mp.weixin.qq.com
作者 | Katie Shannon 译者 | 无明 作为 LinkedIn 的 SRE,我在一次应用部署并发起回滚命令后,一系列的后续事件让 LinkedIn 网站瘫痪了 1 个多小时。

三年前,22 岁的我拿到了计算机科学(CS) 学士学位,并加入 LinkedIn。在我的最后一个学年,一名招聘人员通过我的 LinkedIn 个人资料找到了我,并向我介绍 SRE 职位。当时我并不知道 SRE 是什么,但还是决定去试一试。我通过了面试,并得到了人生的第一份工作。我知道,在 LinkedIn 这样的公司工作应该让人感到开心,但究竟什么是 SRE,我将在这里有怎样的表现?

什么是 SRE?

虽然 SRE 已经存在了好多年,但仍有很多人不熟悉这个角色,就像当初我刚从学校毕业时那样。在 LinkedIn,我们通过 3 个核心原则来定义 SRE:

  • 站点运行和安全:我们需要确保站点按照预期运行,并且用户数据是安全的。

  • 赋予开发者所有权:需要集体协作来确保 LinkedIn 代码的可靠性,并且系统是可扩展的。

  • 运维是一个工程问题:人们倾向于将运维视为手动工作,但 LinkedIn 致力于对日常运维问题进行自动化。

所有这些定义和核心原则都很好,但 SRE 对我来说意味着什么呢?很快,我发现有几件事确确实实让我吃了一惊。

首先,对于“站点运行和安全”这一点,我们该如何确保网站始终正常运行?我们有轮班待命的工程师,他们能够解决现场问题,并且提供 7*24 的服务。我很快就要为我的团队填补这个轮班待命的角色。如果凌晨 3 点出现问题,我会收到一个电话,并及时将问题解决掉。因为之前从来没有遇到过这样的情况,我对轮班待命感到非常犹豫。LinkedIn 还有很多我以前从未使用过的自定义工具,操作这些工具所需的知识量也令人生畏。

为了赋予开发人员所有权,我必须与团队成员和开发人员保持良好的关系。当我环顾我加入的第一个团队,我感觉自己是个异类。

SRE 团队中跟我一个年纪的人很少,很少有人拥有 CS 学士学位,没有人像我一样经验不足,也没有女性工程师。跟我一起毕业的同龄人没有成为 SRE 工程师,他们大多数都成为了开发者。这让我开始思考我应该处在什么样的位置上、为什么我会去承担一个之前没有经历过的角色,以及其他人与我有什么不同。最后,我想到了一些东西。“运维是一个工程问题”意味着我能够通过编写代码来解决工程问题,而且我非常乐于编写代码。

在 LinkedIn 工作了几个月之后,我开始适应 SRE 这样的角色。我的团队负责移动应用程序和桌面主页,因此我们需要面对大量的用户流量。我沉下心学习所有的自定义工具,并开始感觉得心应手。令我感到惊讶的是,我在轮班待命时发现自己处理事情非常高效。在我的第一次轮班待命体验中,我诊断出了一个问题,并将它修复。当时,SRE 副总裁表扬了我,我到现在还保留着那个聊天屏幕截图。

我开始变得越来越自信,与我的同事相比,缺乏经验的自我意识开始没有那么强烈了,而且我能够与他们建立良好的工作关系。我继续进行编码自动化,而且能够将一个全新的移动 API(Voyager)部署到生产环境中。这是对我们移动应用程序的一次彻底的改革,也是我能够胜任 SRE 角色的最有力的证据。我可以向我的父母和朋友们展示新的应用程序:“看,我做到了”!我真的开始感觉自己找到了方向,直到发生了那个事故。

   事故   

在 LinkedIn 工作了大约一年后,Voyager 团队的一名开发人员要我将应用部署到生产环境。在当时,这是非常正常的行为。作为一名 SRE,我非常了解我们的部署工具,所以可以轻松地帮助开发人员做好这件事。当我将代码部署到生产环境时,我们发现新代码导致移动应用程序上的资料页面不正常。因为查看他人的个人资料是 LinkedIn 的一个很重要的应用场景,所以我想尽快修复这个问题。我发起了一个自定义回滚命令,以便将错误代码移出生产环境。回滚成功后,我查看了 Voyager 的健康检查,一切看起来都很正常。

SRE 领域有一种说法:“对于运维来说,每天都是星期一”。意思是我们的系统始终处于不断变化的状态,我们的团队需要随时待命,以解决任何时候都可能冒出来的问题。这天发生的事故是一个很好的例子,因为没有人能够访问 LinkedIn 主页。进一步调查发现,没有人能够通过包含 linkedin.com 的 URL 访问任何页面。我们很快就发现流量层挂掉了。流量层负责将浏览器或移动应用程序发出的请求路由到后端的服务器上。由于它已经挂掉了,所以无法路由流量,也无法完成任何请求。虽然这个问题确实影响到我的团队所负责的服务,但我们无法控制流量层,所以我们退后一步,让他们来调试问题。

在流量团队调试问题 20 多分钟后,我注意到 Voyager 的行为变得非常奇怪。健康检查恢复到健康状态,但在几秒钟后又切换到不健康状态。通常应该是处于其中一个状态,而不是在两个状态之间来回切换。我登录了 Voyager 主机,并发现 Voyager 已经完全过载,并且没有响应——它影响到了整个流量层。

一个仅为移动应用程序提供数据的 API 是如何影响到整个网站的?流量层与 LinkedIn 其他服务之间存在某种信任协议,如果一个服务表明自己是健康的,流量层就会为该服务提供连接,并期望在合理的时间内收回连接。然而,Voyager 说自己是健康的,但实际上不是,所以当流量层给了它一个连接时,永远无法回收,并最终囤积了整个连接池中的连接。流量层所有的鸡蛋都放在了 Voyager 的篮子里,Voyager 无法交还这些鸡蛋,这让流量层变得毫无用处。

我们知道必须重新启动 Voyager 才能将所有连接返回给流量层。在发出重启命令后,部署工具确认重启成功,但实际上,工具无法重启服务。由于我们不能相信部署工具,因此我们必须手动登录每个 Voyager 主机来终止服务。最后,流量层恢复了,我们的补救奏效了。

数百名 LinkedIn 工程师开始质疑一个问题:“为什么会发生这样的事情”?这个问题是我在 LinkedIn 工作 3 年半当中见过的最糟糕的一个问题。在 1 个小时 12 分钟内,没有人能够通过 linkedin.com 访问网站。经过几个小时的调查,我们发现造成这个问题的根本原因是我。

那天早些时候,当我发出回滚命令时,我的首要任务是尽快将包含 bug 的代码从生产环境中移除。为此,我重写了回滚命令,让它更快完成回滚。通常,部署以 10%的批次进行——因此,如果有 100 台 Voyager 主机,则一次只部署 10 台。然后,在前一批完成部署后,部署接下来的 10 台,并以此类推。我重写了命令,将批次设置为 50%,这意味着一次有一半的主机会停机。剩下的另一半主机无法处理所有流量,进入超负荷和完全无法触及的状态,同时变成了完美风暴的催化剂,使网站的其余部分也失效。

完美风暴

我发出这个回滚命令,同时犯下了大错。我将有问题的代码引入到生产环境中,我感到很紧张,同时又让这种压力影响了我的决策。但如果我没有修改回滚命令,最多只会导致 5 分钟的停机。实际上,要让整个网站挂掉确实需要很多因素,但不幸的是,还有很多其他外部因素导致了这个问题。

首先,我们有一些工具可以捕捉代码中的问题,但由于它最近一直在返回不可靠的结果,开发人员决定绕过它,直接将代码部署到生产环境中。然后,一旦代码进入生产环境,我们的部署工具就会报告说它能够成功重启 Voyager,而实际却没有。总的来说,那天,我们的工具不仅没有帮到我们,反而给我们挖了个坑。

正如我所提到的,Voyager 当时也才刚被引入到 LinkedIn。我们使用的是一个全新的第三方框架,LinkedIn 的其他很多地方都没有用过这个框架。事实证明,这个框架存在的两个严重 bug 加剧了这个问题的发生。首先,当应用程序进入过载状态时,健康检查机制无法正常工作。这就是为什么 Voyager 一直报告自己处于健康状态,但实际上却不是。另一个 bug 是,当应用程序处于过载状态,停止和启动命令将无法正常执行,但它会报告命令已生效。这就是为什么工具报告重启是成功的,但实际上并没有。这个事故暴露了我们之前没有考虑到的问题,这些问题在之前可能不存在,但随着技术栈变得越来越复杂,随着规模的不断增长,这些问题就会出现。

最后,如果当天早些时候没有误诊故障,那么这个问题持续的时间可能会大大缩短。比如,如果我的团队没有回退并让流量团队来诊断问题的话,或许结果会不一样。

   善后   

是我导致了网站瘫痪,这一事实让我很难接受。但我不得不重新开始找回信心,感觉就像一头撞在了墙上。所幸的是,LinkedIn 的文化是针对问题,而不是人。每个人都明白,如果一个人可以导致网站瘫痪,那么肯定还有其他很多问题存在。因此,我们的工程组织没有将责任归咎于我,而是做了一些改变,以防止再次发生这种情况。

首先是暂停整个网站的变更。除非是关键修复,否则不允许任何代码部署。经过数月的工程努力,我们的网站变得更具弹性。我们还对工具进行了全面的重新评估,因为那天它不仅没帮到我们,还给我们带来了麻烦。

我们最终为两个工具系统制定了黄色代码。黄色代码是指我们的内部声明:“出了点问题,我们需要谨慎行事”。声明黄色代码的团队将所有精力都放在修复问题而不是开发新功能上。这是解决问题的一种开放而诚实的方式,而不是将问题掩盖起来。我们后来有了一个新的部署系统,它更易于使用,而且更加可靠。

当然,这次经历也改变了我个人的想法。最开始我对自己感到非常失望,在搞挂网站后,我不知道该如何面对我的同事,并且还能得到谅解。但团队支持我,并且我已经学会了在发生事故时如何保持冷静。在经历这次事故之前,我在面对这样的事件时肯定会感到慌乱和压力。我现在意识到,三思而后行比鲁莽行动要好得多,否则可能会导致更大的站点瘫痪。如果我在发出回滚命令之前停下来喘口气,或许会再想想能不能用这么大的批次。自从这次事故发生以来,我已经学会了如何在紧张的氛围中保持冷静

事件发生后,我还在工作中找到了更多的社区同僚——特别是从事 SRE 的其他女性,我可以跟她们聊聊我的疑虑和担忧。后来发展成为 LinkedIn 现在的 Women in SRE(WiSRE)小组。因为这些女性 SRE,并看到了自己在 SRE 领域找到了一定的位置,我感觉自己确实属于 SRE 组织。

最后,我意识到,有时候“搞”破坏也是有好处的。这个问题导致了大量的技术改造,这使得 LinkedIn 变得更加可靠。我已经把这个想法铭记于心,并加入了 LinkedIn 的另一个 SRE 团队——Waterbear。这个团队故意将故障引入到应用程序中,以观察它们的反应,然后使用这些信息让它们变得更具弹性。我感到非常兴奋,因为我把工作中经历的最低潮转变成对弹性的热情。

英文原文:https://venturebeat.com/2018/10/13/what-i-learned-by-bringing-down-linkedin-com/