admin 发表于 2020-11-22 16:43:07

读书有感,SRE书籍摘录 2

跟踪故障

[*]提高可靠性的唯一可靠的方法论是建立一个极限,同时不断跟踪改变。

 测试可靠性

[*]如果你还没有亲自试过某件东西,那么就假设它是坏的。
[*]SRE的一项关键指责就是要定量地分析我们维护的某项服务的质量。对服务质量的自信可以用过去的系统可靠度和未来的系统可靠度来衡量。前者可以通过抓取和分析历史性监控信息来活得,后者可以用给予历史数据的预测来量化。
[*]如果我们在短时间内做了大量改动,等待监控数据再积累一段时间。累计的监控数据和测试的覆盖数据可以用来证明新的代码执行路径的可靠程度。
[*]测试和平均修复时间的关系

系统通过某项测试或者一系列测试并不一定能证明系统的稳定的,但是失败的测试通常证明了系统不可靠。一个监控系统也可以发现系统中的bug,但是仅限于汇报机制的速度(例如报警规则的间隔等)。平均修复时间(MTTR)是衡量运维团队通过回滚或者其他动作修复某个Bug的时间。一个测试系统可以检测出一个MTTR为0的Bug。这种情况出现在当一个系统级别的测试应用在某个子系统上,并且测试检测到了监控系统也会检测到的一个Bug。那么这项测试可以被用来阻挡这个Bug的发布,使得这个Bug根本不会进入生产环境(虽然这个Bug可能还是需要从源代码级别修复)。通过组织发布的方法修复MTTR为0的Bug是很高效的。你发现的0 MTTR Bug越多,你服务的平均失败时间(MTBF)就越长。随着测试的优化,MTBF会上升,开发者可以更快地上线新功能。有些新功能也会包含Bug。新的Bug的发现和解决会同时导致变更发布速率的下降。
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7


[*]测试的步骤
   
[*]单元测试。一个类或者一个函数的正确性。
[*]集成测试。组件的功能的正确性。
[*]系统测试。大型测试。
   
[*]冒烟测试。检测非常简单但是非常重要的系统行为。
[*]性能测试。冒烟测试完成后,开始性能测试。通过某个系统测试的变形来保证整个系统的性能自始至终保持在可接受范围内。因为系统的影响时间和资源要求肯呢过在开发过程中大量改变,该系统必须接受某些测试以确保它不会再没人知道的情况下逐渐变慢。
[*]回归测试。历史上的Bug,在准备上线的系统上进行测试,确保Bug不会复现。

[*]生产测试。生产测试和一个已经部署在生产环境中的业务系统直接交互,而不是运行在密闭的测试环境中。这些测试和黑盒监控在很多地方十分类似,有的时候也被称为黑盒测试。生产测试对运行一个可靠的生产环境来说是必要的。

[*]变更发布与测试

人么你经常宣称测试时在(或者应该在)密闭的测试环境下进行的,这句话暗示了生产环境是非密闭的。当然生产环境通常不是密闭的,因为有节奏的变更发布过程在进行小范围的,已知的生产系统改变。为了更好地控制不可预知性,同时避免最终用户收到影响,变更可能没有按照它们被加入源代码版本控制系统的顺序发布。发布过程经常按阶段进行,使用某种机制逐渐将用户切换到新系统上。同时,监控每个新阶段以保证新环境没有遇到任何未知的问题。所以,整个生产环境通常并不能用任何一个源代码版本控制系统的版本来代表。有可能在源代码版本控制系统中间时存在多个版本的二进制文件,以及它对应的待发布配置文件。这个场景下针对生产环境测试有可能会导致问题。例如,这项测试可能在使用代码仓库中的最新版本的某个配置文件与生产系统中的老版本的二进制文件。或者测试可能使用的是旧版文件。结果发现了一个已经被新版本修复的Bug。同样的,系统测试也可以使用配置文件在测试前组装模块。如果测试通过,但是该测试配置测试却没有通过,那么这项测试只通过了密闭环境下的测试,却没有在生产环境下通过。这样的结果是很不好的。
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7


[*]配置测试。在Google,WEB服务的配置信息保存在低吗仓库中的文件中。针对每个配置文件,有一个单独的配置测试检查生产环境,以确保该服务的配置和配置文件一样,同时汇报任何不一致的情况。这个测试自然不是密闭性的,因为它们需要在测试系统的沙盒之外进行。
[*]金丝雀测试。煤矿中的金丝雀。要进行一次该测试,一小部分服务器被升级到一个新版本或者新配置,随后保持一定的孵化器。如果没有任何未预料的问题发生,发布流程会继续,其他的软件服务器也会逐渐升级到新版本。如果发生了问题,这个单独修改过的软件服务器可以很快被还原到已知的正常状态下。我们经常用“烘烤这个二进制文件(Baking the binary)”来指代这个过程。这种测试并不是一个测试,而是一种结构化的最终用户验收测试。一般采用指数型整张部署,一开始一台,然后两台,然后四台,然后八台…大部分的Bug都是U=1级别的。
[*]创造一个构建和测试环境。如果所有的任务都是高优先级的,那么它们就也全是低优先级的。
[*]大规模测试。
[*]针对危险性高的软件设计防护边界

绕过常见的,大量测试过的API而进行某种操作(哪怕是给予良好理由的前提下)的软件可能会再生产系统上造成严重后果。举例来说,某数据库引擎为了便于管理者缩短维护窗口期,而提供了一种暂时关闭事物的工呢过。这个引擎可能被用来进行批量操作,但是这个引擎如果一旦意外地在用户可见的实力上运行,可能会造成用户可见的数据问题。应该利用设计方式避免这种大问题:1. 使用一个独立的工具在复制配置文件中设立一道防护边界,确保该副本无法通过健康检查。于是这个副本永远不会被负载均衡选择直接面向用户。2. 修改危险的工具类代码,使得它们上线之后就检查防护边界。只允许这些工具类代码访问处于不健康状态下的副本。3. 使用与黑盒监控一样的副本健康检查机制。
[*]1
[*]2
[*]3
[*]4
[*]5


[*]针对灾难性的测试
[*]对速度的渴求。
[*]测试截止时间

大部分测试都是很简单的,意味着它们是用一个密闭型,自包含的测试文件在某个计算容器中运行几秒完成的。这些测试可以再工程师切换工作环境之前提供及时的反馈信息。需要同时协调很多服务器与容器的测试通常仅仅启动就要数秒,这样的测试无法提供及时的反馈,它们只能被称为批量测试。这些测试不能告诉工程师“先不要关掉这个代码编辑器Tab”,而只能告诉代码评审这“这段代码还没有通过测试”。一个测试的非官方运行截止时间就是当工程师转而处理下一个事情的时候。测试结果只有在工程师走神之前才有用,否则工程师下次走神可能就像XKCD说的那样了。
[*]1
[*]2
[*]3
[*]4
[*]5

20161015153257338 303/

[*]发布到生产环境。 生产环境的配置信息通常来说保存在版本控制系统中,配置文件通常和源代码文件分别存放。配置文件放在不同的分支,或者不同的目录。
[*]允许测试失败。

 SRE部门中的软件工程实践

[*]当你让某人说出一个Google的软件工程实践成就时,它们很可能说起的是一个类似Gmail或者Google地图这样面向消费者的产品。有的人可能能够说出像Bigtable或者Colossus这样的基础设施项目,但是Google其实有更多的不为人知的幕后软件工程实践,这些软件工程实践很多事来源于SRE部门。
[*]为什么软件工程项目对SRE很重要。Google生产环境复杂,很少有第三方工具是按照这种复杂情况设计的,所以SRE会进行自行开发。SRE是自己工具的直接使用者,所以SRE能够深刻理解要开发工具的重点在哪里。
[*]Auxon。Google开发的容量规划工具。传统的容量规划方法

1. 收集对未来项目需求的预测。需要多少资源?这些资源什么时候需要,以及它们需要在社会么物理位置? 使用我们今天拥有的最佳数据来计划明天;预测长度一般是几个季度到几年。2. 制定资源的采购,构建和分配计划。给予上述预测,我们如何能最好地足未来的资源需求?需要在哪里构建多少资源?3. 评审,并且批准这个计划。这个计划是不是合理的?这项计划是否和预算相符,是否符合产品的期望与技术的要求?4. 部署和配置对应的资源。一单资源最终到位(有可能是在一段时间内),哪些服务最终会使用该资源?如何能够将底层的CPU,磁盘等资源配置给服务使用?这里要着重强调的是,容量规划是一个永远没有尽头的循环:我们的假设时刻砸变化,资源部署可能会延期,预算可能会改变,我们制定的计划也会一再变化。而该计划的每次变化,都必须向下传递到未来的计划中。举例来说,本季度遇到的一个资源短缺问题,必须要在未来的某个嫉妒中得到补偿。传统的容量规划使用“需求”作为一个关键驱动值,在每次“需求”有变动时,手工调整攻击,以满足“需求”。
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6


[*]不可靠性。传统规划中容易产生一个非常不可靠的资源配给计划。该服务可能出现了效率下降的问题,从而需要更多的资源以满足同样的业务需求。该服务变得更受欢迎。,用户需求增加,导致资源的需求也随之增加。某个新计算集群的上线日期推迟。与性能有关的某个产品设计决策变化导致服务的部署规模改变,从而导致资源需求改变(例如,产品决定每个视频需要存两份,而不是一份,将会导致资源用量大幅变化)。小的改动造成计划稍微调整还有效,大的改动只能是资源评估计划推倒重来。
[*]耗时巨大,同时不够精确。
[*]解决方案:基于意图的容量规划。Google内部的大部分团队都已经切换到了这套我们成为基于意图的容量规划流程。将服务的依赖和资源的参数(也就是意图)用变成的方式记录下来,同时利用一个算法自动产生资源的配给方案,包括在哪个集群中将多杀哦资源配置给哪个服务这些细节。
[*]给予意图的容量规划。

意图是服务负责人如何运维服务的一个理性表达。从具体的容量需求到背后理性原因的表达通常需要跳过几个抽象级别。举例如下:1. 我需要50个CPU的资源,必须在集群X Y Z中,为服务Foo使用。这是一个具体的资源请求,但是,为什么我们需要这么多资源,同时一定要在这三个集群中?2. 我需要50个CPU的资源,在地理区域YYYY中的任意三个集群中,为服务Foo使用。这项请求增加了更多的选择自由度,也更容易被满足,但是仍然没有解释这项请求背后的原因,为什么我们需要这么多资源,以及为什么需要三个集群?3. 我想要满足Foo在每个地理区域的需求增长,同时保障N+2冗余度。现在有了更多的选择自由度,同时我们可以更好地理解如果Foo没有获得相应的资源,究竟会造成什么后果。4. 我们想要将Foo以99.999%的可靠度运行。这是相对更抽象的一个需求,当容量得不到满足时的后果也更清楚了:可靠性会下降,而且我们从中获得了更多的选择自由度:也许以+2运行并不是足够的,或者并不是最优化的情况,其他的某种部署计划是更合适的。总结:理想情况下,所有上述级别都应该包括,服务提供的“意图”越多,它们得到的好处也就越大。
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6


[*]表达产品意图的先导条件
   
[*]依赖关系
[*]性能指标
[*]优先级

[*]需求和实现: 成功和不足
   
[*]近似。不要过于关注完美和解决方案的纯粹性,尤其是当待解决问题的边界不够清晰时,我们已经能更改更快地发布和迭代。
[*]提升了解程度,推进采用率
[*]设立期望值
[*]识别合适的用户
[*]客户支持
[*]在合适的层次上进行设计
[*]团队内部组成

[*]在SRE团队中培养软件工程风气

 19 前端服务器的负载均衡

[*]运维大型系统时,将所有鸡蛋放在一个篮子里是引来灾难的最好办法。
[*]如果有一台超大型计算机和用不完的带宽,是不是可以满足google的需求了呢?并不是。就算拥有这样的一套配置,它仍然会收到一些物理条件的限制。例如,光速是通过光纤通信的制约性因素,这限制了远距离传输数据的速度。就算在一个理想的情况下,采用这样一种受单点故障影响的基础设施也是一个糟糕的注意。
[*]使用DNS进行负载均衡
[*]负载均衡: 虚拟IP

 20 数据中心内部的负载均衡系统

[*]一个可靠的识别异常任务的方法:跛脚鸭状态。

从一个客户端的视角看,某个后端任务可能处于下列人一种状态中:1. 健康。后端任务初始化成功,正咋处理请求。2. 拒绝连接。后端任务处于无响应状态。这可能是因为任务正在启动或者停止,或者是因为后端正处于一种异常状态(虽然很少有后端任务在费轻质状态下听通知监听端口)3. 跛脚鸭状态。后端任务正在监听短偶,并且可以服务请求,但是已经明确要求客户端请知发送请求。跛脚鸭状态,能够无影响地停止一个活跃的后打进任务可以让处理代码推迟,设备维护活动,和机器故障问题导致的任务重启变得对用户透明。具体过程如下:1. 任务编排系统发送一个SIGTERM信号给该任务。2. 后端任务进入跛脚鸭状态,同时请求它的所有客户端发送请求给其他后端任务。这通过SIGTERM信号处理程序中调用RPC实现中的API完成。3. 任何在后端进入跛脚鸭状态时正在进行的请求(或者正在进入状态之后,但是其他客户端收到通知之前)仍会继续进行。4. 随着请求恢复被发送回客户端,该后端任务的活跃请求逐渐降低为0。5. 在配置的时间过后,该后端城市需要自己干净地退出,要么任务编排系统主动杀掉它。改时间应该被设置为一个足够大的值,以便一般的请求可以有足够的时间完成。每个服务的该数值都不同,一般来说取决于客户端的复杂程度,10s到150s是一个不错的选择。
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10

 21 应对过载

[*]避免过载,是负载均衡策略的一个重要目标。
[*]QPS陷阱。由于Google是搜索后端,所以安装QPS进行容量规划是不科学的,但是对于一般静态资源的规划还是可以的。在有垃圾回收GC机制的变成环境里,内存的压力通常自然而然地变成CPU的压力(在内存首先的情况下,GC会增加)。在其他变成环境里,其他资源一般可以通过某种比例进行配置,以便使这些资源的短缺情况非常罕见。
[*]给每个用户设置限制
[*]资源利用率信号。一般按照CPU的消耗程度/总的CPU,同时也会考虑内存的使用率。随着资源率的上升,我们开始根据请求的重要性来拒绝一些请求。
[*]过载的分类
   
[*]无过载: 1000个请求,重试1次=0,重试2次=0(所有请求都接受)
[*]轻微过载:1000个请求,重试1次=1,重试2次=0(1%的后端任务正在拒绝10%的流量)
[*]中等过载:1000个请求,重试1次=25次,重试2次=1(5%的侯丹任务正在拒绝50%的流量)
[*]重度过载:1000个请求,重试1次=180,重试2次=32(20%的任务正咋拒绝90%的流量)

页: [1]
查看完整版本: 读书有感,SRE书籍摘录 2