代码语言:javascript复制作为谷厂出品的神书《SRE Google运维解密》, 笔者早有耳闻并断断续续阅读过部分内容,最近终于静心品阅了一遍(作为拖延症患者, 写完此文与阅读完原书已间隔约半年),里面的很多理念确实值得细细品味(部分章节没有实际操作空间,快读略过)。 5月底恰逢IT内部调整组织架构,其中一个开发运营团队顺手更名为了SRE,不求完美COPY谷歌文化,但求走出符合自己特色的站点可靠工程文化。试运行一段时间后,我想应该会再回头重温一下这本书,一定会有不同的理解。 个人理解SRE三个字母,S R是一块内容,E是另一块。本文不会讲太多关于E即工程化的内容,而重点说说“站点可靠”需要做什么。
先抛个很多人都说好但可能没思考过为什么的问题:
Gmail到底好在哪里?
这个牛逼的邮件客户端2004年愚人节横空出世,
优点很多:界面简洁,容量超大,免费安全,基于谷歌主业实现的优秀搜索、标签分类等等功能,
最重要的是顺带激活了之前半死不活的Javascript语言,而今前端工程师如此火爆真的要感谢下谷歌当时的翻牌。
既然本文谈的是Reliability, 那大家就可以考虑下,
如何能让用户量超过10亿 , 免费用户15G容量上限,如此海量邮件数据和系统的高可靠,
结合下文读者自己去思考下应该怎么做。
What is SRE
那么,最近大火的SRE到底是个什么岗位? 首先要说SRE概念的流行很大一部分原因是源自Google的最佳实践,才导致业界的各种跟风。其实甚至SRE这个名词的发明人Ben Treynor 也从来没有给它公布过一个清晰的定义。 https://landing.google.com/sre/#sre 我先把Google官方 SRE 网页翻译部分节选让大家有个直观感觉。
基本上发生在,当你要求一个软件工程师设计一个运维功能的时候。(牛人说话需要细细揣摩) -- Ben Treynor Sloss, founder of Google SRE
当你把运维视作一个软件问题的时候,SRE就是你所需要的。我们的任务是保护、提供支持和推进藏在所有公有服务背后的软件和系统,永远警惕关注它们的可用性、延迟、性能和容量。 我们是一种在业界任何他处还没发现的复合型工种。类似于传统的运维团队,我们需要保证重要的、核心盈利的系统运行正常(up and running) ,不管面对龙卷风、带宽中断或者配置错误。又不同于传统运维团队,我们把软件所为第一生产力工具,以此管理、维护和关注我们的应用系统;为了达到这个目标,我们必须拥有源码级别的访问权限和道德权威(moral authority), 方可修复、扩展和分布式化代码使其不仅仅可工作,甚至更加健壮地面对互联网的各种异常行为,然后可以开发我们自己全球规模(planet-scale)的平台。作为SRE, 从细粒度的磁盘驱动器IO调度,到跨大洲级别的多系统&海量用户服务能力的宏观规划,我们可以无缝切换。
从官方定义可以提炼出几个基本关键字:关注高可用,高可靠,性能,必备系统和软件开发能力,全栈能力和优秀的学习能力。 写到这,突然感觉这些也是架构师的必备技能呢... 如同敏捷中经常提到的拥抱变化,SRE其中一个指导思想叫“拥抱风险”,这样才能驱动SRE不断的创新和快速试错,因为风险就像BUG永远消灭不了,基于一个可信的“风险容忍度”指标,SRE可以通过管理风险来提高系统可靠程度。
很多人可能要问了,SRE跟DevOps到底有什么区别么?别是 Google 自己炒的一个概念吧?其实两者还是有区别的,不然笔者也不会真的架设了SRE和DevOps这两个团队了。
有篇英文的对比文章, 部分观点笔者并不赞同,读者有兴趣可以去阅读一下(https://devops.com/sre-vs-devops-false-distinction/)
个人总结的区别如下: DevOps 更多是一种理念,用于帮助IT组织架构以敏捷的角度进行调整和演进的方法论,在开发和运维团队中架设起一个健康的合作桥梁。字面其实就可以看出来,很多时候,Dev想要保证尽快的发布和快速迭代,Ops只想确保线上的稳定,否则出问题电话爆掉的是Ops,所以Ops会尽可能的要求放慢节奏...这也算是DevOps的由来吧。DevOps主要关注ITIL、ITSM、Agile、持续交付CD等方面。上方英文作者提到DevOps发现生产故障只是抛出而不是修复,且偏保守,这个笔者完全不赞同,DevOps必须具备处理生产故障的能力。目前笔者的DevOps团队偏向于基础系统(虚拟化、网络、数据库)、持续交付工具等的自动化开发运维。 SRE 的定位相对更加的具体,就是 a) 面向生产环境进行可靠性需求的自我发现 b) 应用自动化运维的软件工程实现 c) 一切影响可靠性的行为通报和推进修复 d) 架构师视野,参与新项目的线上方案可靠性评估 目前笔者的SRE团队更偏向于线上应用的全链路监控、技术/业务数据收集、运维软件研发、自动化排障修复和架构设计方案评审等。
【吐槽】最近 DevOps 又开始跟敏捷、精益绑定输出了很多新概念,且有愈演愈烈之势。新瓶装旧酒笔者并不反对,但是在你把边界界定清楚,职责划分清楚之前,能不能别在“糊涂”外面再包装一层“忽悠”?看到此类文章,笔者都免不了吐槽一番...
如何理解站点可靠
先澄清下,“站点可靠”绝对不是问百度搜出一堆网站,不知道哪个是可靠的,导致都不敢点进去。这里的“可靠”指的是系统在特定的时间跨度内执行系统功能返回期望结果的可能性,也就是说“可靠”是个可度量值,一般通过下面两个基本的公式来计算:
失败平均时间 = 可正确服务的总时长 / 失败次数 失败率 = 失败次数 / 可正确服务的总时长*
通过公式很容易得知要提高可靠性,只要尽可能的减少失败次数,缩短失败时长。但这两点说起来简单,做起来却只能通过不断实践和摸索来实现了。 那具体到底应该如何做呢?开发工程师把应用的稳定性、并发和性能优化到极致是不是就是高可靠了呢?这当然可以作为提高可靠性的手段之一,但线上环境千差万别,基于某些特定条件的本地优化很多时候只可能沦为纸上谈兵。下文将罗列一些常见的提高可靠性的一些手段供大家参考(也是目前米么团队的一些经验之谈)。
小贴士:Reliability vs Availability 很多人们会将可靠性和可用性混淆,其实这是两个完全不同的概念,上文解释过可靠性和计算公式。而可用性更多是一个衡量可用时间的运维参数,计算公式是: =正常运行时长 / 总时长(正常运行 故障停机)
分布式监控
有人要说了我们要提高系统可靠性,最优的方法肯定是“事前”就想到一些隐患并做好预防或补救措施,而不是通过监控这种明显“事后”错误去实现。首先要说这种理解是片面的,监控也可以做到预警,做到“事前”(事故发生前),其次并不是所有故障都可以提前就想透的,最后监控确实是在软件系统不够成熟的情况下,相对容易实施和实现的一种提高可靠性的手段。 只要是搞互联网应用,分布式、微服务这些概念就铁定绕不开,而与它们绑定的监控也就更具挑战性。为什么要监控?监控什么?怎么监控?监控目标是什么?
- 监控什么?
- 基础资源(如虚机/带宽/磁盘/DB/Redis等)的健康检查
- 应用系统的健康检查,不能仅仅是静态页面,最好有应用正常启动后才能访问的ping接口
- 业务指标项统计
- 微服务调用链上的响应时间,异常统计等
- 安全相关(如恶意频繁请求IP)的数据统计
- 业务/技术指标的长期趋势
- 怎么监控?
这里说的“怎么”监控不是问怎么实现,具体方案本来就可能千人千面。这里问的是监控的指导思想是什么,怎么去遵照才算比较好的监控。 比如健康检查类的接口或者日志收集的Agent,务必要评估清楚这些额外进程会对核心的应用系统正常运转的影响范围和影响程度;
- 所有需要通过埋点实现监控的基础组件要求能异步就坚决不能同步,对埋点应用的性能影响降低到最小;
- 对实时性要求特别高的指标项(比如接口响应时间,某些核心业务指标等), 能够做到准实时到实时的统计告警;对监控服务端的数据处理和并发能力提出了特别严苛的要求;
- 监控端必须有丰富的UI展示和报表输出,因为监控还有一项重要目的就是可以用于线上排障(What is down & Why it's down),若监控信息都清晰的渲染在页面上,不管是人工排障还是自动化排障(提供API),都是有绝佳益处的;
- 针对长期/一个时间窗口内的数据能够预见大部分指标项的波动指数和趋势,并据此不断调整预警的区间参数,这就可以做到我们说的“事前”发现可能故障。
- 如何监控我们的监控系统保证高可用呢?笔者也不能说目前自己在用的是万能方案,只能说相对靠谱。可以引入另一个监控系统来做个环形监控,比如CAT做应用监控,Zabbix做基础资源监控,它俩完全可以做一个互相之间的监控,两个都挂的可能性应该小很多了吧?
- 监控后的告警数量一定要保证规模,过多的告警等于没有告警,应该做到只要是告警就应该有清晰的处理和修复机制去规范。
- 监控目标?
报告老师,监控的目标是“告警”。 答错,坐下。
监控的结果展现形式之一是“告警”,但绝不是监控的目标。目标当然是保证站点高可靠咯!所以我们监控了那么多的指标,通过告警这个手段通知到相关干系人;其他的目标上一章节也穿插的提到过的“排障定位”,“预警”,“统计报表”。而真正要提高可靠性,关键是拿到监控数据后的工作:
- 故障重复出现,应该如何推动系统负责人去尽早修复?而不是任由告警发霉。
- 预警的基线区间是基于什么计算出来的?随着数据量的累计,如何不断更新这些预警值?
- 监控到的一些常见异常如何正反馈到各团队,更新他们的checklist,确保不重复犯错;
- 第一次需要人工介入排障和处理的故障,第二次以及日后类似故障如何通过技术手段做到自动识别和自动修复?
智能告警
我们已经收集了很多监控指标数据了,告警是水到渠成的事。就告警本身而言是没有难度,但是如何告,何时告,告的内容详细到什么程度。这些和上面的监控描述的基本一致。这里重点提下“智能”的告警。
- 告警规则的设计
一条通用的告警规则可以抽象为这么几个要素:
代码语言:javascript复制EffectTime - 规则生效的时间窗口
Interval - 数据统计的时间窗口
Variables - 规则对应的变量
Expression - 逻辑表达式(与或非)
Level - 告警级别
举个例子:常规工作时间(EffectTime=9:00 - 18:00) 1分钟(Interval=1min)内的异常数量(Variable=ExpCnt)不能超过5个(Expression=ExpCnt < 5),超过就严重告警(Level=Critical) 当然示例基本是最简单的一种告警规则了,要做好较好的规则解析,就需要完善的规则解析器,甚至可以做出一个UI友好的界面,供运维人员以所见即所得的方式拖曳生成一个告警规则,并自动上线,这个终极目标也是我们目前努力的方向。
很多时候的规则并不是基于特别具体的变量,而是基于各种时间窗口的对比,比如今天9点的订单数,昨天9点的订单数和前一周9点的订单平均数进行比较,才能做出一个告警判断。当然这些也可以抽象为一个一个的变量,但是对于变量的设计需要更加的细致。
其实Google Borgmon对于告警还有一个时间窗口的概念,叫做“最小持续时间值”(笔者命名为滑动时间窗口 SlidingTimeWindow, 下文还会提到),用作当警报持续时间超过这个值的时候才会发送警报,这样不会触发太多的报警。而实现相同功能的这个值在点评CAT中配置名叫 SuspendTime, 完全是从另一个角度考虑的,也就是当前报警触发后,CAT就会暂停/挂起一段时间后,再继续汇总这个时间窗口内的告警信息进行报警。所以说,你看,同一个事情理解和设计角度不同,却实现了同样的功能,怎么理解都很顺畅,这就是架构设计的美妙之处。
- 批量告警的筛选
一般的监控平台(比如CAT,PinPoint) 后面都会再挂一个告警平台,用来做告警渠道的对接。这个告警平台绝对不是简单的报文拼装后的报警,它的职能边界还包括: 在 SlidingTimeWindow 内进行各类告警的优先级排序,如果量比较大,可以抑制某些低级别的告警,保证严重告警不会被淹没
在 SlidingTimeWindow 内的大量告警进行合并和排重,节约网络带宽,更加可以让报警接收人迅速关注到明确的信息;
上面两条筛选都必须基于警告的一些属性和标签进行过滤,那么警告的属性需要尽可能的携带一些必要参数,比如应用名,业务功能模块等等。
- 告警信息如何描述
这个笔者就不举例来说了,无非其一是让报警接收人可以一眼通过标题或简述大约看懂这是一个什么告警和什么严重级别的告警,其二告警的详细描述尽量携带让人可以尽快定位或找到排障线索信息,并添加一些外链可以让人一键跳转到具体的数据展示页面,这样我觉得就差不多了。
自动排障和修复
自动排障目前笔者团队已经可以将日志、数据库、监控数据等各类数据源融合起来,做出一个汇总的报告,并给出一些初步的故障可能根源和建议修复方案等,人工只要介入一下即可。 而自动修复暂时限定在某些业务场景,比如通过用户的手机号在数仓内找到所有的动作轨迹,来确定该用户的问题是卡在哪一步,然后调用验证过的数据修复功能模块自动修复数据,进而让用户继续进行下去。 这个话题太大,而且需要大量故障知识库的总结才能梳理出根源和方案,否则自动修复再引入一些BUG,那就真的尴尬了。本文不再展开。
发布协调师
Google内部是有设置发布协调师这个岗位的(LCE, Launch Coordination Engineering),实际上米么IT虽然没有明确的架设这个岗位,但由PMO的项目经理们兼任了这项职能。比如有个大版本的上线涉及到10多个微服务,服务之间的依赖关系,上线顺序都特别的关键。每逢这种时候都会安排一个大版本上线规划会,集合所有服务的负责人,将变更部分的依赖关系梳理清楚,最终生成一份上线计划提交给运维团队。
特别说明:这里说的是“变更部分”的依赖关系,而不是微服务之间固有的依赖关系。微服务之间固有的依赖关系我们确实可以通过调用链分析来做到,而每次上线对于变更部分的功能依赖会远少于固有关系依赖,这部分如何能够做到尽量的智能评估,也是我们在攻关的一个环节。
大家不要小看这个协调的事情,并不是所有公司都做的好敏捷,并做到保证各服务接口可以兼容上线的,很多时候发生一些不兼容的上线依赖,这种协调工作是非常有必要且重要的。其实Google赋予了LCE更重要的职能,因为LCE必须对各种系统之间的依赖和可能的隐患相比单个系统负责人有更清晰的认识,意味着LCE可以从业务架构师的角色中挑选人担任,甚至LCE应该参与各系统的架构设计评审,这种专业意见由了解大部分系统架构细节的人来给出,更加的有说服力。
数据完整性
- 备份还是恢复
这其实是个老生常谈的问题,就算有些老司机也会在备份这个概念上翻船。大家现在就去看一下自己的系统数据是否做好了备份,假设你确认备份好了,是否就可以松一口气了呢?实际上备份只是第一步,能从备份能恢复出数据来才是最终目的。而不少工程师只是做到了备份,等真的要用到这些数据做恢复的时候,发现有损坏或者各种抓瞎,那备份的意义在哪里呢?
- 保障完整性的手段
Google SRE给出了24中数据完整性的事故组合, 如下图,保障手段分三层:第一层是软删除,就是我们在数据库表设计中常见的删除字段,这样可以保护数据不能被意外真的被物理删除掉;第二层是备份和对应的恢复机制;第三层是复制机制,也就是冗余的概念,将备份再来一次冗余,提高安全性。
知识库和事后总结
其实知识库和事后总结是所有工程师都应该具备的基本素养,但是这点对于SRE的意义更加突出一些,因为很多方案是只能是通过大量的故障记录、归类和总结中得出。目前笔者团队记录了大量的故障信息和总结,但是问题就出在故障的记录和总结还没有形成一个统一规范,导致进行故障合并归类的时候,出现极大的困难,当然这个是一个逐步演进的过程,是无法直接跨过去的。如果你已经具备大量的运维经验,这些抽象提前做好也不是很难的问题。
结 语
本文借鉴了Google运维解密一书中的部分观点,并结合自己团队的一些实践和思考,希望把站点可靠文化更加坚实的做下去。现阶段笔者也是跟团队一起在摸索,更多的新思路还希望大家一起加入探讨。