高效运维最佳实践:如何做好 On-call 和事故响应?

阅读数:2 2019 年 1 月 9 日

话题:DevOps运维最佳实践

太多的公司所用的 on-call 轮转和事故响应流程让团队成员感到紧张、焦虑、痛苦。特别是,许多优秀的工程师只是由于这个原因而拒掉工作。

并非一定要这样。在 New Relic,我们的开发运维实践让我们得以创建既能够支持系统的快速增长又高度重视系统的可靠性,同时还能保护开发人员免受戏剧性事故和压力的影响的 on-call 轮转和事故响应流程。通过分享我们构建和管理 on-call 轮转和事故响应系统的经验和最佳实践,希望可以帮助其他公司解决类似的挑战,让他们的开发人员和其他实践者的生活能够更轻松。

On-call 策略实战

New Relic 的产品组织目前由 50 多个工程团队组成,包含 400 多名工程师和管理人员,支持超过 200 个独立服务。每个团队都是独立运行的单元;团队自行选择所使用的技术用于编写和维护服务,管理部署、操作运行手册和 on-call 轮转。

我们的工程团队由软件工程师、站点可靠性工程师 (SRE,Site Reliability Engineer) 和工程经理组成。大多数团队至少作为三个服务的主要负责人。通常在他们加入公司后的两到三个月内开始,每一位工程师和工程经理都要加入 on-call 轮换当中。

我们这样做的首要原因是因为这是必须的。New Relic 为全球数千名客户的应用程序和基础设施提供至关重要的监控、警报和商业智能。当客户遇到问题时,不可能把问题拖到第二天解决。虽然我们在美国和欧洲都有工程师,但绝大部分团队都在俄勒冈州的波特兰全球工程总部工作。这就意味着我们不可能像谷歌那样,采用“跟随太阳”的轮转方式,在每日工作结束时,一个地方的工程师把他们的 on-call 职责交给世界各地的其他同事。

1. 采纳并拥抱 DevOps 实践

在 DevOps 作为一种应用开发方法出现之前,on-call 职责通常是由工程师及其他 IT 人员中的一部分人员来承担,例如集中式的 SRE 团队或运营团队。

这些员工——而非实际构建软件的开发人员——对牵涉到他们所监控的服务的事故作出响应。然而,来自 SRE 团队的反馈很少能够到达开发人员的手中。此外,产品负责人通常会选择开发更多新特性,而不是敦促团队偿还技术债务,使产品和服务尽可能可靠。

DevOps 出现的原因之一就是要拆除这些组织竖井。在 New Relic 所采用的这类现代应用程序体系架构中,各种服务组合在一起,形成一个大型的、互连的产品平台,该平台依赖于由云服务,数据库维护器以及错综的网络层所组成的复杂系统——这仅仅是复杂系统组成部分的几个示例。特定的事故响应可能起始于某个团队,但是根本原因则涉及更深一层的服务。

DevOps 支持这样一种观点,即没有哪个团队是孤立的,团队之间必须能够保持交互,并且具有清晰的、文档化的 on-call 流程,以保持这些复杂系统的平稳运行。此外,在一个实践性较强的 DevOps 实践中,如果开发人员需要对他们构建的服务提供支持,那么开发人员在构建服务时会做出更好的决策——他们不能把自己构建的服务抛之脑后,留给其他人。

2. 在团队自治和问责制之间保持平衡

在 New Relic 的大多数团队都采用了一种为期一周的 on-call 的轮换方式,其中一名工程师担任主要响应人员,另一名工程师担任次要响应人员。这样,如果一个团队有 6 个工程师,那么每个工程师每六周就会成为一次主要响应人员。

然而,一个成功的 on-call 流程更加依赖于团队的组成、团队所管理的服务以及对于这种服务团队掌握的集体知识情况。这就是团队自治发挥作用的地方——在 New Relic,每个团队都创建了反映各自需求和能力的 on-call 系统。

让我们来看一下这种方法在实践中的两个案例:

  • New Relic 度量管道团队已经构建的轮转方式,能够始终保证有一个“主要”和一个“非主要”的 on-call 联系人。通过一个 Jenkins 脚本,团队随机轮转非主要的联系人的 on-call 顺序。当事故发生时,如果无法与主要联系人取得联系或主要联系人未对呼叫作出响应,则按随机顺序每次呼叫一个非主要联系人,直到有人响应为止。
  • New Relic 浏览器团队则采用了一个可配置的定制化应用程序,该应用程序每分钟将一名新团队成员轮转到“主要”角色。如果在呼叫某个团队成员时,没有得到立即响应,系统就会轮转到下一个人,以此类推,直到有人对警报作出响应为止。这种方法实际上减轻了团队成员的压力:当问题出现时,如果团队成员没有时间或者觉得还没有好的问题解决方案,只需两分钟的时间就可以轮转到另一个团队成员。

3. 跟踪并度量 on-call 绩效

New Relic 在工程师、团队和群组层面追踪几个维度的 on-call 度量标准:

  1. 每个工程师的呼叫响应数量 ;
  2. 每个工程师被呼叫的时间间隔 ;
  3. 非工作时间接收到的 (发生在正常工作时间之外的呼叫) 呼叫数量。

这些度量标准,以及如何对其作出响应,对于维护一个能够让团队在 on-call 实践中茁壮成长的组织架构至关重要。举例来说,在 New Relic,从 PagerDuty 获取到的警报数据可以让经理和高管们了解到一个团队在给定的时间段内被呼叫了多少次,以及这些警报中有多少是在非工作时间发出的。

跟踪非工作时间的呼叫有助于将注意力放在那些在不可控的 on-call 负荷中苦苦挣扎的团队上。什么是不可控的负荷?在 New Relic,如果一个团队平均每周有多于一个的非工作时间呼叫,那么就认为这个团队有很重的 on-call 负荷。

如果团队的负担过重,就需要考虑让团队将精力集中到偿还技术债务或将工作自动化之上,直到 on-call 的负荷降低为止。或者,像 New Relic 一样,以高级 SRE 的形式为团队提供支持,以帮助团队改进服务。

选择 on-call 模式时需要考虑的问题

On-call 模式不必过于复杂,但它必须确保指定的工程师随时能够对呼叫做出响应,并处理在其职责范围内的事故。On-call 模式应该解决的问题包括:

  • 如何为每次 on-call 轮转选择团队成员?
  • 每次轮转会持续多久?
  • 如果某个 on-call 工程师未能响应呼叫会发生什么?
  • 如果一名工程师无法胜任处理 on-call 呼叫的任务,有哪些可供选择的选项?
  • 同一时间有多少工程师处于 on-call 状态?
  • 多名 on-call 的工程师如何分工?
  • 团队如何处理计划外的轮转和其他不可预见的事故?

对于包含多个团队的大型组织,这些问题的答案也取决于团队自治的程度。DevOps 组织通常都更偏爱更高程度的团队自治,不过有些组织比其他组织更加重视这个概念。

事故响应:当寻呼机响起时发生了什么

一个组织的 on-call 流程是该组织软件质量和可靠性实践的一个关键的方面。另一个密切相关的方面则是其事故响应程序。

事故响应涵盖了各种各样的事件,从普通的到可怕的;如果没有专门的监控工具的帮助,有些事故极有可能会被忽略,而另一些事故则可能会对数百万用户造成影响,成为全国性的头条新闻。

New Relic 将“事故”定义为任何可能对客户造成负面影响的系统的意外行为。

和许多软件公司一样,New Relic 不可能等到事故发生后再制定计划。我们需要迅速有效地采取行动。我们必须有一个清晰的计划,并且时刻做好准备。

1. 在客户之前发现事故

一个成功的事故响应系统的目标很简单:在客户受到影响之前发现事故,最理想的情况是发现并修复它。

作为一个组织,我们的目标是确保我们永远不会等到愤怒的客户在 twitter 上谈论的时候,才发现事故——没有什么比这更糟糕了。我们也希望不会有愤怒的客户给支持人员致电,这也不是我们所希望的。

在 New Relic,我们喜欢说我们“喝自己的香槟”(这比“吃自己的狗粮”要好)。工程团队可以自由选择他们用来构建服务的技术,但有一个条件:服务必须能够被仪表化。这意味着必须有监控和警报。(绝大多数情况下,我们都会使用自己的产品,只有极少数情况例外。)

当然,如前所述,工程团队针对各自管理的服务都有相应的 on-call 轮转机制。良好的监控设置和主动的事故报告,意味着一旦发现问题,就会立刻呼叫工程师——最好是在客户注意到问题之前。

2. 开发一个用于评估事故严重性的系统

有效的事故响应始于一个能够根据事故的严重程度对事故进行排名的系统——通常用对客户造成的影响作为衡量标准。New Relic 的内部事故严重程度量表为组织构建自己的事故响应流程提供了一个很好的起点;它基于 1-5 级的排行,每个级别都有明确的标准:

  • 级别为 5 的事故永远不应该产生客户影响,可以简单地把它定义为提高对有风险的服务部署等问题的认识。
  • 级别为 4 的事故则包括对客户造成影响不大的小错误或数据延迟。
  • 级别为 3 的事故包括较大的数据延迟或不可用的特性。
  • 级别 1 和级别 2 的事故是为产品短暂的、完全的中断或对业务造成直接威胁的事故预留的。几年前 New Relic 发生的“Kafkapocalypse”事件就是这种级别事故的一个例子。

每个事故级别都对应一个特定的约定,以此调用内部资源、管理响应、决定是否与客户沟通、如何沟通,以及其他一些任务。New Relic 将突发事故视为最严重的事故;这些事故通常需要更高层级的响应,某些情况下,甚至需要法律、支持和领导层团队的直接参与。

研究事故会如何影响客户并对客户体验造成影响;思考响应团队用于诊断、控制和解决问题所需的资源都是非常重要的。

在 New Relic,在事故发生时我们通过为事故分配一个严重级别以确定我们需要多少支持。然后,在事故发生后,会根据客户的实际影响重新评估该事故的严重级别。这反映了 New Relic 的一个关键的事故响应原则:我们鼓励工程师在事故发生时迅速提升事故的严重级别,这样就可以得到所需要的支持以解决问题。事故结束后,我们会对事故的实际影响做出评估,如果事实证明影响并没有最初所担心的那么严重,就会下调事故的严重级别。

3. 为响应团队定义和分配角色

下表概述了 New Relic 配备事故响应团队成员所使用的角色。这其中的许多角只有在特定的严重级别才会出现。在其他情况下,分配给角色的职责取决于事故的严重程度:

4. 设置事故响应场景

绝大多数组织都无法完全模拟实际的事故响应——尤其是严重级别较高的事故。不过,即便是有限的模拟也可以让您了解在事故发生时会出现什么情况,如何设置优先级和升级流程,如何协调团队中的角色,以及其他关键洞见。

让我们来看一下 New Relic 的一个假想事故的案例:

事故的模拟从一个 New Relic 产品团队的 on-call 工程师收到呼叫开始。监控该工程师所负责的一项服务的 New Relic Synthetics 健康检查小黄人通知工程师健康检查出现失败。工程师在 New Relic Insights 仪表板上查看了这项服务,发现健康检查确实失败了——吞吐量在下降,她担心客户会因此受到影响。这是怎么回事?她该怎么办?

首先,她在我们指定的 Slack 通道发布一起事故。机器人 Nrrdbot(GitHub 机器人 Hubot 的克隆版本) 将会指导她完成这个过程。因为她决定担当事故指挥员的角色,她输入了“911 ic me”。Slack 管道的报头会随之更新,并在 Upboard(公司内部自建的事故跟踪器)中创建一个新的处于打开状态的事故;Nrrdbot 直接通知她后续的步骤。

IC 现在需要完成三项工作:

  1. 为事故设置一个严重级别(到底有多严重?)
  2. 为事故设置一个标题(简要概述出了什么问题)并设置事故当前的状态(简述目前进展如何)。
  3. 找到一名或多名技术负责人调试问题。如果 IC 是 TL 的最佳人选,那么就让其他人选接管 IC 的角色,因为 IC 不应该承担对事故做技术分析的职责。

IC 设置的严重级别将决定谁会在这次响应中提供帮助。对于严重级别至少在 3 级以上的事故,支持部门会自动指派一名团队成员作为沟通负责人(CL)参与这一事故。CL 的工作是协调与客户的沟通;他们会转发所有与事故相关的客户投诉,并根据工程师最新的发现主动与客户进行沟通。

此时,IC 会打开一个众包协作文档,与参与响应的所有人共享。IC 负责管理所有参与响应的各方之间的沟通流程。她还会在需要的时候提供支持,更新状态 (每 10 分钟更新一次,或者在 Nrrdbot 提醒她的时候),并在情况发生变化(好转或恶化)时更新严重级别。

如果问题在 60-90 分钟内仍未得到解决,她会将 IC 的角色转交他人,因为这是一项相当耗费精力的职责,尤其是当凌晨 3 点从熟睡中醒来的时候。

一旦问题完全解决,所有负责人都确认满意度后,IC 会在 Slack 通道中输入“911 over”。这一操作会将事故置为关闭状态。

5. 抱最好的希望,做最坏的打算

上面的例子模拟了 New Relic 的一个重大事故,但是它并未上升到真正的紧急状态。紧急事故极为罕见 (至少应该如此),但它们对企业构成的威胁要大得多。事实上,在真正最糟糕的情况下,如果事故升级到无法控制的程度,它可能会变成生死存亡的威胁。

在 New Relic,严重级别为 1 或 2 的事故集会自动触发一个后台进程,该进程将呼叫 New Relic 紧急响应部队 (NERF) 中的一名成员和一名 on-call 的工程高管。NERF 的团队成员都是 New Relic 经验最丰富的员工,他们对我们的系统和架构以及事故管理流程都有深入的了解。他们擅长处理严重事故,特别是当这类事故需要协调多个团队时。

高管与 NERF 成员共同加入事故响应团队,承担三个关键职责:通知高级管理人员;协调法律、支持和安全团队;做出艰难的决定。

6. 通过事故学习、改进和成长

作为从事故中获取知识和学习的第一步,示例中的 New Relic IC 在事故结束后还将执行几项任务:

  • 将最终细节汇总到协作文档中,包括:
    • 事故持续时间 ;
    • 对客户的影响 ;
    • 所有需要回滚的紧急修复 ;
    • 在事故中出现的重要情况 ;
    • 关于谁应该参与事后回顾的说明 ;
  • 确认应该参加无指责回顾的人选 ;
  • 选择一个团队作为该事故的负责人 (例如上述案例中的 Synthetics 团队),以便团队的工程经理可以安排事后回顾。

我们还要求团队在事故发生后的一到两个工作日内进行回顾。New Relic 组织了“无指责”的回顾,旨在发现问题的根源,而不是寻找替罪羊。在这里了解更多关于 New Relic 如何构建和使用无指责回顾作为其对 DevOps 最佳实践的更广泛的承诺的一部分。

7. 实现“不重复事故”(DRI)的策略

在 New Relic,如果服务事故对客户造成影响,我们有一个“不重复事故”(DRI) 的策略,该策略强迫我们停止对该服务的任何新工作,直到我们修复导致该事故发生的根本原因或提出相应的减缓措施。DRI 流程在 New Relic 工程团队的成功中扮演了重要的角色——能够确保他们识别并偿还技术债务,通过其他手段,技术债务通常无法得到更优先的安排。

重要的是要记住,我们的目标不是完全消除偶然事故——这是不现实的。相反,New Relic 希望其团队能够更有效地应对将来确定会发生的事故。

现在轮到你了:能够为事故响应计划提供指导的问题列表

我们已经讨论了很多关于 New Relic 如何处理 on-call 和事故响应流程的内容,并提供了一系列最佳实践。我们鼓励你制定清晰的指导方针,以便你的团队能够清楚地理解期望;识别并减少在事故响应和解决过程中出现最严重的摩擦;并决定如何正确地组织您的 on-call 和事故响应流程。

回答以下问题可以帮助你更有效地执行上述这些工作。

规模:你所在的工程机构有多大规模?每个团队有多大规模?团队能处理什么类型的轮转?

增长:工程机构的增长有多快?周转率是多少?

地理:您的组织机构在地理上是集于一处的还是分布广泛的?您是否有足够的规模和分布来采取“跟随太阳”的轮转方式,或者工程师是否需要处理非工作时间的呼叫?

组织结构:工程机构的结构如何?是否采用了现代的 DevOps 文化,在这种文化中,团队负责服务的从开发到运营的完整生命周期,或者开发和运营是割裂的?您是否拥有一个集中化的 SRE 小组,或者 SRE 遍布于整个组织的工程团队中?

复杂性:您的应用程序是如何构造的?您的工程师所支持的是嵌入到更大的系统体系结构中的定义良好的插件式服务,或者您的产品是由不同团队支持的单一应用程序?

依赖关系:有多少客户 (内部或外部) 依赖于您的服务?如果服务失效,破坏范围有多大?

工具:您的事故响应流程和工具复杂性如何?团队的运行记录和监控的全面度和及时度如何?工程师做出呼叫响应时是否有足够的工具和组织支持?工程师能否自动收到可操作的问题通知?

期望:在你们的工程文化中,On-call 是否正在成为规范?它是否被视为工作中有价值和必要的一部分,还是额外的负担?

文化:你的公司是否拥有无指责的文化,专注于真正的根源并解决系统性的问题,或者你们的公司文化是“责备和羞耻”的文化,出错时人们会因此受到惩罚?

英文原文:

https://blog.newrelic.com/engineering/on-call-and-incident-response-new-relic-best-practices/