SRE 运维解密 - 什么是 SRE:DevOps 模型的具体实践!
Google SRE 代表了对行业现存管理大型复杂服务的最佳实践的一个重要突破。由一个简单的想法“我是一名软件工程师,这是我如何来应付重复劳动的办法”而生,SRE 模型已经发展成一套指导思想、一套方法论、一套激励方法和一个拥有广阔空间的独立职业。
一、系统管理员模式
Dev/Ops 分离
雇佣系统管理员(sysadmin)运维复杂的计算机系统,是行业内一直以来的普遍做法。
这些系统管理员负责将现成的软件组件部署于生产环境中,对外提供某种业务服务。系统管理员的主要工作在于应对系统中产生的各种需要人工干预的事件,以及来自业务部门的变更需求。随着系统变得越来越复杂,组件越来越多,用户流量不断上升,相关的事件和变更需求也会越来越多。于是公司需要招聘更多的系统管理员,来应对日益增多的事件。系统管理员的日常工作与研发工程师相差甚远,通常分属两个不同的部门:开发部(Dev)和运维部(Ops)。
Dev/Ops 分离的优势
这种模型具有许多优势。对新公司来说,这种模式在行业内具有广泛的应用案例可供参考。市场上具有相关从业经历的人也很多,招聘相对容易。
很多第三方工具厂商及系统集成厂商都有现成的工具和软件解决方案帮助一个相对初级的系统管理员团队应对简单的系统维护操作,避免重新发明轮子。
Dev/Ops 分离存在的问题
但是,很少有人提及这样做以及相应造成的 Dev/Ops 分离的团队模型存在一些无法避免的问题。下面我们从两个大的方面来阐述。
1.直接成本。直接成本相对清晰,因为系统管理员团队大部分依赖人工处理系统维护事件以及变更的实施。随着系统复杂度的增加,部署规模的扩大,团队的大小基本与系统负载成线性相关,共同增长。
2.间接成本。研发团队和系统运维团队分属两个部门所带来的间接成本就没那么容易度量了,但是这些间接成本往往大得多。从本质上来说,由于研发团队和运维团队背景各异,技术能力与工具使用习惯上差距巨大,工作目标也截然不同。两个团队对产品的可靠程度要求理解不同,具体执行中对某项操作的危险程度评估与可能的技术防范措施也有截然不同的理解。这些细节上的分歧累积起来,最后逐渐演变成目标与方向上的分歧及形成内部沟通问题,甚至最后上升到部门之间的信任与尊重层面。这样的情形是谁也不愿意见到的,但却是时时上演的。
Dev/Ops 的目标是互相矛盾的
传统的研发团队和运维团队分歧的焦点主要在软件新版本、新配置的变更的发布速度上。
研发部门最关注的是如何能够更快速地构建和发布新功能。
运维部门更关注的是如何能在他们值班期间避免发生故障。
由于绝大部分生产故障都是由于部署某项变更导致的——不管是部署新版本,还是修改配置,甚至有时只是因为改变了用户的某些行为造成了负载流量的配比变化而导致故障。这两个部门的目标从本质上来说是互相矛盾的。
极端来说,研发部门想要:“随时随地发布新功能,没有任何阻拦”,而运维部门则想要:“一旦一个东西在生产环境中正常工作了,就不要再进行任何改动。”由于两个部门使用的语境不同,对风险的定义也不一致。在现实生活中,公司内部这两股力量只能用最传统的政治斗争方式来保障各自的利益。
运维团队常常宣称,任何变更上线前必须经过由运维团队制定的流程,这有助于避免事故的发生。例如:运维团队会列出一个非常长的检查清单,历数所有以前曾经出现过的生产事故,要求研发团队在上线任何功能之前必须将所有这些事故模拟一遍,确保不会重现。这个清单通常没有任何标准,每项事故的可重现程度、问题价值并不一定是一致的。
而开发团队吃过苦头之后也很快找到了自己的应对办法:开发团队宣称他们不再进行大规模的程序更新,而是逐渐转为功能开关调整、增量更新,以及补丁化。采用这些名词的唯一目的,就是为了绕过运维部门设立的各种流程,从而能更快地上线新功能。
二、Google 的解决之道:SRE
SRE 这种模型是 Google 尝试着从根本上避免产生这种矛盾的结果。SRE 团队通过雇佣软件工程师,创造软件系统来维护系统运行以替代传统模型中的人工操作。
SRE 究竟是如何在 Google 起源的呢? 其实我的答案非常简单:SRE 就是让软件工程师来设计一个新型运维团队的结果。当我在 2003 年加入 Google 的时候,我的任务就是领导一个由 7 名软件工程师组成的“生产环境维护组”。当时,我的整个职业生涯都专注于软件工程,所以很自然,我按照自己最习惯的工作方式和管理方式来组建了这个团队。时过境迁,当年的 7 人团队已经成长为公司内部 1000 余人的 SRE 团队,但是 SRE 团队的指导理念和工作方式还是基本保持了我最初的想法。
SRE 团队的两类工程师
SRE 方法论中的主要模块,就是 SRE 团队的构成。每个 SRE 团队里基本上有两类工程师。
第一类,团队中 50%~60% 是标准的软件工程师,具体来讲,就是那些能够正常通过 Google 软件工程师招聘流程的人。
第二类,其他 40%~50% 则是一些基本满足 Google 软件工程师标准(具备 85%~99% 所要求的技能),但是同时具有一定程度的其他技术能力的工程师。目前来看,UNIX 系统内部细节和 1~3 层网络知识是 Google 最看重的两类额外的技术能力。
除此之外,所有的 SRE 团队成员都必须非常愿意、也非常相信用软件工程方法可以解决复杂的运维问题。Google 一直密切关注这两类候选人在招聘通过之后在 SRE 团队中的表现,但是到目前为止还没有发现他们在工作上和成绩上的显著差异。事实上,由于两类工程师技术背景互补,SRE 团队经常能够寻找到全新的、高效的解决问题的方法。
SRE 团队的特点
按照这个标准来招聘和管理 SRE 团队,我们很快发现 SRE 团队成员具有如下特点:
(a)对重复性、手工性的操作有天然的排斥感。
(b)有足够的技术能力快速开发出软件系统以替代手工操作。
同时,SRE 团队和产品研发部门在学术和工作背景上非常相似。因此,从本质上来说,SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的任务。这些 SRE 倾向于通过设计、构建自动化工具来取代人工操作。
SRE 团队的工作与时间分配
SRE 模型成功的关键在于对工程的关注。如果没有持续的、工程化的解决方案,运维的压力就会不断增加,团队也就需要更多的人来完成工作。传统的 Ops 团队的大小基本与所服务的产品负载呈线性同步增长。如果一个产品非常成功,用户流量越来越大,就需要更多的团队成员来重复进行同样的事情。
为了避免这一点,负责运维这个服务的团队必须有足够的时间编程,否则他们就会被运维工作所淹没。因此,Google 为整个 SRE 团队所做的所有传统运维工作设立了一个 50%的上限值。传统运维工作包括:工单处理、手工操作等。设立这样一个上限值确保了 SRE 团队有足够的时间改进所维护的服务,将其变得更稳定和更易于维护。这个上限值并不是目标值。随着时间推移,SRE 团队应该倾向于将基本的运维工作全部消除,全力投入在研发任务上。因为整个系统应该可以自主运行,可以自动修复问题。
我们的终极目标是推动整个系统趋向于无人化运行,而不仅仅是自动化某些人工流程。当然,在实际运行中,服务规模的不断扩张和新功能的上线已经让 SRE 够忙了!
SRE 的经验法则
Google 的经验法则是,SRE 团队必须将 50%的精力花在真实的开发工作上。那么我们是如何确保每个团队都是这样做的呢?
首先,我们必须不断地度量每个团队的工作时间分配。依靠这个数据,SRE 管理层会对在开发工作上投入时间不够的团队进行调整。通常,管理层会要求该团队将一些常见的运维工作交还给产品研发部门操作,或者从产品研发部门抽调人力参与团队轮值值班工作。
此外,还可以停止该 SRE 团队的一切新增运维工作。只有管理层主动维护每个 SRE 团队的工作平衡,我们才能保障他们有足够的时间和精力去进行真正有创造性的、自主的研发工作,同时,这也保障了 SRE 团队有足够的运维经验,从而让他们设计出切实解决问题的系统。
SRE 模型的优势
我们发现 Google SRE 模型在运维大规模复杂系统时有很多优势。
由于 SRE 在调整 Google 系统的过程中常常直接参与开发、修改代码,SRE 文化在公司内部基本代表了一种快速、创新、拥抱变化的文化。
实践证明,SRE 团队运行、维护、改进一个复杂系统所需要的成员数量与系统部署规模呈非线性增长。而运维同样的系统,用传统的系统管理员模型维护则需要更多数量的人。
最后,SRE 模型不仅消除了传统模型中研发团队和运维团队的冲突焦点,反而促进了整个产品部门水平的整体提高。因为 SRE 团队和研发团队之间的成员可以自由流动,整个产品部门的人员都有机会学习和参与大规模运维部署活动,从中获得平时难以获得的宝贵知识。普通的开发人员有多少机会能将自己的程序同时跑在 100 万个 CPU 的分布式系统上呢?
SRE 模型存在的问题
虽然 SRE 模型带来了一些优势,但也存在一些问题。Google 面对的一个持久性的难题就是如何招聘合适的 SRE。
首先 SRE 要和产品研发部门招聘传统的软件开发工程师竞争。
其次,由于 SRE 要求同时具备多项技能,市场上具有相关从业背景和经验的人就更少了。由于 SRE 模型也比较新,行业内关于如何建立和维护 SRE 团队的相关信息并不多。(本书希望能为改变这种情况而努力。)
最后,SRE 团队建立之后,由于 SRE 模型中为了提高可靠性需要采取一些与常规做法违背的做法,所以需要强有力的管理层支持才能推行下去。例如:由于一个季度内的错误预算耗尽而停止发布新功能的决定,可能需要管理层的支持才能让产品研发部门重视起来。
DevOps 还是 SRE?
DevOps 这个名词是在 2008 年年末流行起来的,截止到本书写作时(2016 年初),这个单词的具体意义仍在不断改变中。这个名词的核心思想是尽早将 IT 相关技术与产品设计和开发过程结合起来,着重强调自动化而不是人工操作,以及利用软件工程手段执行运维任务等。这些思想与许多 SRE 的核心思想和实践经验相符合。我们可以认为 DevOps 是 SRE 核心理念的普适版,可以用于更广范围内的组织结构、管理结构和人员安排。同时,SRE 是 DevOps 模型在 Google 的具体实践,带有一些特别的扩展。
三、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%的可用性是没有实质区别的。从最终用户到服务器之间有很多中间系统(用户的笔记本电脑、家庭 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(平均恢复时间)的函数。评价一个团队将系统恢复到正常情况的最有效指标,就是 MTTR。
任何需要人工操作的事情都只会延长恢复时间。一个可以自动恢复的系统即使有更多的故障发生,也要比事事都需要人工干预的系统可用性更高。
当不可避免地需要人工介入时,我们也发现与“船到桥头自然直”的态度相比,通过事先预案并且将最佳方法记录在“运维手册(playbook)”上通常可以使 MTTR 降低 3 倍以上。初期几个万能的工程师的确可以解决生产问题,但是长久看来一个手持“运维宝典”经过多次演习的 on-call 工程师才是正确之路。虽然不论多么完备的“运维手册”也无法替代人的创新思维,但是在巨大的时间压力和产品压力下,运维手册中记录的清晰调试步骤和分析方法对处理问题的人是不可或缺的。
因此,Google SRE 将大部分工作重心放在“运维手册”的维护上,同时通过“Wheel of Misfortune”等项目不断培训团队成员。
变更管理
SRE 的经验告诉我们,大概 70%的生产事故由某种部署的变更而触发。
变更管理的最佳实践是使用自动化来完成以下几个项目:
采用渐进式发布机制。
迅速而准确地检测到问题的发生。
当出现问题时,安全迅速地回退改动。
这三点可以有效地降低变更给 SRE 和最终用户带来的时间成本和服务质量的下降。通过将人工因素排除在流程之外,这些操作将不再受到经常发生在人身上的“狼来了”思想以及对大量重复性劳动的关注疲劳所影响。于是,变更执行的速度和安全性同时得到了提高。
需求预测和容量规划
需求预测和容量规划简单来说就是保障一个业务有足够的容量和冗余度去服务预测中的未来需求。这里并没有任何特别的概念,但是我们发现行业内有许多团队根本没有这个意识和计划去满足这个要求。一个业务的容量规划,不仅仅要包括自然增长(随着用户使用量上升,资源用量也上升),也需要包括一些非自然增长的因素(新功能的发布、商业推广,以及其他商业因素在内)。
容量规划有几个步骤是必需的:
必须有一个准确的自然增长需求预测模型,需求预测的时间应该超过资源获取的时间。
规划中必须有准确的非自然增长的需求来源的统计。
必须有周期性压力测试,以便准确地将系统原始资源信息与业务容量对应起来。
因为服务容量对可用性来说是极为重要的,很自然的,SRE 应该主导容量规划的过程。同时,这也意味着 SRE 需要主导资源部署的过程。
资源部署
资源的部署(provisinging)是变更管理与容量规划的结合物。
在我们的经验里,资源的部署和配置必须能够非常迅速地完成,而且仅仅是在必要的时候才执行,因为资源通常是非常昂贵的。而且这个部署和配置的过程必须要确保能够正确地执行完毕,否则资源就仍然处于不可用状态。
增加现有容量经常需要启动新的实例甚至是整个集群,这通常需要大幅度修改现有的集群配置(配置文件、负载均衡、网络等),同时还要执行一系列测试,确保新上线的容量可以正确地服务用户。
因此,新资源的部署与配置是一个相对比较危险的操作,必须要小心谨慎地执行。
效率与性能
高效地利用各种资源是任何赢利性服务都要关心的。因为 SRE 最终负责容量的部署和配置,因此 SRE 也必须承担起任何有关利用率的讨论及改进。因为一个服务的利用率指标通常依赖于这个服务的工作方式以及对容量的配置与部署上。如果能够通过密切关注一个服务的容量配置策略,进而改进其资源利用率,这可以非常有效地降低系统的总成本。
一个业务总体资源的使用情况是由以下几个因素驱动的:用户需求(流量)、可用容量和软件的资源使用效率。SRE 可以通过模型预测用户需求,合理部署和配置可用容量,同时可以改进软件以提升资源使用效率。通过这三个因素能够大幅度推动一个服务的效率提升(但是并非全部)。
软件系统一般来说在负载上升的时候,会导致延迟升高。延迟升高其实和容量损失是一样的。当负载到达临界线的时候,一个逐渐变慢的系统最终会停止一切服务。换句话说,系统此时的延迟已经是无穷大了。SRE 的目标是根据一个预设的延迟目标部署和维护足够的容量。SRE 和产品研发团队应该共同监控和优化整个系统的性能,这就相当于给服务增加容量和提升效率了。
四、小结
Google SRE 代表了对行业现存管理大型复杂服务的最佳实践的一个重要突破。由一个简单的想法“我是一名软件工程师,这是我如何来应付重复劳动的办法”而生,SRE 模型已经发展成一套指导思想、一套方法论、一套激励方法和一个拥有广阔空间的独立职业。
版权声明: 本文为 InfoQ 作者【董哥的黑板报】的原创文章。
原文链接:【http://xie.infoq.cn/article/0b3d051dc1eb34e0b257354d9】。文章转载请联系作者。
评论