Files
devops/sre.md
2025-09-17 16:08:16 +08:00

71 KiB
Raw Blame History

<<google SRE运维解密>>

中立的第三方 监控系统,计算可用率指标

错误预算

创新速度 vs SLO(service level object)

google云计算服务 3.5个9 99.95%

toil - 琐事

  • 运维服务中手动的、重复的、可被自动化
  • 漏洞修复

工程工作

4个黄金指标 延迟、流量、错误、饱和度

注意指标统计的长尾效应 区分平均的慢,还是长尾的慢,长尾的慢用分区统计分析。

度量的精度

《SRE Google 运维解密》笔记

  1. 主旨
  2. 概览
  • 2.1 提出 SRE 的动力?
  • 2.2 SRE 聚焦问题点
  • 2.3 庖丁解牛
    • 2.3.1 你看到了什么?
    • 2.3.2 如何管理你看到的?
    • 2.3.3 能否站在全局视角上看问题?
  1. 指导思想
  • 3.1 学会拥抱风险
    • 3.1.1 如何度量服务的风险?
    • 3.1.2 判断服务风险的容忍度?
    • 3.1.2 设计合适的「错误预算」
  • 3.2 服务质量目标
    • 3.2.1 指标在实践中的应用
    • 3.2.2 目标在实践中的应用
  • 3.3 减少琐事
    • 3.3.1 定义琐事
    • 3.3.2 正确理解工程工作的定义
    • 3.3.3 平衡
  • 3.4 分布式系统的监控
    • 3.4.1 监控的 4 个黄金指标
    • 3.4.2 现象 vs 原因
    • 3.4.3 降噪
  • 3.5 Google 的自动化系统的演进
    • 3.5.1 自动化的价值
    • 3.5.2 可靠性
    • 3.5.3 痛苦是可以被表达的
  • 3.6 发布工程
    • 3.6.1 发布工程哲学
    • 3.6.2 持续构建与部署
  • 3.7 简单化
    • 3.7.1 系统的稳定性与灵活性
    • 3.7.2 乏味是一种美德
    • 3.7.3 我绝对不放弃我的代码
    • 3.7.4 「负代码行」作为一个指标
    • 3.7.5 最小 API
    • 3.7.6 模块化 + 发布简单
  1. 具体实践
  • 4.1 基于时间序列数据进行有效的报警
    • 4.1.1 监控系统是什么?
      • 4.1.1.1 数据收集
      • 4.1.1.2 数据存储
      • 4.1.1.3 数据分析
    • 4.1.2 报警
  • 4.2 应急事件的处理
    • 4.2.1 on-call 轮值
    • 4.2.2 有效的故障排查手段
      • 4.2.2.1 理论
      • 4.2.2.2 实践
    • 4.2.3 紧急事件响应
      • 4.2.3.1 当系统出现问题时怎么办?
      • 4.2.3.2 向过去学习,而不是重复它
    • 4.2.4 紧急事故的管理
      • 4.2.4.1 认错
  • 4.3 事后总结和问题根源分析
    • 4.3.1 事后总结:从失败中学习
    • 4.3.2 跟踪故障
  • 4.4 测试
    • 4.4.1 测试可靠性
      • 4.4.1.1 创造一个构建和测试环境
      • 4.4.1.2 大规模测试
  • 4.5 容量规划
    • 4.5.1 SRE 部门中的软件工程实践
      • 4.5.1.1 Auxon 工具的实践
      • 4.5.1.2 推动你的工具
    • 4.5.2 前端服务器的负载均衡
      • 4.5.2.1 有的时候硬件并不能解决问题
      • 4.5.2.2 负载均衡
    • 4.5.3 数据中心内部的负载均衡策略
      • 4.5.3.1 健康管理
      • 4.5.3.2 划分集群
      • 4.5.3.3 负载均衡策略
    • 4.5.4 应对过载
    • 4.5.5 处理连锁故障
      • 4.5.5.1 防止软件服务器过载
      • 4.5.5.2 连锁故障的触发条件
      • 4.5.5.3 解决连锁故障的步骤
  • 4.6 软件研发
    • 4.6.1 管理关键状态:利用分布式共识来提高可靠性
      • 4.6.1.1 使用共识算法的动力
      • 4.6.1.2 分布式共识的系统架构模式
      • 4.6.1.3 分布式共识系统的性能问题
      • 4.6.1.4 分布式共识系统的部署
    • 4.6.2 分布式周期性任务系统
    • 4.6.3 数据处理流水线
    • 4.6.4 数据完整性:读写一致性
      • 4.6.4.1 造成数据丢失的事故类型
      • 4.6.4.2 Google SRE 保障数据完整性的手段
  • 4.7 产品设计
    • 4.7.1 可靠地进行产品的大规模发布
      • 4.7.1.1 起草一个发布检查列表
      • 4.7.1.2 可靠发布所需要的方法论

1. 主旨

之前有人问我这本书的中心思想是什么?忘记了当时给出的答案了,但是让我现在在回答一次的话,应该是——漫步 Google 运维,讲述 Google 这个拥有海量数据、多数据中心的公司,是如果通过各种手段来保证它的可用性。

接下来将会分为四部分对该书进行总结: 概览——了解 SRE 的定义,以及该职位与传统运维的区别 指导思想——讨论 SRE 的工作模式、行事方法,以及日常运维工作中关注的焦点 具体实践——理解 SRE 日常工作背后的理念,讨论具体的构建与运维大型分布式系统的实践。 管理——探索 Google 在培训内部沟通以及在会议方面的最佳实践。ps 这篇笔记里针对这部分是没有描述的,感兴趣建议自己阅读)

2. 概览

2.1 提出 SRE 的动力?

很多公司开发部Dev和运维部Ops是分属两个不同部门的这种 Dev/Ops 分离的团队模型,无法避免的带来两类成本问题: 直接成本:随着系统复杂度的增加,部署规模的扩大,团队的大小基本与系统负载成线性关系,共同增长。 间接成本:研发团队和运维团队背景各异,技术能力和工具使用习惯上差距巨大,工作目标存在不可调和分歧点,而这些会严重影响产品的迭代。 但SRE 团队的作为解决上分歧点被提出来在快速迭代与系统稳定性直接做了平衡。SRE 团队的出现也大大节省了公司的开支。

Cheng: 研发:随时随地发布新功能,没有阻拦; 运维:一旦正常工作,不要进行任何改动; 变更是稳定的大敌80%的故障由变更造成;

Note: SRE最早在十多年前Google提出并应用近几年逐步在国内外TOP互联网公司都开始广泛应用。据笔者了解业界SRE落地成功的权威有Google、Netflix等前者缔造了SRE并奠定了其权威的地位而后者将SRE的实践做到了极致据官方曝露的信息Netflix仅有的个位数的Core SRE支持了190个国家、数亿用户、数万微服务实例业务规模的运维。

互联网有基因论–阿里有交易基因,所以来往、淘江湖会失败;腾讯是即时通讯基因,所以拍拍等交易业务全部扑街。 这就是“康威定律”这是康威在1967年在论文里提出来的后来被软件开发神书《人月神话》引用并总结成四条定律。

康威第一定律 - Conways law: Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations. Melvin Conway(1967) 组织设计的产品/设计等价于这个组织的沟通结构。

Cheng所有产品都是其组织沟通结构的缩影 用人话来说,就是你组织是啥德行,产品就是啥德行。 从这个角度上来说,阿里做来往就扑街,做钉钉就成功,好像还蛮有道理的哦。 阿里的组织架构和沟通机制就非常职业化和政治化,你在钉钉上截图,会带上你自己的名字和手机号码,这与阿里员工截屏会打水印是一样一样的。 阿里的产品架构都非常严谨中规中矩先顶层设计后逐步细化。阿里善于学习、总结、提炼所以阿里去SuperCell学习回来就把中台吸纳、提升为中台概念。 腾讯的组织架构和沟通机制就很有意思小马哥天天在内网跟一帮人探讨产品据说邮件都是秒回。所以QQ、微信都很成功但是企业微信就被无数人吐槽。 腾讯的组织架构就比较散以IEG事业群为例下面有4大工作室天美、北极光、魔方和光子。像盛极一时的王者荣耀就是在这种松散的组织架构中被组装起来的其中一个案例。所以腾讯把SuperCell收购了之后依然是独立管理继续做游戏。 有些公司的沟通机制是老板一言堂,这种产品就很有意思了,天马行空,随意的很。产品形态没有下限,甚至也没有上限,那真是,红旗招展,彩旗飘飘。程序员们也不是面向对象开发,而是面向老板开发。

康威第二定律 - There is never enough time to do something right, but there is always enough time to do it over。 时间再多一件事情也不可能做的完美,但总有时间做完一件事情。 不要试图一次性做到完美,软件开发领域,永远不可能完美,所以建议我们先把事情做完。你看这是不是就是敏捷的思想? 文档可以不完美,拍张照片都行; 上线的功能可以不完美,能跑通就行; 代码可以不完美有bug也没关系咱持续迭代就行。 先把事情做了,再去逐步逼近完美。所以敏捷管理主张持续交付,快速迭代,及时反馈,立刻验证,持续优化。

康威第三定律 - There is a homomorphism from the linear graph of a system to the linear graph of its design organization. 线型系统和线型组织架构间有潜在的异质同态特性。 异质同态指的是系统和组织虽然是两个东西,但是有相同的结构。所以系统是啥样,组织也就得变成那个样子。这个比较好理解,做过技术管理的人在设计组织架构的时候都会参照系统的架构来设置。 比如咱公司如果是单体架构,那就一个开发组就行了;但是如果是前后端分离,那么必然就会拆分为前端组和后端组,分别进行管理。这就是所谓的异质同态。如果系统和组织的结构不匹配,那么将会是灾难。你想象一下系统是前后端分离,但是压根就没拆分前后端的岗位是啥情况?

Cheng长期来看产品形态也可以反噬组织结构。

康威第四定律 - The structures of large systems tend to disintegrate during development, qualitatively more so than with small systems。 大的系统组织总是比小系统更倾向于分解。 这句话非常有意思,系统架构的核心字诀就是“拆”和“合”。 从单体架构开始,分层架构、微服务架构、网络服务架构,都是在拆,拆的越来越小。

DevOps 这个名词的核心思想是尽早的将 IT 相关的技术与产品设计和开发过程结合起来,着重强调自动化而不是人工操作,以及利用软件工程手段执行运维任务等。可以认为 DevOps 是 SRE 核心理念的普适版SER 是 DevOps 模型在 Google 的具体实践。

2.2 SRE 聚焦问题点

确保长期关注研发工作Google 将 SRE 团队的运维工作限制在 50% 以内,剩余的时间花在研发项目上。你需要拥有上帝视角,才能更好的解决问题。 在保障服务 SLO 的前提下最大化迭代的速度Dev 和 Ops 不可调和的矛盾点是 [公式] 。 但是请记住,任何软件都不应该一味地追求 100% 可靠,因为大多数情况下 99.999% 和 100% 的可靠性是没有实质区别的。所以你需要「错误预算」。 错误预算的另一个好处是用一个明确的、客观的指标来决定服务在一个单独的季度中能接受多少不可靠性,用来控制调节发布速度。

Cheng: 我们似乎还没有到达到这样的阶段但方向上是不错的不要在某些方面的可靠性上追求100%不管是硬件的或者软件的因为我们的资源是有限的。而是应该思考在合理SLO下如何及时发现问题监控系统和体系发生故障后怎么办 当然有些系统除外,比如核电站控制系统,登月系统,导弹系统

你需要思考的是,花费巨大的精力将系统变为 100% 可靠是否能为用户带来实质意义上的好处? 从用户终端到服务器之间有很多中间系统(用户终端、家庭 wifi、网络提供商和输电线路等这些系统综合起来的可靠性要远远低于 99.999%。

监控系统:一个监控系统应该只有三类输出:紧急警报、工单、日志 不论是如何优秀研发人员,过多的噪音,一定会影响你对事物的判断。狼来的故事教育我们,你要在狼真的来的时候才去呼救。

应急事件处理:自愈是目标,任何需要人工操作的事情都只会延长恢复时间。要牢记:一个可以自动恢复的系统即使有更多的故障发生,也要比事事都需要人工干预的可用性更高。 一个缓慢的不断重启的实例要好过一个不重启一直泄露资源的实例。 MTTF MTTR 建立运维手册playbook

Cheng关注自愈/自动化修复的幂等性。

变更管理:制定符合自己公司的强管控的变更管理策略,会是一件很有趣、很有意义的事情。比如 Google 最佳实践: - 采用渐进式的发布机制,比如灰度、滚动升级 - 迅速而准确的检测到问题的发生,失败的定义,以及如何验证和发现 - 当出现问题时,安全迅速地回滚 - 需求预测和容量规划:这两点是保障一个业务有足够的容量和冗余度去服务预测中的未来需求。一个盈利性公司的特点是业务不会停滞不前,所以用户群一定会增长并且必然会增长。请为你设计的系统预留这部分容量,如果不能预留,也请能发现增长的趋势,及时作出应急举措。 系统不是摆设,不是死的,动态增长 - 资源部署:确保新上线的容量能够正确地服务而用户,你需要为自己的系统设计合适的上线验收策略。 - 效率与性能高效地利用各种资源是任何盈利性组织都要关心的。SRE 和产品研发团队应该共同监控和优化整个系统的性能,这就相当于给服务增加了容量和提升了效率。从公司的角度看,云产品的超卖策略不就是个很棒的 idea 嘛。(???)

2.3 庖丁解牛

你看到的跟我看到的世界虽然是同一个,但是感受却截然不同。 作为用户,我看到的只是一个可用的系统,这个系统能够完成我需要的功能。我不需要知道背后的原理。 作为研发,除了功能外,你需要做到能够快速理解底层的实现。能够看到截然不同的世界,我觉得这是很有趣的事情。

2.3.1 你看到了什么?

物理服务器:代表具体的硬件(有时候也代表一个 VM 虚拟机) 软件服务器:代表一个对外提供服务的软件系统。 注:物理服务器上可以运行任何类型的软件服务器。

2.3.2 如何管理你看到的????

管理物理服务器的系统管理软件:

管理物理服务器Borg -> Kubernetes (Apache Mesos) 重新编排资源,以求达到最大化的资源利用率。 存储:熟悉各类存储类型,了解目前公司支持的存储类型,为你的系统找到最合适的存储。 网络合理分配网络带宽可以达到降低成本的目的。Google 使用 OpenFlow 协议的软件定义网络SDN是一种普通的非智能交换组件结合集中化的控制器连接方式。该控制器负责计算网络中的最佳路径。 [公式] 个人觉得这个设计思路的实践可以看下这个 饿了么异地多活技术实现API-Router的设计与实现 所有好的技术都应该是从真实的业务场景中提炼出来的。「生命存在的价值应该是能够创造更多的价值,技术亦是如此」,不要为了使用而使用,而是你的业务场景真的需要它,比如系统软件分布式锁服务、监控与报警系统。

Google 底层软件基础设施的设计目的是最高效的使用 Google 的硬件基础设施。站在巨人的肩膀上的你,才有可能看的更高,所以不要重复造轮子,而是学会基于轮子去造车。

2.3.3 能否站在全局视角上看问题?

一叶障目,不辩春秋。 你需要足够熟悉自己负责的业务,但同时你也需要全局视角。可以看看这个 一个完整的 Web 请求到底发生了什么 用户请求的处理过程:用户 -> dns -> 反向代理(负载均衡)-> 网关(鉴权) -> 业务 -> 缓存 -> DB 任务和数据的组织方式:发生未可知的故障的时候,你的系统是否仍能正常提供服务,你的冗余度设计的是否合理。

3. 指导思想

3.1 学会拥抱风险

「过分追求稳定性不仅限制了新功能的开发、产品交付给用户的速度,同时也很大程度的增加了成本。」

风险,定义为遭受伤害或损失的可能性。

3.1.1 如何度量服务的风险?

基于时间的可用性—— 可用性 = 系统正常运行时间 / (系统正常运行时间+停机时间) 请求成功率—— 可用性 = 成功请求数 / 总请求数 在 Google 基于时间的可用性毫无意义Google 所采用的故障隔离手段保证在任何时候任何地方对于一个给定的服务总是可以处理一定的用户流量ps 总结,有钱任性) 请求成功率的计算需要注意一点:不是所有请求都是平等的,一个新的用户注册请求失败和一个单纯的后台接口调用请求失败是不同的

Cheng: 拿WIFI举例云管的请求失败和portal的请求失败的响应要求也是不同 所以,在我们故障处理过程中,我常常问的第一句话是,影响了多少用户,用户是那个给业务带来增长和收入的因素

3.1.2 判断服务风险的容忍度?

用户的容忍度: 用户可用性目标 用户可接受的故障类型(持续低故障率或者偶尔发生的全网中断哪一个更糟糕?) 其他服务指标(比如,广告的投放是否会拖慢用户的搜索体验,这很重要 服务自身对所依赖基础设施的要求: 了解所依赖基础设施的可用性目标 在基础设施的故障时候,是否有逃逸策略 尝试优化基础设施的成本

Cheng: 我们有没有测算过云基础设施的故障率从我的个人体会看是比较高的HA或逃逸策略是很重要的。

3.1.2 设计合适的「错误预算」

便利店收银员在收银的时候,公司会规定一个「收银差异」,在差异内的误差金额由公司承担。而「错误预算」的作用和功能类似于「收银差异」,它的使用使得讨论发布速率更容易,同时可有效的减少任何关于事故的讨论。

为发布和稳定性之间设计一个平衡点,而这个点的体现就是「错误预算」。如果你的错误预算足够的多,你可以快速迭代发布新版本,反之,请保持基于「错误预算」的契约精神,谨慎对待每一次发布。

Cheng错误预算的数据来自中立的监控系统。

3.2 服务质量目标

对于可靠的运维系统来说你需要了解系统中各种行为的重要程度。Google 倾向于用不同的语义描述不同的行为服务质量指标SLI、服务质量目标SLO以及服务质量协议SLA

服务质量指标:请求延迟(处理请求所消耗的时间)、错误率(请求处理失败的百分比)、系统吞吐量(每秒请求数量)、可用性。 服务质量目标:服务某个服务质量指标的目标范围值。比如,定义搜索请求的服务质量目标为延迟小于 100ms。 SLO 的选择和公布可以帮助设立用户对于服务质量的预期,以及应对那些没有根据抱怨「服务太慢了」的行为。 服务质量协议:指服务与用户之间的一个明确的,或者不明确的协议,描述了在达到或者没达到服务质量目标之后的后果。

Cheng: 内部更关注SLO内部设置的目标驱动你的测量阈值(例如,仪表板和警报)。通常,它应该比 SLA 更严格。 例如,如果你设置了 99.9%的 SLO那么服务可以停机的总时间如下: 30 天43 分钟(3/4 小时) 90 天129 分钟(~2 小时) 5个999.999%5分钟 (每年)

''' 集群可用性的关键指标包含五个集群健康度、Pod 创建成功率、残留 Terminating Pod 的数量、服务在线率和故障机数量。 集群健康度:通常使用 HealthyWarningFatal 三个值来描述,其中 Warning 和 Fatal 对应告警体系,例如 P2 告警发生,那集群就是 Warning而 P0 告警发生,那集群就是 Fatal必须进行处理。

Pod 创建成功率:这是一个非常重要的指标,蚂蚁集团一周的 Pod 创建量在百万级别,如果成功率波动会造成大量 Pod 失败,同时 Pod 成功率下跌也是集群异常的最直观反映; 残留 Terminating Pod 的数量:有人可能会好奇为什么使用残留 Terminating Pod 的数量,而不用删除成功率?这是因为当 Pod 数量达到百万级别后,即使删除成功率达到了 99.9%Terminating Pod 的数量也有数千,残留这么多 Pod 占用应用容量,在生产环境中是不可接受的; 服务在线率:这个指标是通过探针来衡量的,探针失败则意味着集群不可用; 故障机数量:这是一个节点维度的指标,故障机通常是指无法正确交付 Pod 的物理机,集群故障机需要做到“快速发现,快速隔离,及时修复”,否则会对集群容量造成影响。

'''

''' 几个月前T云上海光缆被挖断视频业务受到了影响基本上70%-80%的视频是无法观看的,从业务特点上,是因为我们绝大部分的主播都集中在江浙沪一带,而北方和华南的主播是比较少的,所以虽然是一个局部地域的影响,对于我们来说,基本就是全局的。 不过从云厂商的角度来看实际的监控情况显示一个地域的部分影响只占全局影响的2%-3%左右这时对于云厂商就要判断为了这2%-3%的局部影响,要不要做全局的切换动作,对于其它客户会不会造成影响等等,他就要考虑更多的因素。 所以,仅仅等这样一个决策,就花了很长时间,最终从业务角度出发和考虑,还是做了切换,保障了业务恢复。 '''

3.2.1 指标在实践中的应用

运维人员和最终用户各关系什么:只有理解用户对系统的真实需求才能真正决定哪些指标是否有用,盲目将监控系统中的所有指标都定义为 SLI 不是一个好方法。

用户可见的服务系统 : 可用性 存储系统:延迟、可用性和数据持久性 大数据系统:关系吞吐量和端到端的延迟 所有系统:正确性 指标的收集、汇总、标准化

平均值 + 累计概率分布是个好建议

Cheng: 最大化的降低误报率,假阳性 - 是一种无谓的开销,去毛刺

3.2.2 目标在实践中的应用

思考用户关系的方面入手,而不是现在能度量什么入手(如何正确做好,而非现在能做什么

目标定义:清晰具体为上 目标选择:不要仅以目前的状态为基础选择目标、保持简单、避免绝对值、SLO 越少越好不要追求完美SLO尽量保持简洁好的SLO能指导团队有效优化产品而不是做无用功 有效的控制手段:比较指标和目标,以决定是否执行什么操作 不要建立过高的用户预期:留出一定的安全区、实际SLO也不要过高

3.3 减少琐事

3.3.1 定义琐事

琐事被定义为手动性、重复性的、可以被自动化的、突发的、没有持久价值的、与服务同步线性增长的。

Cheng: 系统的增加带来人力开销的线性增加

3.3.2 正确理解工程工作的定义

工程工作Engineering是一种新型的本质上需要主观判断的工作。典型的活动主要包括 软件工程:编写或修改代码,以及所有其他相关的设计和文档的工作。 系统工程:配置生产系统、修改现有配置,或者用一种通过一次性工作产生持久的改进的方法来书写系统文档。 琐事:与运维服务相关的重复性的、手工的劳动。 流程负担:与运维服务不直接相关的行政负担。

3.3.3 平衡

平衡琐事的比重Google 建议琐事所占有的比例要低于 50%。 「救火很重要,但是疲于一直救火,会阻止你去思考该如何从本质上去解决问题。」

Cheng: 早期的WIFI平台感觉一天到晚处于救火状态大家提心吊胆参加过第一届互联网大会重保的同事应该都有体会。原来天翼看家也是。

3.4 分布式系统的监控

如果你需要随时随地知道服务的运行状况,那么你需要构建一个适合自己业务的监控系统。知道服务运行状况的最终目的是保证服务的稳定性,确保其能更好的服务用户。

3.4.1 监控的 4 个黄金指标

延迟:服务处理某个请求所需要的时间。能够区分请求成功和失败这点很重要。 流量:使用系统中的某个高层次的指标针对系统负载进行度量。比如每秒 HTTP 请求数量等。 错误:请求失败的速率,显示、隐式、或者是策略性导致的失败。 饱和度:系统中某种受限资源的具体度量,比如 CPU 、内存等。 监控中度量指标不是目的,需要为所度量指标设置合适的阈值,以期在指标不符合预期的时候,能迅速做出反应,缩小影响范围,这才是重点。

Cheng如果有大量的监控结果需要主管判断分析和复杂响应设计不佳应重构好的告警应该能够直击问题从而快速响应。

Cheng: 思考监控度量指标的精度、分组、汇总处理等。

p56 -- 监控系统应该回答的问题

监控指标简化,不常用的(比如一个季度没有用到)移到候选区。

p51: 我们会避免任何“魔法”系统--例如试图自动学习阈值或自动检测故障原因的系统。。。。我们坚持监控系统规则越简单越好,同时要求这些监控规则可以检测到某个非常简单、具体,但是严重的异常情况。用于容量规划、流量预测等方面的监控规则可以稍微复杂一些。

Cheng按这样的标准AIOps成了反模式???

健康检查 健康检查有两种模式:由外向内的健康检查,验证服务是否正在运行,并确定服务的响应时间/延迟;由内向外的健康检查,跟踪应用程序和系统指标,可以在事故发生前发现潜在的问题(包括性能问题)。 模式1 由外向内的健康检查 正常运行时间Uptime —— 这个指标回答了一个由来已久的问题,“我的服务是否在运行,是否在做应该做的事情?”健康检查程序 ping 了待查服务后,如果收到了响应,就说明服务启动了,如果没有响应,就意味着需要开始补救工作 用户感知的时延User-perceived latency —— 我们必须从全球多个位置检查服务时延。例如,从日本访问服务的用户感知的时延可能与从西班牙和美国访问服务的用户感知的时延不同。可以使用健康状况检查 API 调用的时延作为用户感知时延的代表。 上述两组的组合还可以作为服务的综合可用性信号。

Cheng: 支撑验证就属于这类 模式2 由内而外的健康检查 那么应该关注哪些应用程序指标呢?至少收集以下四种信号。 请求率 —— 服务有多忙? 错误率 —— 服务中是否存在任何错误?如果有,有多少个,多久发生一次? 请求时长 —— 服务响应请求需要多长时间? 饱和度 —— 服务有没有超载?还有多少增长空间? Cheng: 比如看家的S3的使用情况IOPS的情况【IOPS测算队列的饱和度 饱和度趋势预测 img

反模式: 使用日志对指标建模 使用日志数据对度量建模开销很大(意味着需要花更多的钱),并且增加了提取、处理和反馈的时间,从而增加了 MTTD(平均检测时间),这两种后果都不可接受。 AIOps?

通过使用更复杂的技术(包括机器学习),可以主动发出告警并检测异常情况,从而为服务所有者提供更好的体验。

告警反模式

  • 不要依赖人工观察。 随着系统规模和复杂性的增加,我们不能依赖人工 24/7 的盯着监视器来查看服务运行状况趋势,并在超过阈值时呼叫某人来解决问题。我们需要依靠机器和算法,在出现问题时通知我们主动触达,这也能够排除人为错误,并尽可能将过程自动化。+自愈
  • 并非所有告警都是等价的。 不要以相同的方式对待所有告警,将服务中的每个小问题都作为告警发送电子邮件/Slack 通知只会导致垃圾邮件泛滥,并大大降低信噪比。对于每一个可能导致客户问题/违反 SLA(关键问题)的服务问题,都需要呼叫工程师(使用类似 PagerDuty 的东西)进行处理,其他所有内容都应该作为问题单记录,或者作为日志记录。降低假阳性比例

Cheng: 云宽带监控的假阳性

3.4.2 现象 vs 原因

你以为你以为的就是你以为的嘛?并不是 现象:什么东西出了故障 原因:为什么出了故障

例子: 现象:返回 HTTP 500 或者 404 回复速度很慢 原因:数据库服务器拒绝连接 or CPU 被某个排序操作占满,某根网线被压在机柜下面造成断续的网络丢包。 「在一切合理的答案都被逻辑排除后,剩下的那个因为主观,所以被贴上“不可能”的标签的答案即为正解。」

3.4.3 降噪

过多监控会带来负面效应,对比一天收到几条和几百条监控你的前后变化,会发现这是一件「被人忽略,但是收益很高」的事情。

Cheng: 告警过多/告警风暴=没有告警

Cheng打补丁 vs. 根本修复,打补丁可以为根本解决争取时间,但会形成技术债务。

3.5 Google 的自动化系统的演进

你会变老,反应也会变慢,但机器不会,机器永远会按照你给的指令「周而复始,循环往复」的运行。

Cheng: MySQL on Borg - MOB, 一般理念是数据库必须是坚如磐石但是理念也在逐步转变很久以前大家都觉得开源的MySQL相比Oracle是不值得信赖的当然现在也有这样的认识比如一些金融相关的系统原来单体结构硬件故障不可接受上云后这种状况不得不接受但这种认识在转变因为对可靠性的理解发生了变化我们把关注点更多的放在总体的可用性上放在自动化、自愈、合理的资源调度达到用户的连续服务上更多的技术的演进支持了这种观念下的落地云原生就是重要的组成。现在我们的服务已经都构建运行在容器之上了负载分担、容量弹性、故障的自愈都方便实现那么数据库呢 MOB释放了60%的硬件资源,这个怎么做到??? Cheng: “测试 - 修复”的问题,特别是在测试发现配置或数据库问题时,进行修复动作如果不具备幂等性,可能造成系统处于不一致状态。

3.5.1 自动化的价值

一致性:任何一个人或者一群人执行数百次动作时,不可能保证每次都用同样的方式进行,但机器可以。 平台性:平台性的延伸价值意味着其通用性更高。 修复速度更快:一个自治系统恢复的速度从概率上来说会小于手工接入使其恢复的速度。

3.5.2 可靠性

你要确保的第一要素是可靠性,系统能够按照你预期的自动化方式运行,不能有分毫差距。**大规模自动化运维的带来的风险是,允许大规模故障的爆发。**收益和风险的正相关关系,很重要。

3.5.3 痛苦是可以被表达的???

如果在推动自动化的过程中受阻,请牢记以下两点:

  • 一个不亲自运行自动化的团队是没有动力去建设一个能够很容易自动化的系统的
  • 一个产品经理的时间表如果不受低质量的自动化影响,他永远优先新功能的开发,而不是简化和自动化

Cheng: 自动化的演进

  • 服务管理,故障检测和重启,日志正则过滤
  • 数据库跟踪,工具去监控,服务器的摘除,机器的损坏

3.6 发布工程

发布工程是 Google 内部的一项具体工作。主要负责定义软件发布的全部步骤——包括软件是如何存储于源代码仓库,构建时是如何执行编译的,如何测试、打包、最终部署。

Google 的体量之大,所以类似流水线的精细化分工会为其带来相应的收益。但对于体量相对较小的公司,发布工程这部分工作常常由对应的研发人员或者运维人员所负责。所以我们可以借鉴 Google 在发布工程中的设计哲学,减少发布所带来的稳定性问题。

3.6.1 发布工程哲学

自服务模型:开发工具,制定最佳实践,让产研团队可以自己掌握和执行自己的发布流程。 追求速度:「面向用户的软件组件重新构建非常频繁,因为我们的目标是让用户可见的功能越快上线越好」。 密闭性:构建工具必须确保一致性和可重复性。 强调策略和流程:可回溯的历史,能够在系统发生问题的时候,让你快速回退。

3.6.2 持续构建与部署

构建、分支、测试、打包、部署,请确保每个节点所做的事情符合预期。

3.7 简单化

可靠性只有靠对最大程度的简化不断追求而得到。 「凡是复杂的即为易错的

Cheng: 简洁的是美的 要么去复用你的代码 要么去拆分你的服务 高内聚,低耦合

3.7.1 系统的稳定性与灵活性

清楚地知道自己需要先探索以及失败才能真正理解需要完成的任务。一个对于 SRE 管理系统方法的建议是「始终在系统的灵活性和稳定性上维持平衡」。SRE 通过创造流程、实践以及工具来提高软件的可靠性。同时SRE 需要最小化这些工作对于开发人员的灵活性造成的影响。

3.7.2 乏味是一种美德

我们总是希望程序按照设计的进行执行,可预见性的完成目标,但是生产环境中的意外是 SRE 最大的敌人。

必要复杂度和意外复杂度: 必要复杂度是一个给定的情况所固有的复杂度,不能从问题中移除。比如,编写一个 Web 服务器需要处理快速提供 Web 页面的必要复杂度。 意外复杂度可以通过工程上的努力来解决。比如,我们使用 Java 编写服务器代码,试图减少 GC 的影响。

3.7.3 我绝对不放弃我的代码

因为工程师也是人,他们经常对于自己编写的代码形成一种情感依附,这种冲突在大规模清理源代码树的时候并不常见。但是那些没有使用的源代码,会变成一颗颗会在未知时间引爆的炸弹,为了世界和平,所以请深呼吸,然后删除它。

3.7.4 「负代码行」作为一个指标

「软件膨胀」用来描述软件随着时间的推移不停地增加新功能而变得更慢和更大的趋势。这种趋势从直观上看就是不可取的,所以:

  • 要么去复用你的代码
  • 要么去拆分你的服务
  • ……
  • 最终让你的代码结构看起来清清爽爽,这是目的

3.7.5 最小 API

设计 API 请遵循这样一个原则「不是在不能添加更多的时候,而是没有什么可以去掉的时候,才能达到完美」。

3.7.6 模块化 + 发布简单

很多年以后,你会明白解耦合你的代码,确保「高内聚,低耦合」,是多么朴实但是又有深意的一句话。

4. 具体实践

这本书还是挺良心的告诉了你思想是什么同时又告诉了你基于这些思想Google 是如何实践的。具体包含书中 10 - 27 章,将会被分为以下 7 个部分进行介绍:

监控10 章 应急事件的处理11 - 14 章 事后总结和问题根源分析15 - 16 章 测试17 章 容量规划18 - 22 章 软件研发23 - 26 章 产品设计27 章

4.1 基于时间序列数据进行有效的报警

离开监控系统我们就没有能力辨别一个服务是不是在正常提供服务。Google 的监控系统不仅要分析一些简单的系统指标(比如某一台在欧洲 Web 服务器的平均响应时间),还要分析更高抽象级别的指标(比如整个欧洲地区 Web 服务器的响应时间分布情况)。

4.1.1 监控系统是什么?

监控系统从本质上来说就是一个可编程的计算器。并且加入了一些语法糖,从而可以让它产生报警信息。通常由数据收集、数据存储、数据分析三个部分。

4.1.1.1 数据收集

在数据收集部分需要解决的问题是:

需要针对什么指标进行收集? 收集的时间范围是多久? 精细化收集的粒度需要多高?

4.1.1.2 数据存储

从单台机器上收集到的数据,需要汇总处理,那么数据如何存储,才会更好分析? 一般选择的都是基于时间序列的数据库,从回溯历史和硬件读写的角度,该类型的数据库都合适。

4.1.1.3 数据分析

汇总全部的数据针对服务质量指标SLI设置阈值不满足阈值的时候,告警通知对应负责人,人工介入解决问题。

4.1.2 报警

从日常生活中来看,我们报警,是因为遇到了需要警察帮忙才能解决的问题,系统的报警也应该如此。频繁报假警的会被处罚,对于一个具有仲裁机制的监控系统来说也应该如此,对于那种多次发出报警但是没有人响应的报警,删除它或许不是一件坏事情。 「提升专注力是一件好事情,可有可无的东西请统统忽视它。」

4.2 应急事件的处理

4.2.1 on-call 轮值

on-call 是一种手段,目的是为了保障服务的可靠性和可用性。为了 on-call 的工程师能够快速的解决问题,平衡 on-call 工作是一个很好的建议。

从数量上平衡SRE 团队 50% 的时间花在软件工程上,在其余的时间中,不超过25%的时间用来on-call 211法则50%软件工程25%on-call25%其他日常运维该法则下25%时间用于on-call要满足7x24小时on-call轮值制度至少要8个SRE

Cheng: 我们实践25%on-call很多内容是由支撑承担书中体系没有支撑团队&监控团队的概念,告警直接响应给运维)。 3层过滤1层统一监控2层支撑人员3层才到运维 面向终端用户建议非常紧迫的服务5分钟内响应非敏感业务30分钟。

从质量上平衡每12个小时的轮值最多只能处理两个紧急事件。 避免「过度联想」和「习惯性思维」。 事物的本质很少呈现表象上。脱脂牛奶也可以假装护肤霜

Cheng合理安排,保持适度压力,避免过度疲劳 on-call资源

  • 清晰的问题升级路线
  • 清晰定义的应急处理步骤
  • 无问责,对事不对人的文化氛围

4.2.2 有效的故障排查手段

系统正常,只是该系统无数异常情况下的一种特例。 —— John Allspaw ps 这句话和「幸存者偏差」理论都很让我震惊)

事后: 故障复盘的核心:从故障中学习和提升! 故障复盘的教训:故障根因往往不止一个,聚焦引起故障原因都是哪些,是否都有改进空间。 故障复盘的心得:解决问题,而不是不断提出新的问题! 1、故障复盘黄金三问 1第一问故障原因有哪些 2第二问我们做什么怎么做才能确保下次不会出现类似故障 3第三问当时如果我们做了什么可以用更短的时间恢复业务这点非常重要 注意事项:对事不对人,不允许出现互相指责和埋怨甩锅。故障复盘的核心是找到原因并加以改进,落地优化。 2、故障判定的三原则 1健壮性原则每个组件自身要具备一定自愈和高可用能力而非全部由下游依赖方兜底 2三方默认无责对内谁受影响谁改进,对外推进第三方改进(稳定性要做到相对自我可控,而不是完全依赖外部) 3分段判定原则对于原因较复杂或链路较长的故障建议分阶段评估不同阶段有不同的措施。这一原则的出发点是要摒弃“故障根因只有一个”的观点。

CG确定了一个问题根源时应该将系统问题位置,如何定位,如何修复,如何防止,待办事项总结下来。

4.2.2.1 理论

故障排障过程被定义为反复采取假设-排除手段的过程。大致就是通过观察系统的监测指标和日志信息了解系统目前的状态。再结合我们对于系统构建的原理、运行机制,以及失败模型的了解,提出一些可能的失败原因。

4.2.2.2 实践

书写系统的故障报告是个好习惯,系统故障报告里要写清楚:

  • 系统预期是什么
  • 系统实际的结果是什么
  • 如何重现故障
  • 如何修复故障等 报告问题 -> 定位 -> 检查 -> 诊断 -> 测试和修复 这个一个完整排障的链路。

p120 高等级故障,你的第一反应可能是立即开始故障排查过程,试图尽快找出问题根源,这是错误的!不要这样做。 定位问题的过程中,最重要的不是排障,是如何尽最大可能让系统恢复服务。 定位问题时,应及时保存问题现场,比如服务器日志,以便以后进行根因分析。

Cheng: 5WHY最近的一次私有化监控故障为例。 现象:用户局部间歇性不可用。 W能否应急如何快速恢复业务这一问题与故障的等级有关 W与哪些平台相关各平台有没有故障Action检查平台。 W网络有没有故障Action抓包分析有出包回包部分丢失。 => 网络问题(假设) => 验证 W包在哪里丢失Action上联SPINE进一步抓包定位

总结:

    1. 不可经验武断;疑难故障的排查是一系列的假设+验证网络问题的假设没有错结论显示判断结果有错实际上并不是上联设备配置问题导致丢包而是下联设备的IP配置问题。
    1. 事后总结(验尸报告-postmortem如何定位+如何修复+如何防止再次发生

CG确定了一个问题根源时应该将系统问题位置,如何定位,如何修复,如何防止,待办事项总结下来。 morgue

关注最近一次修改。

Cheng: 业务层面的监控怎么做?确保无侵入性

Cheng做的好的做的不好的

  • 监控是不是发现、及时、到位?误告警?
  • 应急响应有没有发挥作用?有没有可以完善的地方?
  • 远程不可访问了怎么办?带外访问通道?

4.2.3 紧急事件响应

东西早晚要坏的,这就是生活。

Cheng紧急事件必定是不常发生不常处理之事必不擅长。所以要建立应急流程并不断演练熟悉。

4.2.3.1 当系统出现问题时怎么办?

测试导致的紧急事故chaos engineer停止测试恢复数据 变更部署带来的紧急事故:回滚 流程导致的严重事故:终止流程

Cheng: 三个案例值得运维支撑的同学学习

所有系统不但一定会出问题而且会以没有人能想到的方式出现问题。Google 从这些中学到的最关键的一课是,所有的问题都会有对应的解决方案。

4.2.3.2 向过去学习,而不是重复它

Cheng

  • 为事故保留记录,历史就是学习其他人曾经犯过的错。所以,故障总结要能够复盘,才能变成资产,否则是摆设。
  • 提问脑补,甚至那些大的、不可能的问题。
    • vsw故障怎么办vcpe故障怎么办bras故障怎么办
    • 整个DC有问题怎么办
    • 系统被流量攻击怎么办?
    • 系统负载突然提高超出规划容量怎么办?
  • 鼓励主动测试,对提出的问题,制造场景来演练。

4.2.4 紧急事故的管理

如果事前没有对可能发生的紧急事故进行演习,事故发生时,一切管理理念都不起作用。

嵌套式职责分离: - 事件总控:组织,协调 - 事件处理团队:执行,解决,由实际处理人组成 - 发言人:向相关方发布故障处理进展,确保相关方都知道事故处理进展 - 规划负责人为处理团队提供支撑工作bug记录、订餐、职责交接安排、处理过程特殊操作的记录等

通知中心:受到事故影响的部门或者负责人需要实时跟事故总控负责人联系 实时事故状态文档:确保关联的每个人知道事故的进展 明确公开的职责交接文档:确保后续处理的人能够最快投入处理

Cheng以上职责至少需要总控、处理团队、发言人总控和发言人可以合设。以前要求高等级故障集中处理鼓励面对面集中处理war room考虑到跨团队和故障发生时间等因素看起来是有难度的至少确保以上职责人员紧密连线、信息共享、及时跟进。可以“拉群”讨论处理IRC。 故障演习,团队贯穿,内外部

4.2.4.1 认错

害怕犯错是人类的本性,如果不小心犯了错,那么请一定记得要认错。

先宣布事故的发生,随后找到一个简单解决方案,然后宣布事故结束,要比事故已经在持续了几个小时以后才想起来流程管控更好。如果事故满足以下任何一条标准,建议及时宣布: 是否需要引入第二个团队来帮助处理问题? 这次事故是否正在影响到最终用户? 在集中分析了一个小时候,这个问题是否依然没有得到解决?

4.3 事后总结和问题根源分析

4.3.1 事后总结:从失败中学习

Google 事后总结的哲学:协作和知识共享,建立事后总结文化

事后总结的主要目的是为了保证事件被记录下来,理清所有的根源性问题,同时关键的是,确保实施有效的措施使得未来重现的几率和影响得到降低,甚至避免重现。 事后总结不是一种惩罚措施,而是整个公司的一次学习机会。

SRE中最重要的是「对事不对人」的事后总结不应该简单地指责或者抱怨某个团队,而应该确实提出服务如何能够获得进步。

Cheng 总结的条件

  • 二级及以上故障
  • 数据丢失
  • on-call需要人工介入的回滚、流量切换等
  • 解决耗时过长的
  • 监控问题(人工发现,而非告警发现)

Cheng 开放的评论系统,透明化的共享机制 postmortem模板 拥抱故障,卓越运维

Cheng: MTTF,MTTR,MTB所以我们可以看到 MTBF = MTTF + MTTR因为MTTR通常远小于MTTF所以MTBF近似等于MTTF因此我们平时常用的衡量指标就是MTBF和MTTR。 衡量稳定性的指标明确了,那我们稳定性的目标也就明确了: 提高MTBF 降低MTTRF

4.3.2 跟踪故障

提高可靠性的唯一方法论是建立一个基线baseline同时不断跟踪改变Google 使用 Outalator——一个故障跟踪分析工具来做这件事情。

该系统可以获得如下信息:

每次 on-call 轮值发生的报警次数是多少 上个季度中可操作的报警和不可执行的报警的比例是多少 哪个消耗的人工最多等 能够对历史数据进行定量的分析,找出可优化的方向,这些是将来可改进的基本点 。

4.4 测试

4.4.1 测试可靠性

如果你还没有亲自试过某件东西,那么就假设它是坏的

测试,是一个用来证明变更前后系统的某些领域相等性的手段,其目的是维持系统的稳定性。软件测试的类型:

传统测试:单元测试、集成测试、系统测试(包括冒烟测试、性能测试、回归测试)。 生产测试:配置测试、压力测试、金丝雀测试等。

4.4.1.1 创造一个构建和测试环境

测试重点集中在「用最小的力气得到最大收益的地方」。所以在测试一个系统的时候,请从以下方面开始思考:

能否将源代码按照重要程度区分出优先级 是否某些函数或者类是非常关键的,或者对业务运营极为重要 哪些 API 是其他团队需要集成使用的

4.4.1.2 大规模测试

测试大规模测试使用的工具(确保你的工具是正确的 针对灾难的测试 确保测试的准确率 生产环境和测试环境分离(分离会带来不一致的问题,导致你没有办法在测试环境稳定重新问题,但是危险总是不可能完全消除的,你需要做取舍 允许测试失败(缩短反馈周期 集成(针对配置文件集成测试也很重要 生产环境探针(监控和测试并不能完美的刻画出一个正在运行的实时变化的系统,所以你需要探针,总觉得跟古代试毒的操作很像……

4.5 容量规划

4.5.1 SRE 部门中的软件工程实践

SRE 开发的工具也是一个完整的软件工程项目,它打破了团队大小与用户服务规模成比例增长的关系。

4.5.1.1 Auxon 工具的实践

Auxon 是 SRE 内部开发的一个自动化容量规划工具。因为传统的容量规划方法,不可靠、耗时巨大,同时不够精确。所以提出了设计并开发了基于意图的自动化容量规划工具。自动化所带来的附加价值是,能够更快速的应对容量规划的变更。「意图是服务服务责任人对如何运维该服务的理性表达。」

基于意图的容量规划:列出你的要求,而不要拘泥于具体的实现细节。

用户不需要关系存储的数据在哪个区域、哪个机房、哪个机柜,哪个磁盘上,他需要你确保的是存储的数据一定不会丢失。同理,能够提供满足用户意图的自动化容量规划工具也应该被设计的如此。

A我需要 50 个 CPU 的资源,必须在集群 X、Y、Z 中,为服务 Foo 使用

B我想要满足 Foo 在每个地理区域的需求增长,同时保障 N+2 的冗余度

很明显 B 的意图更加清晰,表达产品意图的先决条件是:

依赖关系 性能指标 优先级

4.5.1.2 推动你的工具

持续的和完整的推广方案 用户的拥护 资深工程和管理层的支持,前提是你的项目是有实力潜力的 不要过于关注完美和解决方案的纯粹性,尤其是当解决问题的边界不够清晰的时候。我们应该更快速的发布和迭代。

4.5.2 前端服务器的负载均衡

4.5.2.1 有的时候硬件并不能解决问题

用户流量负载均衡系统是用来决定数据中心中的这些机器中的哪一个用来处理用户的某个请求的。 理想情况下,用户流量应该最优地分布于多条网络链路上、多个数据中心中,以及多台服务器上。

Cheng: 用户流量分布于所有服务器 vs. 按规划容量分布用户流量;似乎后者要求更高,一是对容量有非常合理规划,二是因为单机负载高,要有快速的响应和恢复机制。

问题是:如何理解最优的分布?

逻辑层(是在全局还是在局部) 技术层(硬件还是软件) 用户流量的天然属性 以简单的搜索请求和视频上传场景来考虑最优问题。搜索系统用户最关心的是「延迟」而视频上传系统用户关心的则是「吞吐」。所以在最优化负载的时候:

  • 搜索请求将会被发往最近的、可用的数据中心。判断条件是包的 RTT。
  • 视频上传流则会选择——目前带宽没有占满的链路,来达到最大化网络吞吐量。
4.5.2.2 负载均衡

基于 DNS 进行负载均衡 基于 VIP 进行负载均衡(虚拟 VIP 不是绑定在某一个特定的网络接口上的,它是由很多设备共享的

4.5.3 数据中心内部的负载均衡策略

包括将请求路由给某个具体服务器的应用级别策略。

4.5.3.1 健康管理

如果某个后端任务过载了,请求处理开始变慢,负载均衡应该能自动避开这个后端,从而将任务分配给其他的后端。 需要正确识别跛脚鸭状态——后端服务正在监听端口,并且可以服务请求,但是已经明确要求客户端停止发送请求。

4.5.3.2 划分集群

鸡蛋不要放在一个篮子里一直都很好的建议。 在后端任务滚动重启的操作,需要对客户端透明,同时连接的变动最少(一致性 hash 是个好方案。)

4.5.3.3 负载均衡策略

简单轮询算法、最闲轮询策略、加权轮询策略等。

4.5.4 应对过载

避免过载,是负载均衡策略的一个重要目标。构建能良好处理资源限制的客户端和对应的后端任务是最好的:在可能的情况下重定向请求,在必要时返回降级回复,同时在最差的情况下,能够妥善地处理资源受限而导致的错误。

以可用资源来衡量可用容量 给每个用户设置限制:当全局过载情况真的发生时,使服务只针对某些「异常」客户返回错误是非常关键的,这样其他用户则不受影响。 客户端侧节流:当某个客户端检测到最近的请求错误中大部分都是由于「配额不足」错误导致时,该客户端可以开始自行限制请求速度。

Cheng自适应节流,学过自动控制的知道一个负反馈的东西很类似,基于请求拒绝数量来衡量是否过载,客户端调节请求量,好处是减少系统开销 基于重要程度给请求打标签:最重要的、重要、可丢弃的 资源利用率信号:随着资源利用率的上升,可以根据请求的重要性来拒绝一些请求(最重要的请求对应最高的阈值) 处理过载:区分是全局过载还是局部过载,局部过载重试则有一定概率会成功,全局过载重试则会加重过载问题。 连接造成的负载:定期检查连接资源(批量代理任务,随机断连接 Cheng记录重试次数重试直方图p219重试比例高直接返回无需重试

4.5.5 处理连锁故障

如果请求没有成功,以指数型延迟重试 「为什么人们总是忘记增加一点点抖动因素呢?」 —— Ade OshineyeGoogle 开发者布道师

连锁故障是由于正反馈循环导致的不断扩大规模的故障。比如,服务的一个实例由于过载而出现故障,导致其他实例负载升高,从而导致这些实例像多米诺骨牌一样一个一个全部出现故障。

4.5.5.1 防止软件服务器过载

队列管理:队列 + 线程池的方案(队列中排队的个数建议小于线程数) 流量抛弃和优雅降级:学会避免处理那些不值得处理的请求 重试:基于指数型 + 抖动因子 请求延迟和超时时间:任何时候设置超时是个好习惯google GRPC 框架的第一个参数是 context ,应该是因为这个

4.5.5.2 连锁故障的触发条件

进程崩溃、进程更新、新的发布、自然增长、计划中或计划外的不可用

4.5.5.3 解决连锁故障的步骤

增加资源、停止健康检查导致的任务死亡、重启软件服务器、丢弃流量、进入降级模式、消除批处理负载、消除有害的流量。

4.6 软件研发

4.6.1 管理关键状态:利用分布式共识来提高可靠性

分布式共识系统主要解决:在不稳定的通信环境下一组进程之间对某项事情达成一致的问题。

Cheng: CAP, P-partition tolerance分区容忍度简单理解分布式集群主备两个节点AB之间网络出问题也可能脑裂P就损失了 C-consistency一致性AB数据不一致C就损失了 A-availability可用性用户不可用A就损失了

CA without P如果不要求P没有P实际上就是单点应用了。能保证CA还有什么其他要求不是完美了。现实是没有PCA是保证不了的。

CP without AAB失去联系重点是数据一致性可以牺牲可用性来确保数据的一致比如一些跟钱相关的操作必须强一致性。

AP wihtout CAB失去联系可以单边提供服务高可用是第一位需放弃一致性。为了高可用每个节点只能用本地数据提供服务而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。

4.6.1.1 使用共识算法的动力

分布式系统系统协调失败,产生脑裂问题或者需要人工干预灾备切换。

4.6.1.2 分布式共识的系统架构模式

分布式共识算法很底层,很原始,它们仅仅可以让一组节点一次共同接收一个值。

可靠的复制状态机RSM复制状态机是实现在共识算法逻辑层之上的一个系统。 可靠的配置数据存储和配置存储:复制数据存储是复制状态机的一个应用。 使用领头人选举机制实现高可用的处理系统:复制多份系统并使用一个唯一的领头人来进行某种类型的工作是很常见的设计。唯一的领头人是一种保证粗粒度互斥的方法。 分布式协调和锁服务屏障barrier在分布式计算机中是一种原语可以用来阻挡一组进程继续工作直到某种条件被满足。 可靠的分布式队列和消息传递

4.6.1.3 分布式共识系统的性能问题

世界上没有某个性能「最优」的分布式共识和状态机复制算法,因为算法的性能通常取决于系统负载有关的多个因子,以及系统性能的目标和系统的部署情况。

应对大量的读操作:复制数据存储的优势在于数据同时在多个地点可用,如果不是所有的读请求都需要强一致,数据就可以从任意一个副本来读取。 分布式共识系统的性能与网络延迟: 共识系统在局域网中的性能和主从模式类似。 然而,分布式共识系统通常需要副本运行在「较远」距离上,这样可以保障副本处于多个不同的故障域中

4.6.1.4 分布式共识系统的部署

副本的数量 副本的位置 容量规划和负载均衡 大体量公司的烦恼也很多啊,如果只有一个机房的话,这些问题对于你来说根本就不存在……

4.6.2 分布式周期性任务系统

问题Cron 系统不可能知道要执行任务是否具有幂等性?比如垃圾回收操作或者批量发送 E-mil 通知的操作。系统设计的实现需要在跳过这次任务的执行和执行两次之间做取舍。

答案:一般情况下都会选择跳过这次任务的执行。

分布式 Cron 系统的核心是 Paxos 协议,一个在分布式不可靠系统达成一致的算法。

4.6.3 数据处理流水线

周期性的数据流水线是很有价值的,但是如果一个数据处理问题本身是持续性的,或者会自然增长为持续性的,那么就不要采用周期性的设计方式,而是采用一种类似 Workflow 的设计特点的系统。这样一个系统能够周期性地提供用户所依赖的结果,并且是一个非常可靠且稳定的可运维系统。

Workflow 通过将工作进程进一步划分为更小的任务组,而将流水线的「深度」随意增加。每个任务组负责处理该阶段执行的数据,可以对谋一小块数据进行任意操作(比如 Mapping、Shuffing、排序、分割以及合并等操作。

本质理解的不是很好,后面有空需要重新回顾下。

4.6.4 数据完整性:读写一致性

数据完整性:是指数据存储为了提供一个合理的服务质量,在可访问性和准确性方面必须达到的一个度量标准。

保障超高数据完整性的手段是主动探测和快速修复的能力。没有人真的想要备份数据,他们只是想恢复数据。所以交付一个恢复系统,而非备份系统。

4.6.4.1 造成数据丢失的事故类型

根源问题:用户行为、管理员的错误、应用程序的 Bug、基础设施中的问题、硬件故障和部署区的大型事故。

影响范围:全部用户 or 局部用户

发生速度:瞬间 or 缓慢持续进行

4.6.4.2 Google SRE 保障数据完整性的手段

SRE 假设任何一种数据保护机制都可能在最不合适的时间出现问题,同时没有一种银弹可以同时保护所有事故类型,所以需要分级进行。

用户删除:使用软删除策略,用户可以自主还原数据,预防用户错误。 应用程序删除数据:使用被备份策略,可以被用户支持团队或者应用程序管理员恢复,预防应用程序 Bug 和服务管理员错误。 数据被摧毁:使用备份策略,无法还原需要使用备份,备份可以为这个和其他所有场景提供保护。 Google 在 2012 年 3 月 Google Music 被意外删除事件中,使用基于磁带的备份,恢复了用户被误删除的数据。嗯,是真的。 完美的理论不代表实现也是完美的。

Cheng:

  • 备份 vs 存档 存档:审计、取证、合规,恢复时间不是最重要的考量因素 备份:快速恢复,最少丢失
  • 不断演习关键不是备份是恢复。确保N时间恢复 -> 将N不断逼近0

4.7 产品设计

4.7.1 可靠地进行产品的大规模发布

还记得前面说过的发布工程师嘛?嗯,我觉得除了像 Google 这么大体量的公司以外,很多公司应该都没有这个岗位吧…… ps 突然想起了全局架构组,感觉好像有点类似的样子

Cheng

  • 好的发布流程,需要反复实践来提升速度和可靠性。
  • 谁来组织发布研发运维很多公司由SRE或研发人员兼。 google有个LCElaunch coordination engineering发布协调工程师干这个事这个挺清晰
    • 审核gate提供发布可靠性的建议
    • 协调
    • 跟进,发布过程的所有技术问题
    • 反馈
    • 总结最佳实践给SRE和开发提供发布培训 人员由招聘或有经验的SRE组成具备良好的协调、沟通和领导能力。 我们是支撑兼了这个角色,支撑为什么可以牵头组织上线?
    • 审核、协调、跟进、反馈都是可以的,但程度较浅。
    • 支撑是第三方,跳出运维和研发。
    • 流程就是流程,支撑不深入运维和研发细节,有利于客观的执行流程。
    • 支撑是内外桥梁熟悉应用本身和常见故障的处理上线后可以更好的做UAT。
  • LCE经验/跨职能的视角/客观性,流程考虑可靠性,往往和效率矛盾,不断优化发布流程。
4.7.1.1 起草一个发布检查列表

架构与基础设施的依赖 容量规划:容量规划与冗余度和可用性都有直接关系 故障模式:是否是单点,依赖服务不可用如何处理 客户端行为:客户端的滥用行为是否会影响到服务的稳定性 流程与自动化:流程文档应该能够做到使任何一个团队成员都可以在紧急事故中处理问题 开发流程:代码的版本控制 外部依赖:是否依赖三方代码,是否有合作伙伴依赖你的服务,发布时是否周知他们等 发布计划

Cheng: 分析发布的每一步,问可能故障的备用方案。 所有发布是灰度或金丝雀的,每一批量都有自动验证步骤。制定灰度策略:如几台机器 - 某个数据中心 - 全球全部服务器。 A 比如云宽灰度策略:内部体验用户 - <100个用户小批量验证3-7天 - 2000用户3-7天- 8000用户单网元满载7天 - 半个DC - DC

软件上线发布最佳实践。

发布评审

4.7.1.2 可靠发布所需要的方法论

灰度和阶段性发布:任何改动都具有一定的危险性,而任何危险性都应该被最小化,这样才能保障系统的可靠性。 功能开发框架:创建一个可控更新的机制允许我们在真实负载情况下观察系统的整体行为。用工程的力量和时间换取一些可靠性的保障是很划算的。 应对客户端滥用行为:服务器端控制客户端行为的能力是一个很重的功能。 过载行为和压力测试:你的服务在未来的使用中会遭受最坏的处境时,仍能够符合你的预期是很好的。

Cheng:


长期常规工作,认识不够,无法改变或优化 对问题视而不见,拒绝优化

CG:

  • SRE vs. 传统OPS
  • 制定SLO
  • 找到2、3件永久性解决问题的工作
  • 发现问题(面临最后期限压力时的第一个受害者) - 写入错误报告/团队文档
  • 坚持解释你的逻辑推理
  • 良好的文档目的是确保团队在一个新的情况下不会重复旧的错误

======= 规范的作用: 即使大家出发点是好的,人们总会默认或倾向于选择阻力最小的路径,这些最小路径可能没法让人绕开陷阱。 规范的作用恰恰是为绕开这些陷阱设置的指南。 我们学过网络协议应该知道,传输过程中要设置很多冗余位,做什么用,纠错!网络介质常常会有不可靠的时候,用开销来检查或防止错误。 人也一样,常常有不可靠的时候,怎么办,就需要有规范约束,对于成熟的生产过程减少发散性。 本质上,规范是让你走既定的路线,减少思维发散,是不利于创新的,所以不能过度,过度造成组织固化,但必要的制度和规矩对于组织管理还是必须的。

此外,流程尽量能够固化到工具上,而不是通过手工指挥棒,人工的指挥棒执行过程中容易过度和变形。

SRE要求交维过程onboarding标准化

建议一系列SRE支持的平台和服务框架标准化SRE规范重点、完整、标准的解决方案

  • 性能指标的度量和选择
  • 请求日志的记录,标准格式
  • 流量和负载管理控制系统

如上,一个基于框架和强标准构建的生产平台能够降低运维开销:

把on-call工作融入到SRE职责中SRE只有融入日常on-call才会有自动化改进动力体会帮自己干活。 注意on-call时间占比不能太高不能以淹没运维开发工作为代价on-call类似体验生活 < 50% 最可用的工具通常是那些每天使用他们的人写成的。

把chaos融入故障演练中。

服务降级是研发架构的事情,还是运维思考的事情?

建立实时的事故状态文档,事故总控人最重要的职责就是维护事故的实时文档。最好可以多人同时编辑。关注共享范围。

一些总结


概念:

  • 故障预算故障预算的概念是思考问题方式的改变有故障预算表示故障是不可避免的故障是创新过程的一个部分。确保在保证SLO下的最大迭代速度。可靠性指标与投入呈指数分布关系你需要思考的是花费巨大的精力将系统变为 100% 可靠是否能为用户带来实质意义上的好处?
  • MTTRMTTFplaybook

变更管理必须思考的关键问题:

  • 灰度方案?用户影响最小化
  • 问题检测?第一时间捕获失败
  • 回退方案?预设失败怎么办
  • 其次才是其他非功能性特性,安全、容量、效率、利用率、性能。。。

SRE文化特质&理念:

  • 天然排斥重复性、手工操作
  • 崇尚技术能力,快速开发替代手工操作
  • 应急事件处理:自愈是目标,任何需要人工操作的事情都只会延长恢复时间。要牢记:一个可以自动恢复的系统即使有更多的故障发生,也要比事事都需要人工干预的可用性更高。 一个缓慢的不断重启的实例要好过一个不重启一直泄露资源的实例。
  • 以事后总结为荣,无论有没有触发告警
  • 对事不对人
  • 过多告警等于没有告警
  • 无效备用不如没有备用
  • 你看到的跟我看到的世界虽然是同一个,但是感受却截然不同。 作为用户,我看到的只是一个可用的系统,这个系统能够完成我需要的功能。我不需要知道背后的原理。 作为研发,除了功能外,你需要做到能够快速理解底层的实现。能够看到截然不同的世界,我觉得这是很有趣的事情。
  • 开发里的方法论同样适合:不要重复造轮子。在巨人的肩膀上,才有可能看的更高,所以不要重复造轮子,而是学会基于轮子去造车。
  • 希望不是一种策略hope is not a strategy理性思考。故障的容忍度、测试的深度、发布频率、金丝雀持续的时间等这些决定不应该受办公室政治、不理智的恐惧、一厢情愿的希望所驱使。
  • 拥抱风险,拥抱变化
  • 思考从根本上解决问题,「救火很重要,但是疲于一直救火,会阻止你去思考该如何从本质上去解决问题。」 扩容扩容扩容,重启重启重启
  • 如果系统正常运行中需要人工干预应该将此视为一种bug。正常的定义会随系统进步而改变。
  • Cheng如果有大量的监控结果需要主管判断分析和复杂响应设计不佳应重构好的告警应该能够直击问题从而快速响应。
  • Cheng: 切记故障处理原则,先抢通,再修复
  • 你的公司是否拥有无指责的文化,专注于真正的根源并解决系统性的问题,或者你们的公司文化是“责备和羞耻”的文化,出错时人们会因此受到惩罚?
  • 持续改进。
  • 可靠性是最基本的功能。
  • 痛苦的事情频繁做,故障演练不是走过场。

孙子兵法有云:为将者,未虑胜,先虑败

注意:任何运维故障,运维的领导必须是第一个知道的人,如果他从别的人或者部门中知道这个故障,那么就很被动,而且是故障处理人失职表现。

事后总结

先形成事后总结的习惯,进一步得到要求是在事后总结总获得进步,而非例行公事

条件
  • 二级及以上故障
  • 数据丢失
  • on-call需要人工介入的回滚、流量切换等
  • 解决耗时过长的
  • 监控问题(人工发现,而非告警发现)
内容:
  • 基本信息:发生时间,跟踪人等
  • 事故影响
  • 根因分析
  • 触发条件
  • 解决方案
  • 待办事项
  • 经验教训
    • 做的好的
    • 需要改进的
  • 时间线
    • 标注出发现时间

SRE职责

  • 可用性改进
  • 延迟优化
  • 性能优化
  • 效率优化
  • 变更管理
  • 监控
  • 容量规划和管理
  • 紧急事务

on-call:

  • on-call度量
    • 每个工程师呼叫响应数量
    • 每个工程师被呼叫时间间隔
    • 非工作时间接收量
      • 团队每周>1负载过高
  • 应该解决的问题
    • on-call团队成员如何轮转
    • 每次轮转持续多久?
    • 某个工程师没响应会发生什么?
    • 某个工程师无法胜任怎么办?
    • 同时有几个工程师处于on-call状态
    • 多名on-call工程师如何分工
    • 如何处理不可预见的事故?
  • 目标:
    • 一个成功的事故响应系统的目标很简单 - 先于客户影响前发现事故,最理想的情况是发现并修复它。
    • so,必须有监控和告警
  • 故障:该策略强迫我们停止对该服务的任何新工作,直到我们修复导致该事故发生的根本原因或提出相应的减缓措施。 - 拉灯
  • on-call手册

支撑组织:

  • 建立一线、二线甚至三线支撑团队一线一般为7x24小时值班的人员
  • 二线一般是资深工程师,或者是对应的应用开发/测试同学;
  • 三线一般是主管或者是外部的厂家如涉及硬件、IDC机房等相关服务方。

SRE不再谈论公司中有多少独立项目而是在谈论如何让所有人参与。 通过使用整个公司相同的工具和技术来完成,作为回报,这有助于在每个人之间共享所有权。

团队提升 培训无意义,自觉成长

reference