保持冷静,继续升级
Elasticsearch Lingo
故事
惨痛教训
轻松获得经验教训
总之
额外课程:拥抱你的错误
如果您更喜欢听这篇文章而不是阅读它,请滚动到底部查看这篇文章的来源谈话。
作为一名开发者,遇到问题总是难免的,但一旦遇到,事情就变得非常棘手。接下来要分享的故事,发生在我之前工作单位 Kenna Security 的那段时间。那次事故通常被称为“2017 年 Elasticsearch 宕机”,也是 Kenna 经历过的最严重的一次宕机。
我们在全面宕机和服务降级之间徘徊了近一周。然而,这段经历教会了我们很多东西,让我们知道如何更好地准备和应对未来的升级。它也增强了我们团队的凝聚力,并凸显了团队合作和领导力在高压环境下的重要作用。我们学到的教训将永生难忘。分享这个故事,我希望其他人能够从我们的经验中汲取教训,并在下一次进行重大升级时做好更充分的准备。
Elasticsearch Lingo
在开始之前,我想简单解释一下我将要使用的一些 Elasticsearch 术语,以便更容易理解。
- 节点:为了这篇文章的目的,每当我说节点时,我指的是运行 Elasticsearch 的服务器
- 集群:节点组合在一起形成集群。集群是所有节点共同协作以处理 Elasticsearch 请求的集合。
- Elasticsearch 2.x -> 5.x:在本文中,我将讨论如何从 2.x 升级到 5.x。尽管版本号增加了 3,但 Elasticsearch 5 实际上只是从 2 升级了一个版本。当时,Elasticsearch 决定更新其版本的编号方式,以与其底层语言保持一致,因此版本号增加了 3。
好了,现在开始讲好东西!
故事
那是2017年。当时正值三月下旬,我们庞大的21节点Elasticsearch集群即将升级。升级代码库的准备工作已经进行了数周,每个人都兴奋不已。上次升级Elasticsearch时,我们看到了巨大的性能提升,我们迫不及待地想看看这次升级会带来哪些好处。我们选择在3月23日(星期四晚上)进行升级。
我们经常选择周四晚上进行升级,因为如果需要解决任何问题,我们都可以有一个工作日来处理,而不必工作到周末。
升级涉及:
- 关闭整个集群
- 升级 Elasticsearch
- 为应用程序部署我们的代码更改
- 重新打开集群
所有这些步骤都顺利完成,集群启动后,我们立即将应用程序退出维护模式,并开始运行新集群。然而,当我们开始向集群发送请求时,我们开始在某些节点上看到 CPU 和负载峰值。
这确实有点让人担心,但由于集群仍在进行内部平衡,所以我们就当做这件事处理,然后就此打住。接下来是3月24日,星期五。
早上醒来,我们发现一些 Elasticsearch 节点在夜间崩溃了。我们不太清楚原因,但推测是集群试图平衡自身造成的。我们重启了崩溃的节点,并继续监控集群。上午 9 点左右,网站流量开始回升,我们发现 CPU 峰值越来越高,最终整个集群瘫痪了。
到了这一步,我们再也无法否认了,意识到情况非常不对劲。我们立即进入全面调试模式,试图找出集群突然挂掉的原因。我们开始阅读堆栈跟踪,梳理日志,试图找到任何可能导致所有这些负载和 CPU 峰值的线索。我们尝试用谷歌搜索所有能想到的答案,但一无所获。
到了周五下午,我们决定寻求帮助。我们在 Elastic dicuss论坛上发帖,看看是否有人知道发生了什么事。
我们不知道会不会有人回答。很多人都知道,在像我们这样的论坛或 Stackoverflow 上提问,要么会得到答案,要么可能只会得到一堆空空如也的回复。幸运的是,我们得到的是前者。令我们惊喜的是,有人主动提出帮忙,而且不是随便什么人,正是 Elastic 的高级工程师 Jason Tedor!
说实话,当我们发现 Elasticsearch 的核心开发人员之一正在处理我们的问题时,我们真的有点惊讶,有点激动。帖子里的讨论变成了一封私人邮件,我们分享了所有能找到的数据,帮助 Jason 弄清楚集群出了什么问题。这种反复沟通持续了整个周末,并持续了接下来的一周。
我不想粉饰太平,那段时间我们团队处境非常艰难。

我们每天工作超过 15 个小时,试图找出导致所有这些问题的原因,同时竭尽全力确保应用程序正常运行。但无论我们做什么,这艘船还是不断下沉,每次 Elasticsearch 宕机,我们都不得不重新启动它。
鉴于 Elasticsearch 是 Kenna 平台的基石,正如您可能想象的那样,客户和管理层对这一切并不满意。

我们的工程副总裁不断接到电话和短信,询问更新情况。由于看不到任何解决方案,我们开始讨论“回滚”这个词。是时候回滚了吗?很遗憾,我们没有这方面的计划,但这应该不难,对吧……?哦,我们的假设真是错得离谱。我们很快发现,一旦升级,就无法真正回滚。为了“回滚”,我们必须建立一个全新的集群,并将所有数据重新索引(复制到)其中。
我们估算这需要 5 天时间,这可不是什么好消息,因为我们已经宕机了将近一周。然而,由于没有其他好的选择,我们只好用 Elsaticsearch 2.x 搭建了一个集群,开始费力地将所有数据重新索引到其中。然后,3 月 29 日,星期三,终于到了。
此时,团队虽然精疲力竭,但仍在努力让 Kenna 恢复正常。就在这时,我们终于收到了期盼已久的消息。帮助我们的 Elasticsearch 工程师 Jason 发来消息,说他发现了一个 bug。
哈利路亚!!!🙌 原来,他发现的 bug 是在 Elasticsearch 源代码中,而且多亏了我们提供的信息,他才找到了这个 bug。他立即为 Elasticsearch 发布了补丁,并提供了一个临时解决方案,让我们在补丁合并并正式发布之前使用。当我实施了这个临时解决方案后,情况发生了翻天覆地的变化,我们的集群立即稳定了下来,如下图所示。
那一刻,我们欣喜若狂,我想我们整个团队都哭了。这场持续了近一周的战斗终于结束了。然而,即使事件结束了,学习才刚刚开始。虽然这可以成为一个在酒桌上讲述的精彩故事,但正如你们所想,我们的团队从那次升级中学到了一些事情,而这些经验正是我想与你们分享的。
惨痛教训
1. 制定回滚计划
进行任何类型的升级时,您都必须了解在出现问题时回滚的具体操作。您可以在线回滚软件吗?如果无法在线回滚,您将如何回滚到原始版本?回滚需要多长时间?难度如何?如果回滚需要很长时间,您可能需要提前做好准备。
升级时要考虑最坏的情况,这样你才能做好万全的准备。这样,如果真的出现问题,你就能有一个计划。作为一名软件工程师,专注于代码真的很容易。Elasticsearch 升级的代码可以通过一个简单的恢复 PR 来回滚,但我们从未考虑过升级后软件和数据本身是否可以回滚。
2. 进行性能测试
我们进行这次升级时,就假设它会和上一次一样好。软件只会越来越好,不是吗?错了!但正因为这个盲目的假设,我们从未进行过任何严格的性能测试。我们验证了所有代码都能在新版 Elasticsearch 上运行,但仅此而已。新软件的性能测试,永远、永远都要进行。
我不在乎你升级到什么软件,也不在乎它有多稳定、使用范围有多广,但你必须对它进行性能测试!虽然软件整体上可能对 99% 的用户来说都很好、很稳定,但你永远不知道你的用例是否是那个有 bug 或未优化的小部分。当我们升级到 Elasticsearch 5 时,许多公司都在使用 Elasticsearch 5,但没有一家遇到我们遇到的那个 bug。自那次故障以来,我们实施了一项测试策略,允许我们向多个索引发出 Elasticsearch 请求,以便在进行集群更改时比较性能。
3. 不要忽视小的警告信号
由于这件事发生在升级之前,所以我没有在文章中提及。最初为这次升级进行代码变更时,我们所有的测试都是在本地进行的。在那次测试中,Elasticsearch 在本地环境中多次崩溃。我们再次认定,这不可能是升级软件的问题。一定是我们的设置或配置出了问题。我们调整了一些设置使其稳定,然后继续为升级进行代码变更。
事后看来,这或许是最大的失误。但我们对软件的信任以及过往经验严重扭曲了我们的偏见,以至于我们从未意识到问题出在 Elasticsearch 上。如果你发现一些细微的警告信号,就应该调查,深入挖掘。不要只是让它恢复正常就继续往下看。在忽略警告信号之前,务必先了解具体情况。
轻松获得经验教训
这给了我们三个教训。不幸的是,所有这些教训都是在这次升级过程中没有遵循的,这让我们吃尽了苦头。现在我想换个话题,因为接下来的三个教训在升级过程中进展非常顺利。回顾整个经历,我很容易发现,如果接下来的三个教训没有顺利实施,升级的后果会更加严重。
我肯定你们有些人会想,不好意思,情况更糟了?你们都瘫了将近一周了,怎么会更糟?相信我,情况本来可能会更糟,我想接下来的三节课会让你明白这一点。
4.利用社区
永远不要低估在社区里能找到的帮助。无论是在线上,还是直接打电话给以前的同事,寻求帮助有时都会很困难,也很令人害怕。没有人愿意问出那种只有一行字就能回答的问题,但不要因此而却步!与其浪费一天甚至更长时间去追尾巴,难道你不想得到那一行字就能回答的问题吗?
这是我觉得我们团队在这次升级中做得非常好的一个方面。升级后的第二天,我们立即通过在Elastic 讨论论坛上发帖向社区寻求帮助。我花了大概一个小时才把问题写下来,并收集了所有相关信息,而这几乎是整个升级过程中最有价值的一个小时,因为正是那篇帖子让我们得到了答案。
很多人会把求助社区作为最后的手段。我在这里告诉你,别等了!别等到山穷水尽,别等到经历了数天的宕机。在你走投无路、走投无路之前,赶紧问吧!你可能会让自己和你的团队免于大量的挣扎和挫折。我很自豪我们几乎立即求助于社区,而且它确实奏效了。当然,它可能不会每次都有回报,但问问自己为什么不试一试呢?最坏的情况是,它能帮助你理清所有关于调试工作的思路。
5. 领导和管理支持至关重要
在任何高风险的软件升级或变更过程中,支持工程师的领导和管理团队都至关重要。纵观整个故障事件,很容易将焦点集中在工程师以及他们为修复和处理升级所做的一切工作上。我们工程师之所以能够出色地完成工作,关键原因之一在于我们的工程副总裁。
这次事故中,不仅有奋战在一线的工程师,我们的工程副总裁也全程陪伴着我们。事故发生期间,他每天熬夜到深夜,黎明时分就上线。他不仅在技术上提供帮助,更是我们的啦啦队长和捍卫者。他接听了所有来自高层管理人员的电话和问题,让我们能够专注于解决问题。我们无需担心与任何人沟通或解释,他全程负责。
我们的副总裁也始终坚信我们能解决问题。他始终保持着冷静、沉着和沉着的特质,而这正是我们不断前进的动力。他最喜欢的一句话是“向前失败”(Fail Forward),在这次宕机事件中,他体现得淋漓尽致。如今,“向前失败”已成为Kenna工程文化的基石之一,我们用这个故事来佐证。如果我们换了一位副总裁,我相信事情会截然不同。
所以,各位正在阅读这篇文章的副总裁、经理、高管们,请注意!你们或许不是真正推动代码的人,但我保证,在这些情况下,你们扮演的角色比你们想象的要重要得多,也重要得多。你们的反应将为团队其他成员树立榜样。做他们的啦啦队员,做他们的捍卫者。
他们需要你做什么,你就做什么。但最重要的是,相信他们能做到!这种信任将极大地帮助团队树立自信,这对于保持士气至关重要,尤其是在像这样的长期事件中。
6.你的团队很重要
最后,同样重要的是,我想特别强调一下在这次升级过程中与我合作的优秀工程师团队。毋庸置疑,在任何重大软件变更、升级或其他情况下,您的团队都至关重要。
作为一名开发人员,不仅仅是操作电脑,你还需要与人合作。这次宕机事件让我深刻地体会到了这一点。宕机期间,我们三个人每天工作超过15个小时,真是太残酷了!我们经历了书中提到的每一种情绪,从悲伤到愤怒,再到沮丧。但这些情绪并没有击垮我们,反而让我们团结在一起。
这对我来说是一个重要的顿悟时刻,因为它让我意识到,在危机时刻,品格至关重要。你可以教人们技术,可以教他们如何编程,可以向他们灌输良好的架构原则,但你无法教授品格。招聘时,务必仔细观察你面试的人。认真了解他们,评估他们是否是你愿意与之并肩作战的人。当你需要他们时,他们会毫不犹豫地挺身而出吗?如果答案是肯定的,那就雇佣他们,因为品格不是你能教出来的。
总之
至此,我们从这次故障中吸取的教训就完整了。从技术层面来说:
- 制定回滚计划
- 进行性能测试
- 不要忽视小的警告信号
从非技术角度来看:
- 使用社区
- 领导和管理支持至关重要
- 你的团队很重要
说实话,虽然技术层面很重要,但我坚信最后三个教训才是最重要的。我之所以这么说,是因为你可以制定回滚计划,可以进行性能测试,可以留意并调查出现的每一个小警告信号,但最终还是会有出错的时候。在我们的工作中,出问题在所难免。
但如果出现问题,你能够利用社区的力量,并拥有合适的团队和领导团队,就能安然无恙。只要牢记并实践这三个非技术经验,你就能安然度过任何可能出现的宕机或高压情况。
2017 年 Elasticsearch 宕机事件如今在 Kenna Security 声名狼藉,但其严重程度远超你的想象。尽管那次宕机事件对团队造成了巨大打击,对公司业务也造成了巨大损失,但它却帮助我们奠定了 Kenna 工程师文化的基础。它为每个人提供了一个故事,让我们明白这就是我们。那段经历,就是我们!考虑到这一点,我认为这里还有一个额外的教训。
额外课程:拥抱你的错误
我这里说的“您的”指的是您本人,也指您的团队和公司。这次宕机是由于团队失误造成的。我们对此负责,也乐于接受。在我们这个行业,宕机和停机通常是禁忌。一旦发生宕机,通常会有人受到指责,甚至被解雇,我们会写一份事后分析报告,然后迅速掩盖,希望大家都能忘掉这件事。这不应该。
坦然接受中断和错误是我们真正从中学习的唯一途径。与他人分享这些故事并保持开放的态度,对每个人都有益,并将使我们所有人成为更优秀的工程师。下次您即将进行重大升级时,请记住这 6 条经验教训,以便您能够准备好代码和团队,从而尽可能地为升级提供最佳体验。但是,如果确实发生了中断,无论出于何种原因,请坦然接受它,从中学习,然后与他人分享经验。
编码愉快!😃
这篇文章基于我在RubyConf 2019上的演讲,题为 Elasticsearch 5
或者和破产!