Close

针对高速团队的事件管理

事后析误

我们在 Atlassian 施行无指责的事后析误,以确保我们了解并解决严重性级别为 2 或更高的每个事件的根本原因。以下是我们内部文档的摘要,描述了我们如何在 Atlassian 执行事后析误。

事件管理手册

获取印刷版或 PDF 版手册

印刷版《事件管理手册》限量供应,可应要求免费寄送。或者,也可下载 PDF 版本。


什么是事后分析?

事后析误是对事件的书面记录,具体描述:

  • 事件的影响。
  • 为缓和或解决事件而采取的行动。
  • 事件的根本原因。
  • 为防止事件再次发生所采取的后续行动。

在 Atlassian,我们使用 Jira 事务跟踪所有的事后析误,以确保事后析误完成并得到批准。如果您的需求不太复杂,可以使用更简单的系统(比如 Confluence 页面)来跟踪每次事后析误。


为什么我们要进行事后析误?

事后析误的目标是:了解所有牵涉到的根本原因;记录事件以供日后参考并发现模式;制定有效的预防措施以减少再次发生的可能性或影响。

为了让事后分析能够有效减少重复事件,审查流程必须激励团队确定根本原因并予以解决。具体方法取决于您的团队文化;在 Atlassian,我们找到了适合我们的事件响应团队的方法组合:

  • 面对面会议有助于推动适当的分析,并使团队在需要解决的问题上达成一致。
  • 交付和运维团队经理给出对事后析误的审批,以此激励团队全面执行事后析误。
  • 指定的“优先行动”具有商定的服务等级目标 (SLO),可以是 4 周,也可以是 8 周,具体取决于服务;还有提醒和报告,以确保这些行动完成。

参与这一流程并确保流程有效,需要组织的各个层面做出贡献。我们的工程总监和经理决定了各自领域的行动决议的审批者和 SLO。这个体系只是进行编码并尝试执行他们的决策。


何时需要进行事后析误?

我们对严重性级别为 1 和 2 的事件进行事后析误。对于其他事件,事后析误是可选的。

在解决事务期间或之后不久,事后析误负责人会创建一个新的事后析误事务。


由谁完成事后析误?

故障服务的交付团队(在事件事务中拥有“失败服务”的团队)负责完成事后析误。该团队选择事后析误负责人并为他们分配事后析误事务。

  • 事后分析负责人会一直通过起草和审批等工作推动事后分析的进行,直至结果发布为止。他们负责完成事后分析。
  • 一个或多个事后析误审批者负责审查并批准事后析误,且应该在他们的待办事项列表中将后续行动列为优先任务。

我们有一个 Confluence 页面,上面按服务组列出了事后析误审批者的名单(强制和可选),服务组通常对应着 Atlassian 产品(例如 Bitbucket Cloud)。


如何跟踪事后析误行动?

对于事后析误产生的每一项行动,我们都:

  • 在负责团队的待办事项列表中列出一项 Jira 事务。所有事后析误行动必须在 Jira 中进行跟踪。
  • 将它们从事后析误事务链接到“优先行动”(针对解决根本原因)或“改进行动”(针对非根本原因的改进)。

我们使用 Jira REST API 构建了一些自定义报告,以跟踪每个严重性级别中有多少事件还未通过事后析误中的优先行动解决根本原因。各部门的工程经理会定期审查这份列表。


事后析误流程

执行事后析误流程包括:创建事后析误事务、召开事后析误会议、制定行动、获得批准以及(可选)通知结果。

事后析误负责人有责任通过以下任务执行事后析误:

  1. 创建事后析误并将其链接到事件。
  2. 编辑事后析误事务,阅读字段描述并填写字段。
  3. 为确定事件的根本原因,使用“五问法”彻查因果链,直至找到真正的根本原因。
  4. 安排事后析误会议。使用会议邀请模板邀请交付团队、受影响的团队和利益相关者。
  5. 与团队会面并检查下面的会议安排。
  6. 跟进负责的开发经理,以获得采取具体行动以预防此类事件的承诺。
  7. 在负责团队的待办事项列表中针对每项行动提出 Jira 事务。将它们从事后析误事务链接到“优先行动”(针对解决根本原因)或“改进行动”(针对其他的改进)。
  8. 在 Confluence 中查找相应的审批者,并将其添加到事后分析的“审批者”字段中。
  9. 选择“请求批准”过渡,以请求指定审批者的批准。自动化功能将用审批者的说明作为对事务的评论。
  10. 根据需要进行跟进,直至事后析误获得批准。
  11. 如果事后析误获得批准,我们可以自动在 Confluence 中起草事后析误博文,供您编辑和发布。撰写事后析误博文可以分享您的深刻教训,这会增加事后析误的价值。

完成事后析误流程后,开发团队会根据团队的 SLO 确定行动的优先级,作为常规待办事项的一部分。


事后析误会议

我们发现将团队召集在一起讨论收获可以更深入地分析根本原因。我们的团队比较分散,因此我们通常通过视频会议进行,有时事件涉及很多人,就会以小组形式完成。

我们建议的议程:

  1. 提醒团队事后析误是无指责的,并说明原因
  2. 确定各项活动的时间表
  3. 确定根本原因
  4. 运用“开放式思维”制定行动 -“我们可以做些什么来防止日后发生此类事件?”
  5. 问问团队“哪些方面做得好/哪些方面本来可以做得更好/我们在哪些方面比较幸运?”

建议的日历预约模板:

请和我一起进行 <事件链接> 的无指责事后析误。请参考 <事件摘要>。

事后析误的目标是:了解所有牵涉到的根本原因;记录事件以供日后参考并发现模式;制定有效的预防措施以减少再次发生的可能性或影响。

在本次会议中,我们将设法确定根本原因并决定采取哪些行动来缓解这些根本原因。

如果负责的开发经理不在会议室中,那么请避免在会议中承诺采取具体行动,因为这并不利于优先级决策。人们会对做出承诺感到有压力,并且没有完整的信息。相反,在会议结束后跟进负责的经理,以获得执行所确定的优先行动的承诺。


事后析误事务字段

我们的事后析误事务需要填写一系列的字段,以鼓励大家在召开事后析误会议前,收集与事件相关的所有重要详细信息。以下是一些如何填写这些字段的示例。

字段

说明

示例

事件摘要

用几句话概括事件。包括严重性、原因以及影响持续的时间。

<日期><事件的时间范围,例如 14:30 到 15:00> 之间,<数量> 位客户遇到了<事件症状>。该事件是由在<导致发生该事件的部署或更改的时间>进行的部署引发的。部署包含一项代码更改,<更改的描述或原因>。该部署中的缺陷导致了<问题描述>

<系统>检测到了该事件。我们通过<采取的决议行动>缓解了事件。

这一<严重性级别>事件影响了 X% 的客户。

<支持工作单和/或社交媒体文章的数量>与该事件相关。

致因

描述导致该事件发生的情况,例如,之前做出的更改引入了潜在缺陷。

<日期> <时间>,(<距离客户受到影响的时长>)一项更改被引入到了<产品或服务>以...<引发该事件的更改描述>。这项更改导致了...<更改造成影响的描述>

故障

描述哪些方面不符合预期。附上相关图表的屏幕截图或显示故障情况的数据。

<时间段>期间,<数量> 个响应未正确发送至 X% 的请求。

影响

描述内部和外部客户在事件发生期间看到的内容。包括提出的支持案例数量。

<日期> <时间范围><时长>中,遇到了<事件摘要>

这影响了<数量>的客户(占<系统或服务> 所有客户的 X%),这些客户遇到了<客户遇到的症状描述>

引发了<支持请求单和社交媒体文章数量>

检测

Atlassian 是如何以及何时检测到该事件的?

如何改进检测时间?作为一项思考练习,如何把该时间缩短一半?

检测到事件的标志:<警报的类型>被触发,<呼叫的团队或人员>得到了呼叫。然后,他们必须呼叫<二次响应人员或团队>,因为他们不负责将服务写入磁盘,这导致响应延迟了<时长>

<负责改进的团队>将制定<改进描述>,以便<改进的影响>

响应

谁做出了响应?何时以及如何响应的?我们的响应存在任何延迟或障碍吗?

在协调世界时 14:34 收到呼叫后,KITT 工程师于 14:38 在事件聊天室中上线。但是,待命的工程师没有足够的 Escalator 自动扩展器方面的背景,因此系统在 14:50 发出了进一步的警报,一名高级 KITT 工程师在 14:58 进入了聊天室。

恢复

描述服务恢复的方式和时间。您是如何找到减轻影响的方法的?

需要提出更多问题,具体取决于场景:如何缩短缓解用时?作为思考练习,如何把该时间缩短一半?

恢复是三管齐下的响应:

  • 增加 BuildEng EC2 ASG 的大小,以增加可为工作负载提供服务的节点的数量,降低调度超额订阅节点的可能性

  • 禁用 Escalator 自动扩展器以防止群集大幅缩减

  • 将 Build Engineering 调度器恢复为先前版本。

时间表

按时间顺序提供详细的事件时间线,加注时区。

包括任何的致因;开始产生影响的时间;检测时间;上报、决策和更改;影响结束的时间。

所有时间均为协调世界时。

11:48 - K8S 1.9 的控制平面升级完成
12:46 - Goliath 升级至 V1.9 完成,包括 cluster-autoscaler 和 BuildEng 调度器实例
14:20 - Build Engineering 向 KITT Disturbed 报告了一个问题
14:27 - KITT Disturbed 开始调查特定 EC2 实例 (ip-203-153-8-204) 出现的故障
14:42 - KITT Disturbed 隔离了特定节点
14:49 - BuildEng 报告该问题影响了不止一个节点。问题涉及 86 个实例,表明故障具有系统性
15:00 - KITT Disturbed 建议切换到标准调度器
15:34 - BuildEng 报告了 300 个单元出现故障
16:00 - BuildEng 终止了所有出现故障的构建并出具了 OutOfCpu 报告
16:13 - BuildEng 报告故障在新的构建中不断重新出现,而且不是暂时性的。
16:30 - KITT 将故障识别为事件,并将其作为事件执行。
16:36 - KITT 禁用了 Escalator 自动扩展器以防止自动扩展器删除计算,从而缓解该问题。
16:40 - KITT 确认 ASG 处于稳定状态,群集负载正常,客户受到的影响已解决。

五问法

使用根本原因确定法

首先是影响,询问为什么会出现这种情况以及为什么会产生这样的影响。不断地问为什么,直至找出根本原因。

将您的“为什么”作为列表记录在此处或该问题随附的图表中。

  1. 服务出现故障是因为数据库被锁定

  2. 因为有太多的数据库写入

  3. 因为对服务进行了更改,未预料到增加问题

  4. 因为我们没有针对负载测试更改而设置相应的开发流程

  5. 我们从未进行过负载测试,并且达到了新的规模水平

根本原因

根本原因是什么?根本原因是指为了阻止此类事件再次发生而需要改变的东西。

<导致缺陷的原因或出现缺陷的服务>连接池处理中的缺陷导致在出现故障的情况下泄露连接,以及对连接状态缺乏可见性。

待办事项检查

您的待办事项中的任务可以防止这种情况发生或大大降低其影响吗?如果可以,为什么没有这样做?

此处的如实评估有助于弄清过去围绕优先级和风险做出的决策。

未具体说明。对流类型的改进是已知的正在进行的任务,具有适当的固定程序(例如,在更改/创建文件时添加流类型)。修复集成测试的请求单已经完成,但在尝试时失败

重现

该事件(具有相同的根本原因)之前发生过吗?如果之前发生过,为什么会再次发生?

这一相同的根本原因导致了事件 HOT-13432、HOT-14932 和 HOT-19452 的发生。

吸取的经验教训

我们吸取了哪些经验教训?

讨论哪些方面做得好、哪些方面本来可以做得更好,以及我们在哪些方面比较幸运,找到了改进机会。

  1. 需要进行单元测试,以验证工作的速度限制器是否得到正确维护

  2. 应审查非典型正常操作的批量操作工作负载

  3. 批量操作应该缓慢启动并进行监控,如果服务指标有名无实,则会增加

纠正措施

我们要做些什么才能确保此类事件不再发生?谁将采取行动以及何时采取行动?

创建“优先行动”事务,以链接到跟踪每项行动的事务。

  1. 暂时进行手动的自动扩展速度限制,以限制故障

  2. 单元测试和重新引入工作速度限制

  3. 引入辅助机制来跨群集收集分散的速度信息以指导扩展效果

  4. 由于 AWS ES 不会自动扩展,因此需要调整大型迁移。

  5. 验证 Stride 搜索仍归类为第 2 层

  6. 如果 xpsearch-chat-searcher 出现故障,则针对 pf-directory-service 提交部分出现故障而不是完全出现故障的请求单。

  7. Cloudwatch 警报,以识别 ElasticSearch 群集上的高 IO 问题


直接原因和根本原因

如果您正在撰写或阅读事后析误,则需要区分直接原因和根本原因。

  • 直接原因是指直接导致此事件的原因。
  • 根本原因是指在事件链中处于最要害位置的原因,对其进行更改将防止所有此类事件。

事后分析力图挖掘根本原因决定如何最大限度地缓解根本原因。在事件链中找到最要害位置是事后分析的真正艺术。使用五问法之类的方法沿着事件链顺藤摸瓜,寻找根本原因。

以下是一些直接原因和根本原因的示例:

场景 直接原因及行动 根本原因 根本原因缓解措施

Stride “Red Dawn”队的服务没有 Datadog 监视器以及针对其服务的待命警报,或者它们未正确配置。

团队成员没有针对新服务配置监控和警报。

为这些服务配置监控和警报。

没有制定用于支持新服务的流程,包括监控和警报。

创建一个用于支持新服务的流程,并教导团队遵循该流程。

由于升级到无法在 IE 11 上运行的 Fabric Editor,因此 Stride 在 IE11 上无法使用。

依赖关系的升级。

复原升级。

未进行跨浏览器兼容性测试。

自动进行连续跨浏览器兼容性测试。

来自 Micros EU 的日志未到达日志记录服务。

为 Micros 提供的用以发送日志的角色不正确。

更正角色。

我们无法确定环境中的日志记录何时开始不工作。

针对任何环境中丢失的日志添加监控和警报。

由以前的 AWS 事件触发,Confluence Vertigo 节点耗尽了到 Media 的连接池,导致客户遇到间歇性连接和介质错误问题。

AWS 出现故障。

获得 AWS 事后析误。

Confluence 连接池处理中的缺陷导致在出现故障的情况下泄露连接,以及对连接状态缺乏可见性。

修复缺陷并添加监控,以便在未来检测类似的情况,防止它们产生影响。


根本原因分类及其行动

我们使用这些分类对根本原因进行分组,并讨论针对每种分类的相应行动。

类别

定义

您应该怎么做?

缺陷

Atlassian 对代码做出的更改(这是一种特定类型的更改)

测试。金丝雀。逐步推出并观察它们。使用功能标志。与质量工程师沟通。

更改

Atlassian 所做的更改(除代码之外)

改进您进行更改的方法,例如,您的更改审查或更改管理流程。“缺陷”一栏里的内容也适用于这里。

规模

扩展失败(例如,无视资源限制或缺少容量规划)

您服务的资源限制是什么?它们是否受到监控并会触发警报?如果您没有容量计划,请制定一份容量计划。如果您有容量计划,还需要考虑哪些新的限制?

架构

设计与操作条件不一致

审查您的设计。您需要更换平台吗?

相关性

第三方(非 Atlassian)服务出现故障

您是否要管控第三方出现故障的风险?我们是否做出了接受风险的业务决策,还是需要制定缓解措施?请参阅下面的“与依赖关系相关的根本原因”。

未知

不能确定(行动是提高诊断能力)

通过添加日志记录、监控、调试和类似内容来提高系统的可观察性。


与依赖关系相关的根本原因

当您的服务因为依赖关系出现故障而发生事件时,故障所在位置以及根本原因取决于依赖关系是属于 Atlassian 内部还是第三方,以及对依赖关系性能的合理期望。

如果是内部依赖关系,则问“依赖关系的服务级别目标 (SLO) 是什么?”

  • 依赖关系违反了它们的 SLO 吗?
    • 故障在于依赖关系,它们需要提高可靠性。
  • 依赖关系遵守它们的 SLO,但您的服务仍然出现故障?
    • 您的服务需要增强弹性。
  • 依赖关系没有 SLO?
    • 它们需要 SLO!

如果是第三方依赖关系,则问“我们对第三方依赖关系的可用性/延迟等的合理期望*是什么?”

  • 第三方依赖关系超出了我们的期望(以一种糟糕的方式)吗?
    • 我们的期望不适当。
      • 我们是否能够确信它不会再次发生?例如,我们审查并同意它们的 RCA。在这种情况下,行动就是它们的 RCA。
      • 或者,我们需要调整我们的期望吗?在这种情况下,行动就是提高我们的弹性并调整我们的期望。
      • 我们调整后的期望不可接受?在这种情况下,我们需要以某种方式解决需求和解决方案之间的脱节,例如寻找其他供应商。
  • 第三方依赖关系符合我们的期望,但您的服务仍然出现故障?
    • 在这种情况下,您的服务需要提高弹性。
  • 我们真的没有期望吗?
    • 第三方依赖关系的负责人需要建立期望,并与团队共享,以便他们知道需要在其有依赖性的服务中构建哪种级别的弹性。

*为什么要建立期望呢?我们不是与第三方签订了 SLA 吗?事实上,以合同形式与第三方签订的 SLA 太低,无法用于确定故障和缓解措施。例如,AWS 几乎不为 EC2 发布 SLA。因此,当我们依赖第三方服务时,我们必须决定我们合理期望他们提供的可靠性、可用性、性能或其他关键指标的级别。


事后析误行动

来自 Google 的 Sue Lueder 和 Betsy Beyer 就事后析误行动事项制作了精彩的演示文稿并撰写了优秀的文章 ,我们在 Atlassian 使用它们来提示团队。

通过提出以下问题来帮助确保 PIR 涵盖短期和长期修复:

“缓解未来事件”和“预防未来事件”是解决根本原因的最可能的行动来源。务必至少提问其中一个问题。

类别 要问的问题 示例

调查该事件

“导致这一事件的原因是什么?为什么?”确定根本原因是您的最终目标。

日志分析、绘制请求路径图、检查堆转储

缓解该事件

“我们采取了哪些立即行动来解决和管理这一特定事件?”

回滚、择优挑选、推送配置文件、与受影响的用户沟通

修复该事件造成的损害

“我们是如何解决该事件造成的直接或间接损害?”

恢复数据、修理机器、删除流量重新路由

检测未来事件

“我们如何缩短准确检测类似故障的用时?”

监控、警报、对输入/输出进行真实性检查

缓解未来事件

“我们如何降低此类未来事件的严重性和/或持续时间?”

“我们如何降低此类事件下次发生时受影响的用户百分比?”

优雅降级;排除非关键结果;出故障时自动打开;通过仪表板或手册增强当前的实践;更改事件流程

预防未来事件

“我们如何防止此类故障再次发生?”

代码库稳定性改进、更彻底的单元测试、输入验证以及错误条件的稳健性、配置更改

我们还采纳了 Lueder 和 Beyer 有关如何表述事后析误行动的建议。

表述事后析误行动:

能否正确表述事后析误行动,会带来不同的结果:轻松完成;或者由于不可行或拖延而导致无限期延迟。表述恰当的事后析误行动应该具有以下特征:

可操作:使用以动词开头的句子表述每项行动。行动应该产生有用的结果,而不是一个过程。例如,“列举出关键依赖关系的列表”是一项好的行动,而“调查依赖关系”则不是。

具体:尽可能狭隘地定义每项行动的范围,明确工作中包含和不包含的内容。

有限制:每项行动的措辞应该能够表明如何判断何时结束,而不是让行动没有最终期限或处于一直进行的状态。

原表述... 修改后的表述...

调查该场景的监控。

(可行动)只要该服务返回 >1% 错误,即针对所有这些出错情况添加警报。

修复导致运行中断的问题。

(具体)安全地处理用户地址表单输入中的无效邮政编码。

确保工程师在更新之前检查数据库模式是否可以解析。

(有限制)为模式更改添加自动的预提交检查。


事后析误审批

Atlassian 在使用 Jira 工作流的同时采用审批步骤,以确保事后析误获得批准。审批者通常是服务负责人或其他负责服务运营的经理。对事后析误的批准表明:

  • 同意事后审查的结果,包括根本原因;
  • 同意相关的“优先行动”行动是解决根本原因的可接受方式。

我们的审批者通常会要求采取更多行动或确定某些未被提议的行动未解决的因果链。通过这种方式,我们看到审批为 Atlassian 的事后析误流程增加了很多价值。

事件较少或基础架构不太复杂的团队可能不需要事后析误审批。


无指责的事后析误

当事情出错时,寻找被指责的对象是人之常情。不过,避免这种指责才符合 Atlassian 的最佳利益,因此在执行事后析误时,您需要有意识地克服这种倾向。我们假定我们的员工心怀善意,并且从不指责人们的过错。事后析误需要诚实、客观地审视导致故障的情况,以便我们可以找到真正的根本原因并予以缓解。指责他人会危及这一点,因为:

  • 如果人们感受到他们在同事眼中的地位或他们的职业前景有危险,这种感受通常会在他们的个人等级中超越“我的雇主企业的最佳利益”,因此他们会自然地掩饰或隐藏真相以保护他们的基本需求。
  • 即使一个人做出了直接导致事件的行动,我们应该问的也不是“为什么 x 这个人会这样做”,而是“为什么体制允许他们这样做,或者让他们相信这样做是正确的”。
  • 责备他人是不友善的,而且,如果经常再三地责备他人,就会创造出一种恐惧和不信任的文化。

在我们的事后析误中,我们使用以下方法为所有参与者创造个人安全:

  • 事后分析会议的开场白会声明这是一次无指责的事后分析以及原因
  • 按角色(例如“待命的小工具工程师”)而不是姓名称呼个人(同时对事实绝不含糊其辞)
  • 确保事后析误时间表、因果链和缓解措施在系统、流程和角色而不是个人的背景下进行设计。

我们的无指责事后析误的灵感和“第二个故事”的有用概念来自于 John Allspaw 所写的这篇具有深远影响的文章