SRE方法论
虽然每个SRE团队都有自己的工作流程、优先级定义以及日常工作规范,但是所有的SRE团队都有一套共同的核心方法论。一般来说,SRE团队要承担以下几类职责:可用性改进,延迟优化,性能优化,效率优化,变更管理,监控,紧急事务处理以及容量规划与管理。SRE管理层针对这些内容制定了一套完整的沟通准则和行事规范,这些规范规定了SRE是如何操作Google生产环境的,也规定了SRE如何和产品研发部门、测试部门、最终用户进行有效沟通。这些准则和规范能够帮助每一个SRE部门保持良好的研发和运维工作的平衡。
下面这几小节具体描述了Google SRE的几个核心方法论。
确保长期关注研发工作
上文已经讨论过,Google 将 SRE团队的运维工作限制在50%以内。SRE团队应该将剩余时间花在研发项目上。在实践中,SRE管理人员应该经常度量团队成员的时间分配,如果有必要的话,采取一些暂时性措施将过多的运维压力转移回开发团队处理。例如:将生产环境中发现的Bug和产生的工单转给研发管理人员去分配,或者将开发团队成员加入到轮值on-call体系中共同承担轮值压力等。这些暂时性措施应该一直持续到运维团队的运维工作压力降低到50%以下为止。在实践中,这种措施实际形成了一个良性循环,激励研发团队设计、构建出不需要人工干预、可以自主运行的系统。只有整个产品部门都认同这个模式,认同50%的安全线的重要性,才会共同努力避免这种情况的发生。
SRE 处理运维工作的一项准则是:在每8~12小时的on-call 轮值期间最多只处理两个紧急事件。这个准则保证了on-call工程师有足够的时间跟进紧急事件,这样SRE可以正确地处理故障、恢复服务,并且要撰写一份事后报告。如果一次轮值过程中处理的问题过多,那么每个问题就不可能被详细调查清楚,运维工程师甚至没有时间从中学习。如果小规模部署下还无法做到合理报警,规模扩大之后这个情况就会更严重。相对而言,如果一个项目的紧急警报非常少,能够持续稳定运行,那么保持这么多on-call工程师可能就是浪费时间。
所有的产品事故都应该有对应的事后总结,无论有没有触发警报。这里要注意的是,如果一个产品事故没有触发警报,那么事后总结的意义可能更大:因为它将揭示监控系统中的漏洞。事后总结应该包括以下内容:事故发生、发现、解决的全过程,事故的根本原因,预防或者优化的解决方案。Google 的一项准则是“对事不对人”,事后总结的目标是尽早发现和堵住漏洞,而不是通过流程去绕过和掩盖它们。
在保障服务SLO的前提下最大化迭代速度
产品研发部门和SRE之间可以通过消除组织架构冲突来构建良好的合作关系。在企业中,最主要的矛盾就是迭代创新的速度与产品稳定程度之间的矛盾。正如上文所说,其表现形式可能是间接的。在SRE模型中,我们选择正面面对这种矛盾,使用的工具是错误预算。
“错误预算”起源于这样一个理念:任何产品都不是,也不应该做到100% 可靠(显然这并不适用于心脏起搏器和防抱死刹车系统等)。一般来说,任何软件系统都不应该一味地追求100% 可靠。因为对最终用户来说,99.999% 和 100% 的可用性是没有实质区别的(详见附录A)。从最终用户到服务器之间有很多中间系统(用户的笔记本电脑、家庭WiFi、网络提供商和输电线路等),这些系统综合起来可靠性要远低于 99.999%。所以,在99.999% 和 100%之间的区别基本上成为其他系统的噪声。就算我们花费巨大精力将系统变为100% 可靠也并不能给用户带来任何实质意义上的好处。
如果100% 不是一个正确的可靠性目标,那么多少才是呢?这其实并不是一个技术问题,而是一个产品问题。要回答这个问题,必须考虑以下几个方面:
● 基于用户的使用习惯,服务可靠性要达到什么程度用户才会满意?
● 如果这项服务的可靠程度不够,用户是否有其他的替代选择?
● 服务的可靠程度是否会影响用户对这项服务的使用模式?
公司的商业部门或者产品部门必须建立起一个合理的可靠性目标。一旦建立,“错误预算”就是“1-可靠性目标”。如果一个服务的可靠性目标是99.99%,那么错误预算就是 0.01%。这意味着产品研发部门和SRE部门可以在这个范围内将这个预算用于新功能上线或者产品的创新等任何事情。
错误预算可以用于什么范畴呢?研发团队需要用这个预算上线新功能,吸引新用户。理想情况下,我们应该使用错误预算来最大化新功能上线的速度,同时保障服务质量。这个基本模型建立起来之后,许多常见的战术策略,例如灰度发布、1% AB测试等就全说得通了。这些战术性手段都是为了更合理地使用整个服务的错误预算。
通过引进“错误预算”的概念,我们解决了研发团队和SRE团队之间的组织架构冲突。SRE团队的目标不再是 “零事故运行”,SRE团队和产品研发团队目标一致,都是在保障业务服务可靠性需求的同时尽可能地加快功能上线速度。这个改动虽小,意义却很大。一次“生产事故”不再是一件坏事,而仅仅是创新流程中一个不可避免的环节,两个团队通过协作共同管理它。
监控系统
监控系统是SRE团队监控服务质量和可用性的一个主要手段。所以,监控系统的设计策略值得着重讨论。最普遍的和传统的报警策略是针对某个特定的情况或者监控值,一旦出现情况或者监控值超过阈值就触发E-mail警报。但是这样的报警策略并不是非常有效:一个需要人工阅读邮件和分析警报来决定目前是否需要采取某种行动的系统从本质上就是错误的。监控系统不应该依赖人来分析警报信息,而是应该由系统自动分析,仅当需要用户执行某种操作时,才需要通知用户。
一个监控系统应该只有三类输出。
紧急警报(alert)
意味着收到警报的用户需要立即执行某种操作,目标是解决某种已经发生的问题,或者是避免即将发生的问题。
工单(ticket)
意味着接受工单的用户应该执行某种操作,但是并非立即执行。系统并不能自动解决目前的情况,但是如果一个用户在几天内执行这项操作,系统不会受到任何影响。
日志(logging)
平时没有人需要关注日志信息,但是日志信息依然被收集起来以备调试和事后分析时使用。正确的做法是平时没人会去主动阅读日志,除非有特殊需要。
应急事件处理
可靠性是MTTF(平均失败时间)和MTTR(平均恢复时间)的函数(参见文献[Sch15])。评价一个团队将系统恢复到正常情况的最有效指标,就是MTTR。
任何需要人工操作的事情都只会延长恢复时间。一个可以自动恢复的系统即使有更多的故障发生,也要比事事都需要人工干预的系统可用性更高。当不可避免地需要人工介入时,我们也发现与“船到桥头自然直”的态度相比,通过事先预案并且将最佳方法记录在“运维手册(playbook)”上通常可以使MTTR 降低3倍以上。初期几个万能的工程师的确可以解决生产问题,但是长久看来一个手持“运维宝典”经过多次演习的on-call工程师才是正确之路。虽然不论多么完备的“运维手册”也无法替代人的创新思维,但是在巨大的时间压力和产品压力下,运维手册中记录的清晰调试步骤和分析方法对处理问题的人是不可或缺的。因此,Google SRE将大部分工作重心放在“运维手册”的维护上,同时通过“Wheel of Misfortune”等项目[2]不断培训团队成员。
变更管理
SRE的经验告诉我们,大概 70% 的生产事故由某种部署的变更而触发。变更管理的最佳实践是使用自动化来完成以下几个项目:
● 采用渐进式发布机制。
● 迅速而准确地检测到问题的发生。
● 当出现问题时,安全迅速地回退改动。
这三点可以有效地降低变更给SRE和最终用户带来的时间成本和服务质量的下降。通过将人工因素排除在流程之外,这些操作将不再受到经常发生在人身上的“狼来了”思想以及对大量重复性劳动的关注疲劳所影响。于是,变更执行的速度和安全性同时得到了提高。
需求预测和容量规划
需求预测和容量规划简单来说就是保障一个业务有足够的容量和冗余度去服务预测中的未来需求。这里并没有任何特别的概念,但是我们发现行业内有许多团队根本没有这个意识和计划去满足这个要求。一个业务的容量规划,不仅仅要包括自然增长(随着用户使用量上升,资源用量也上升),也需要包括一些非自然增长的因素(新功能的发布、商业推广,以及其他商业因素在内)。
容量规划有几个步骤是必需的:
● 必须有一个准确的自然增长需求预测模型,需求预测的时间应该超过资源获取的时间。
● 规划中必须有准确的非自然增长的需求来源的统计。
● 必须有周期性压力测试,以便准确地将系统原始资源信息与业务容量对应起来。
因为服务容量对可用性来说是极为重要的,很自然的,SRE应该主导容量规划的过程。同时,这也意味着SRE需要主导资源部署的过程。
资源部署
资源的部署(provisinging)是变更管理与容量规划的结合物。在我们的经验里,资源的部署和配置必须能够非常迅速地完成,而且仅仅是在必要的时候才执行,因为资源通常是非常昂贵的。而且这个部署和配置的过程必须要确保能够正确地执行完毕,否则资源就仍然处于不可用状态。增加现有容量经常需要启动新的实例甚至是整个集群,这通常需要大幅度修改现有的集群配置(配置文件、负载均衡、网络等),同时还要执行一系列测试,确保新上线的容量可以正确地服务用户。因此,新资源的部署与配置是一个相对比较危险的操作,必须要小心谨慎地执行。
效率与性能
高效地利用各种资源是任何赢利性服务都要关心的。因为SRE最终负责容量的部署和配置,因此SRE也必须承担起任何有关利用率的讨论及改进。因为一个服务的利用率指标通常依赖于这个服务的工作方式以及对容量的配置与部署上。如果能够通过密切关注一个服务的容量配置策略,进而改进其资源利用率,这可以非常有效地降低系统的总成本。
一个业务总体资源的使用情况是由以下几个因素驱动的:用户需求(流量)、可用容量和软件的资源使用效率。SRE 可以通过模型预测用户需求,合理部署和配置可用容量,同时可以改进软件以提升资源使用效率。通过这三个因素能够大幅度推动一个服务的效率提升(但是并非全部)。
软件系统一般来说在负载上升的时候,会导致延迟升高。延迟升高其实和容量损失是一样的。当负载到达临界线的时候,一个逐渐变慢的系统最终会停止一切服务。换句话说,系统此时的延迟已经是无穷大了。SRE的目标是根据一个预设的延迟目标部署和维护足够的容量。SRE和产品研发团队应该共同监控和优化整个系统的性能,这就相当于给服务增加容量和提升效率了。[3]