在第三部分中,我们描述了如何建立从开发到运维的快速流动的工作流,以及它所需要的架构及技术实践。在第四部分中,我们将描述如何实现第二步工作法的技术实践,创建从运维到开发的快速且持续的反馈。
这个实践能加快并增强反馈回路,让我们识别出发生的问题,并把这些信息反馈给价值流中的所有人。这样就可以在软件开发生命周期的早期快速地识别并修复问题 ;在理想情况下,早在导致灾难性事故发生以前,问题就被处理掉了。
我们还将阐述在构建、测试和部署的流程中,如何对用户行为、生产故障、服务中断、合规问题和安全漏洞进行全面监控。需要探索和落实如下工作 :
运维团队无法规避的一个问题是发生故障——一个小小的变更也会导致很多意外后果,包括服务中断,甚至是对所有客户造成影响的全球性故障。事实就是:运维团队面对的是复杂系统,没有哪个人能了解整个系统,能说清楚系统的每个部分是如何配合的。
为了能训练有素地解决问题,我们需要设计出能够持续遥测的系统。遥测被广泛定义为“一个自动化的通信过程,先在远程采集点上收集度量数据,然后传输给与之对应的接收端用于监控
”。目标是在应用及其环境中建立遥测,包括生产环境、预生产环境和部署流水线。
本章的目标是通过建立全面的监控系统,确保服务在生产环境中正常运行。在出现问题时,能快速地定位,并做出正确的决策解决问题,而且最好是早在客户受到影响之前就解决。此外,监控让我们能够汇集对现实最好的理解,并在理解不正确时及时发现。
应急响应指标:
运维监控和日志管理绝对不是新鲜事物,多年以来运维工程师已使用和定制监控框架(例如,HP OpenView、IBM Tivoli 和 BMC Patrol/BladeLogic)来确保生产系统的正常运行。监控数据通常使用在服务器端运行的代理或通过无代理监控(如 SNMP Trap 或基于轮询的监控)方式来采集。前端通常会使用图形用户界面展示,而后端经常使用诸如 Crystal Reports 等工具来补充。
现代的监测体系架构具有以下组成部分
“监控是如此重要,所以监控系统需要比被监控的系统更具可用性和可扩展性。”
从此,术语遥测可以和度量互换使用,它涵盖了应用程序栈的各层级服务所产生的事件日志和度量指标,也包括来自所有生产环境、预生产环境和部署流水线的事件日志记录和度量指标。
有了集中的遥测基础架构,我们必须确保对所有正在构建和运维的应用都建立充分的遥测。要实现这一点,开发和运维工程师必须把建设生产遥测作为日常工作的一部分,不仅仅是对新服务,对已有的服务也要建立充分的遥测
“NASA 每次发射火箭时,都用数百万的自动传感器来报告这一宝贵资产每个组成部分的状态。然而,我们通常不会对软件做同样的事。我
们发现,建设应用和基础设施的遥测是投资回报最高的事情之一。”
日志要具有不同的级别,其中的一些可能也会触发告警,举例如下
为了帮助确保拥有与服务可靠性和安全操作相关的信息,我们应该保证所有潜在的重大应用事件都生成日志记录条目
为了更容易地解释和给出所有日志条目的意义,(理想情况下)我们应该对日志记录进行分级和分类,比如对非功能属性(如性能、安全性)和功能属性(如搜索、排行)
如本章开头所述,高绩效者在解决问题方面是训练有素的,这与依靠道听途说的常见做法形成鲜明对比,后者的平均清白证明时间(即花多长时间说服其他人,不是我们造成了中断)指标是非常糟糕的。
遥测技术赋予了我们一种科学的方法,让我们能够对具体问题的原因和解决方案作出假设。在解决问题的过程中,我们可以回答以下问题
为了让所有人都能在日常工作中发现并解决问题,我们需要让他们在日常工作中可以轻松地创建、展示和分析度量指标。因此,必须建立必要的基础设施和库,让任何开发或运维人员都能很容易地针对任何功能创建遥测。理想情况下,创建一个新的指标,通过仪表板显示出来,让价值流中的所有人都可以看到它,应该像编写一行代码那样简单。
图 14-3 显示了用一行代码创建的用户登录事件(在这个例子中,那一行 PHP 代码是:StatsD::increment("login.successes")
)。图中显示了每分钟登录成功和失败的次数,图上的垂直竖线表示一次生产部署。
通过将创建生产环境度量指标作为日常工作的一部分,不但可以及时地捕获问题,而且还可以在设计和运维过程中不断暴露问题,从而能跟踪越来越多的指标
我们希望生产监控指标具有高度的可见性,这意味着要将其放置在开发和运维人员工作区域的中心,从而使所有感兴趣的人都能看到服务的现状。这至少要包括价值流中的每一个人,比如开发、运维、产品管理和信息安全。
这通常称为信息辐射器(information radiator),它是由敏捷联盟定义的:“这个通用术语指的是,团队放置在一个非常显眼位置上的手写、绘制、印刷或电子信息展示,让所有团队成员以及路过的人都可以快速浏览最新信息:自动化测试次数、速率、事故报告、持续集成状态等。这个想法起源于丰田生产系统。
通过将信息辐射器放置在非常显眼的地方,我们在团队成员中传播着责任感,同时也积极地展示出以下价值观:
现在,我们可以将基础架构生成的生产环境遥测信息辐射到整个组织,还可以将此信息传播给内部客户,甚至外部客户。例如,创建可以公开浏览的服务状态页面,方便客户了解他们所依赖的服务的状态
我们需要在所有环境中,在应用程序栈的每个层级中,以及支持它们的部署流水线中,建立充分而完整的遥测。我们需要以下层级的度量指标
通过利用遥测完整地覆盖以上领域,我们能够看到服务依赖的所有事物的健康状况,用数据和事实说明问题,而不是听信传言、指指点点、互相责备
通过尽早发现并修复问题,我们可以在问题还小、容易修复的时候就修复它们,进而减少对客户的影响。此外,在每次生产故障之后,我们应该识别是否存在遥测盲区,弥补它们就能更快地发现故障和恢复服务。更好的做法是,在功能开发阶段,在同行评审的过程中就能识别出这些盲区。
在应用程序层面,我们的目标是:不仅要确保产生的遥测能够反映应用程序的健康状况(例如内存使用、事务计数等),还要度量目前组织的业务目标的实现情况(例如用户增长数、用户登录次数、用户会话时长、活跃用户比例、某些特性的使用频率,等等)。
业务指标将是客户获取渠道的一部分,它是潜在客户购买商品的理论步骤。例如,在电子商务网站中,可度量的事件包括:用户在线时长、产品链接点击次数、购物车中的商品数量,以及完成的订单。
“通常情况下,功能团队会在获取渠道上定义目标,包括每个客户在一天中使用该功能的次数。有时候,在监控的不同阶段,对用户的非正式称呼分别是‘踢轮胎者’‘活跃用户’‘成员用户’和‘骨灰级用户’等。”
与为应用程序度量指标所做的类似,对于生产环境和非生产环境的基础架构,我们的目标是确保建立全面的遥测指标,以便在任何环境中出现问题时,能够快速定位问题是不是由基础架构引起的。此外,还必须能够定位到究竟是基础架构的哪个组件引发了问题(例如,数据库、操作系统、存储、网络等)
我们希望尽可能多地向所有技术利益干系人展示基础架构的监控信息,而且在理想的情况下是按照服务或应用程序的逻辑来组织的。换句话说,当环境出现问题时,我们需要准确地知道应用程序和服务可能会或正在受到什么影响。
不管服务多么简单或者多么复杂,将业务指标与应用程序和基础架构指标聚合在一起显示,会有助于发现故障。例如,可能会看到新客户注册数下降到日平均值的 20%,然后还立即发现所有数据库查询花费的时间是正常情况的 5 倍,这使我们能够把精力集中在解决问题上。
“我们不是根据停机时间来衡量运维,更好的做法是根据停机所造成的实际业务后果来衡量开发和运维团队:我们应该获得却没有获得的业务收益是多少。”
为了提高变更的可视化程度,可以在监控图形上叠加显示所有生产环境的部署活动。例如,对于处理大量入站事务的服务,生产环境变更可能会导致明显的下跌周期,在此期间,应用的性能由于所有高速缓存查询失效而骤降。
为了更好地理解和保持服务质量,我们要了解性能何时能恢复,并且如果有必要,还要实施性能提升方案。同样,我们还想叠加其他有意义的运维活动,例如当服务正在维护或备份时,有可能需要在某些地方显示告警或者暂停告警
在问题发生时就能发现问题是多么地重要,这样才能及时地找出原因,并迅速补救。无论是在应用程序、数据库还是生产环境中,通过使服务的所有组成部分都发送遥测信息以便进行分析,可以早在故障导致灾难之前,甚至是早在客户注意到问题之前,就发现并解决问题。这样不仅能使客户更加满意,而且通过减少救火和危机次数,工作压力也会减轻,倦怠程度也会降低,工作也会更加愉快、更富有成效。
本章,我们将创建工具来识别隐藏在生产环境遥测中的差异和微弱的故障信号,从而避免灾难性故障的发生。本章会介绍大量统计技术,并通过案例研究来讲解它们的用途
本章会探讨很多统计和可视化技术(包括异常检测),我们可使用它们来分析遥测数据,从而更好地预测问题。这样,我们就能够以更快的速度、更低的成本,早在客户或组织中的任何人受到影响之前就解决问题。此外,我们还将创造更多的数据使用场景,帮助我们做出更好的决策,实现组织的目标。
分析生产环境度量指标最简单的一种统计技术是计算均值(或平均数)和标准差。通过这种方式,我们可以创建一个过滤器,用来检测度量指标与正常值显著不同的情况,甚至配置告警,以便触发修复动作(例如,当数据库查询速度明显低于平均值时,在凌晨 2 点通知生产环境的值班员进行排查)。
标准差的常见用途是,定期检查数据集的某个度量,如果与均值有显著差异就告警。例如,当每天未经授权的登录次数比均值大三个标准差时就告警。只要这个数据集呈高斯分布,我们就预计只有 0.3%的数据点会触发告警。
即使只是一种简单的统计分析,它也是有价值的,因为再也不必设置静态阈值——如果跟踪的是几千或几十万个生产指标,这样是不可行的。
在本书的后续内容里,我们将交换使用术语遥测、度量和数据集。换句话说,度量(例如“页面加载时间”)将映射到一个数据集(例如,2 毫秒、8 毫秒、11 毫秒等),统计学家用后者来描述一个数据点矩阵,其中每一列代表对其执行统计操作的一个变量。
在当前这个阶段,我们将复制以上实践成果。其中一个最简单的方法是:分析在近期(例如30 天内)遇到的最严重的事故,并建立一个遥测列表,用来更早、更快地检测和诊断问题,以及更方便、更快捷地确认已经实施了有效的修复措施。
例如,如果 NGINX Web 服务器停止对请求做出响应,我们会查看主要指标,它们可能已提前警告我们,我们已开始偏离标准操作。例如:
上述所有指标都是生产环境事故的潜在征兆。对于每一个这样的指标,我们将设置告警。当它们偏离均值足够多时,就发出告警,通知相关人员采取纠正措施
通过对所有更弱的故障信号重复以上过程,我们就可以在软件的生命周期中更早地发现问题,从而减少影响客户的事件的发生次数。换句话说,我们不但要主动地预防问题,而且要进行更快速的探测和修复。
使用均值和标准差来检测异常是非常实用的。然而,在运维中我们会用到许多个遥测数据集,对它们都使用这些技术,并不一定会产生预期的结果。
换而言之,当数据集里的数据没有呈上述的高斯分布(钟形曲线)时,使用与标准差相关的属性就不合适了。例如,我们正在监控网站每分钟的文件下载量,需要检测的是下载量异常大的时段。例如,当下载率比均值大三个标准差时,我们就可能要主动地增加更多的带宽。
Nicole Forsgren 博士解释说:“运维中的很多数据集呈我们所谓的‘卡方’分布。对这样的数据使用标准差,不仅会导致告警过度或告警不足,还会产生荒谬的结果。当并发下载量比均值低三个标准差时,结果会是负数,这显然是讲不通的。”
Netflix 利用了这样一个事实:其消费者的浏览模式有着惊人的一致性和可预测性,尽管未呈高斯分布。图 15-4 反映的是在整个工作周内每秒的客户请求数,展示了从周一到周五客户浏览模式是规律和一致的
在监控数据并不呈高斯分布的情况下,我们仍然可以使用各种方法来找到值得关注的差异。这些技术广泛地分类为异常检测,其通常的定义是“搜索不符合预期模式的数据条目或事件”。其中的一些功能可以在监控工具里找到,而其他功能可能需要统计专家的帮助。
我们采用了称为平滑的统计技术,它对于时间序列数据特别适用,这意味着每个数据点都有一个时间戳(例如,下载事件、已完成的事务处理事件等)。平滑技术通常涉及使用移动平均数(或滚动平均数),它利用每个点与滑动窗口中的所有其他数据的平均值,来转换数据。这样做有助于抑制短期波动,突出长期趋势和周期。
图 15-6 中展示了这种平滑技术的效果。黑线表示原始数据,而灰线表示 30 天的移动平均数(即 30 天的平均值轨迹)。
我们可以预期,与用户有关的大量遥测数据将具有周期性/季节性的相似性——网络流量、零售交易、电影观看以及许多其他用户行为,其每日、每周和每年的模式都是惊人地规律和可预测。这让我们可以检测出与历史规律有差异的情况,例如,周二下午的订单交易率降至周平均数的 50%
图 15-7 显示了某电子商务网站每分钟的交易次数。注意在这幅图中,每周的交易量是在周末下降的。目测第四周发生了特殊的状况,因为周一的交易量并没有恢复到正常水平。这表明我们应该对这个事件进行调查。
本章探讨了几种用于分析生产环境遥测数据的统计技术,通过它们能更早地发现和解决问题,并且能在问题较小的时间予以解决,从而避免造成灾难性后果。这些技术使我们能识别出那些微弱的故障信号,并及时采取行动,从而建立一个更安全的工作系统,同时提高实现目标的能力。
我们必须要将生产遥测的监控融入到部署工作中,同时还要建立文化规范,那就是每个人都对整个价值流的健康承担着相同的责任
本章将建立反馈机制,让我们在服务生命周期的每个阶段(从产品设计到开发和部署,再到运维和最终下线),都能够持续地改善价值流的健康状况。这样,就可以保证服务始终处于“就绪”的状态,即使是在项目的初始阶段,同时还可以从每次发布和生产问题中总结和学习,并将经验用于未来的工作中,从而提高安全性和每个人的生产力。
在这个阶段,我们确保在任何人执行生产部署时,都积极主动地监控生产环境的度量指标,这可以让部署人员(无论是开发人员还是运维人员)在新版本在生产环境中运行以后,快速地确认功能是不是按预期正常运行。毕竟,在这个新版本按预期在生产环境中运行以前,我们都不应该认为代码部署或生产环境变更已经完成
如第三部分所述,我们的目标是在软件进入生产环境之前,在部署流水线中就发现错误。然而,还是存在着检测不到的错误,这就要依靠生产环境的遥测来快速恢复服务了。我们可以使用特性开关关闭出错的功能(这通常是最简单且风险最小的选择,因为它不涉及生产部署),或者前向修复这个错误(即为了修复缺陷而修改代码,然后通过部署流水线将代码变更部署到生产环境),或者回退(例如,使用特性开关切换回之前的旧版本,或通过蓝绿部署、金丝雀发布等模式,将出错的服务器做离线处理)
每一项产品功能都标记为“完成”并不代表业务目标已经实现。相反,所有功能都在生产环境中按照设计正常地运行,没有引起重大的故障,也没有引发计划外的运维或开发工作,才是真的“完成”。
ITIL 将“保证”定义为服务能在生产环境中可靠地运行一段预定时间(例如两周)而无需干预。理想情况下,这个“保证”的定义应该纳入到“完成”的定义中。
这种做法对各种团队都适用,包括面向市场的团队、负责开发和运行功能的团队,以及以职能为导向的团队。
不管团队的组织结构怎样,基本原则是不变的:当开发人员获得应用程序在生产环境中运行的反馈时,包括故障的修复状况,他们与客户之间的距离就更近了,这会使价值流中的所有人都受益。
交互和用户体验设计中最强大的技术之一是情境访谈。产品开发团队观察客户在他们的自然环境中(通常是在他们的办公桌前)使用应用程序,这就是情境访谈。通过情境访谈,通常会发现客户在使用产品的过程中所遇到的困难,例如,在日常工作中执行一项简单的任务也需要很多次点击操作,需要在多个屏幕之间复制和粘贴文本,或者需要在纸上记录信息。其实这些都是补偿性行为,是由应用程序的可用性不足造成的。
我们的目标是运用这种技术观察我们的工作对内部客户产生的影响。开发人员应该跟踪他们的工作,这样可以看到下游工作中心在生产环境中是如何与他们开发的产品交互的。通过这种方式,我们获得了对代码的非功能方面(包括所有与面向客户的功能无关的元素)的反馈,并能找到提高应用程序的可部署性、可管理性、可维护性等的方式。
通过进行用户体验观察,能够在源头保证质量,并对价值流中的其他团队成员产生同理心。理想情况下,用户体验观察有助于我们创建应用的非功能需求,并将其放入共享的待办工作中去,最终我们可以主动地将它们落实到构建的所有服务中,这是 DevOps 文化建设工作的一个重要组成部分。
即使开发人员平时在类生产环境中编写和运行代码,运维团队仍有可能遇到导致灾难性事故的产品发布,因为这其实是我们第一次看到代码在真实生产条件下的表现。出现这种结果的原因是,在软件生命周期中运维学习往往进行得太晚了。
为了解决这一问题,谷歌的一项实践是值得参考的。他们先让开发团队自己在生产环境中管理他们开发的服务,然后才能交由集中的运维团队管理。通过让开发人员自己负责部署工作并且在生产环境中提供支持,他们所开发的产品更有可能顺利地过渡给运维团队去管理。
为了防止有问题的自管理服务进入生产环境,带来组织性风险,我们可以定义服务的发布要求。只有满足这些要求,服务才能与真实客户交互,并暴露给生产环境流量。此外,为了帮助产品团队,运维工程师应该担当顾问,帮助他们做好将服务部署到生产环境的准备。
通过建立服务发布指南,有助于确保用整个组织的集体智慧,特别是运维团队所累积的经验,去帮助每一个产品开发团队。服务发布指南和要求可能包括以下内容。
目前,我们还可能想了解,现在或者未来,这项服务是否要遵从任何监管目标。
以上信息将确保我们有效地管理与服务相关的技术风险,以及潜在的安全和合规风险。它还为生产环境的控制和设计提供了重要的输入
本章讨论了反馈机制,它使得我们可以在日常工作的每个阶段改进服务,不管是将变更部署到生产环境,在出现问题时请求工程师修复代码,让开发人员跟踪下游工作,建立非功能性需求来帮助开发团队编写更优的生产就绪代码,还是将有问题的服务交回给开发团队自己管理。
通过创建这些反馈回路,可以使生产环境的部署更安全,提高所开发代码的生产就绪程度,并且通过强化共同的目标、责任和同理心,在开发和运维团队之间建立更好的工作关系。