系统管理员的角色正在从被动的接受工作任务转变为维护那些系统平稳运行的机器人,让它们各司其职;团队构建和运行分布式系统要拥抱失效的组件,且保持密切的合作以确保长远的成功。这就是由 Thomas Limoncelli, Strata Chalup, and Christina Hogan合写的新书 《云系统管理实践:大型分布式系统的设计和运维》 的两个主要观点。尽管书的作者们定为的目标读者是系统管理员,但是内容的全面性和实战性也适合相关的任何聚焦技术的团队阅读。
书的第一部分有六章,交代了分布式系统的设计考虑。第一章通过描述分布式系统设计的核心考虑为后续奠定了基础,这些考虑囊括了通过小型的系统构建成大型系统的原理、分布式状态的交互、CAP理论的阐释、松耦合方面的思考、以及对于影响响应时间的选择的密切关注。第二章以作者在管理分布式系统时对作者有着深刻影响的实例作为开端。在本章,作者叙述了在设计分布式系统时如何考虑运维方面的内容。不能将运维视为事后处理这样的角色,而是开发者在设计系统时就应该考虑到如何管理配置、简单的启动/关闭程序、清晰的升级流程、每个服务都应支持横向的扩展、严格的操作要求等等。
你该如何选择合适的基础设施托管平台?第三章解释了在云交付模式之间选择的决策标准。作者带领大家什么时候该将系统运行在虚拟机之上,还是物理主机之上,还是容器之上。第四章则聚焦于应用程序的架构。此章回顾了多层的架构策略,然后对负载均衡技术及其算法作了深层次的交代。第四章的后半部分则是深挖消息总线的技术,及其在分布式系统所扮演的角色。可扩展性对于一个分布式系统来说是一个非常重要的概念。第五章全是为设计团队就可扩展性的提出的出色的意见。作者在这里首先提到了通过确定的策略确定瓶颈所在,然后是横、纵向扩展的解决方案。然后他们转到了对于缓存、数据分片、队列以及内容分发网络的评估。第六章包含了本书中的“设计”一节,对弹性进行了热烈的讨论。作者认为因为成本与灵活性的原因,软件的弹性归根结底还得是硬件的弹性。然后他们继续解释了如何处理闲置资源、失效域、负载均衡及自动化从而能够帮助系统能够在各种各样的攻击和人为的错误下保持运行。
书的第二部分则侧重于分布式系统的运维。第七章介绍了站点靠谱工程师(SRE)以及他们在态度、职责范围与传统企业IT团队是如何的不同。本章的剩余部分对分布式系统的运维主题进行了广泛的讨论,包括有自动化的方法、服务的生命周期、以及如何组织运维团队。第八章的主题是DevOps,作者站在一个过来人的角度,阐释了改进运维的“DevOps三部曲”、DevOps的核心价值、将DevOps文化融入到坚持持续交付中。第九章和第十章则将目光转向到了服务交付阶段以及团队如何构建一条高效的流水线工作流程。第十一章对如何在生产环境中更新正在运行的服务做了深入的探讨,作者在此解释了滚动更新、canary部署、按阶段推出、proportional shedding、以及蓝/绿部署等之间的区别。自动化是管理大规模系统的关键,在第十二章以实际出发来看自动化与人为因素所起的作用。此章解释了自动化的目标、什么是自动化、以及在系统的各个方面如何的去自动化等。第十三章则是将目光转移到了设计文档,以及如何创建有用的描述复杂系统的手册。
第十四章描述了oncall资源的价值以及如何建立响应迅速和高效率的组织结构。我们知道灾难随时可能会发生,第十五章诠释了对灾难准备计划如何规划、实现、以及常规测试。第十六章和第十七章探究了在分布式系统中使用监控,以及提供了什么样的系统数据应被监控和存储的可行建议。你该如何确定你需要多少资源,什么时候需要?第十八章就包含了容量规划的良好建议,以及在启动一个新的服务时应该考虑何种因素。作者宣称“测量影响行动”,在第十九章就阐释了如何设置目标以及创建有用的关键性能指标(KPI)。最后一章先是描述了运维服务的整体质量,然后描述了卓越的运维是何样子,那么你该如何实现它了呢?作者针对自我评估和注重结果给出了一些提示型的建议。
本书通俗易懂,而且延伸了关于分布式计算相关的信息。读者不仅能够找到现实中的例子,还能够获得实用的建议,而且一系列的主题也带来了深刻的印象。不论你是CIO、架构师、开发者还是系统管理员,你都能够学到交付大规模系统方面的知识以及参考的意义。
InfoQ采访了作者们,希望能够获知关于本书更多的思路。
作者团队:现代的开发者和架构师需要懂运维。这和一次性的将代码烧录到光盘的shrink-wrapped软件年代有着很大的不同了,哪个时候运维是他人的问题。书分为两个部分:第一部分阐述了对于运维很重要的所关心的系统架构和设计的一些元素。第二部分则是概述了针对大型系统的一些运维实践,比如服务交付、监控和oncall。开发者和架构师在这两部分中均可找到自己需要的内容,因为书的内容所阐述的真实的运维场景是他们原来难以想到的。
作者团队:是管理。你无法去“采用DevOps”,因为它不仅仅是一个事情。它是一个实践的工具箱,这些实践具有共同点就是:通过打破阻碍沟通与合作之间的孤岛来实现业务的改进。当底层的员工发起采用DevOps运动时,管理层就成了拦路虎。DevOps非常惧怕那些将信息隐藏、将团队对立起来、头衔就是一切“都对”的行政力量。而这些现象要比你想象的严重的多。
每个人都声称自己不是沟通的障碍,直到他们被要求成为清晰透明的主(举个例子,如 此种情形 )。
这并是说推动DevOps和基层员工的作用关系不大,也很重要。我听说一个管理层一厢情愿的、遭遇阻击、困难重重的糟糕的故事。我曾经和一个人讲过,这就好比于父母在教孩子训话,永远是单向的。 这可不是一个好的场面 。
我们建议采用DevOps的实践要一次解决一个问题慢慢来完成,尤其是解决那些导致多个团队成员直接的、明显的问题。举个Tom 在Google工作时的例子,他常参加一些彼此合作的团队的会议,在会议上团队之间并不会对彼此之间的议程进行沟通,而是简单的讨论下所谓的自己的“痛点”。DevOps的引入立即得到团队之间的共鸣,且开始合作无论是大小团队都开始减轻对方的痛苦。所解决的这些问题有时候是简单的如一个团队为另一个团队提供的字母排序,而不是时间排序;有时候是较大的问题,如抛出的API作为服务来为另外一个团队自动化流程的输入;有时是直接删除那些已经没有人在使用的却仍然在维护的整个子系统。
没有人会拒绝目标是消除他们共同的痛点的会议。一旦人们开始讨论起来,那么就能获得更多的施展机会。最终,越来越多的DevOps实践就是自然而然的事情了。
作者团队:我们增加了网络和存储深入到其内部的知识。网络的涉及面很广,从一个包如何路由,到TCP是如何工作的,再到诸如HTTP等高层的协议等等。我自己曾经又过调试网络的问题经历,它需要我知道Linux是如何路由网络包的(它是反人们日常所认为的)、TCP窗口大小是如何工作的、以及SSL证书是如何工作的(何时不能正常工作)等。
和运维工作密切相关的性能优化,是需要能够理解系统中所有的组件是如何工作的。这也意味着设计一个可靠的系统时,我们必须了解所有这些因素可能会失效。有些内容是无法在手册中找到的。我们必须去理解其内部的工作原理方可理解所有可能的影响。
数据存储亦类似。磁盘存储不再仅仅是磁盘那么简单的了。数据存储拥有RAID系统、控制器、连接器、卷管理器、以及文件系统;技术的范围从真实的磁盘驱动器,到SSD模拟磁盘,再到裸的SSD,再到SAN、NAS、DAS等等。内存也不再是RAM了,它还有L1/L2缓存和虚拟内存系统。( 可参考此文 )
我讲个我近来遇到的故事,我的开发者同事不能够理解为什么在10G以太网链接中复制数据不够快这么一个问题。瓶颈并不在于网络这块,事实上是因为数据的读取来源是一个非常慢速度磁盘。当源数据移动到SSD系统时的瓶颈在于内存总线。目的就成为了和SSD最大写入速度有关的瓶颈。开发者们必须意识到这些问题,这就要求必须与拥有深厚知识的系统管理员搭档,提出的解决方案方能满足所有的设计需求。
作者团队:我希望容器的标准化部署流程能够像海运集装箱那样的物流标准一样。容器应成为交付应用的标准格式,无论你是在桌面系统部署服务、还是在一个小型集群中、又或者是上千的大型分布式系统。
所有新的技术都需经历一定的阶段。在第一阶段,倡导者会宣称它能适应所有的情况并会解决所有的问题。在第二阶段,方才落到实处,这往往是经历了痛苦的过程,产业的发展是通过对于技术解决问题的用例中有些是非常有意义的,而也有一些是毫无益处的。
容器仍处于第一阶段。随着时间人们会理解容器对于某些特定的情况是大有好处的。我发现对于解决某些问题就非常的有用,比如我们会在开发环境或测试环境有一个安装软件的流程,在生产环境中还有一个流程。而这两个流程,前者永远比后者要领先。一个人拥有一块表来看时间,一个人戴两块表该怎么决定?容器让统一这些重复的部署流程成为可能,避免了重复的工作,也无须再去重复制造轮子,还能够做到限制版本skew。
业界也对容器不能适应于那些应用达成了共识。举例来说,其中一个共识,那就是容器没法做到进程之间的安全隔离(至少目前的技术无法实现)。随着时间的推移,此例以及其它用例都会被证明有效还是无效。
作者团队:将monolithic系统转换为各自独立的组件(“面向服务架构”即SOA)还需要走很长的一段路。最好的开启之路是采用“速赢”策略。它会融入到你正在构建的SAO架构,也会带来更多的成长的痛苦以及更多的运维任务。通过最小化的开始来学习他们。
经常有一些子服务是可以较明显的首先梳理出来。运气好的话,它们还拥有非常好的边界和隔离等离散的特性。
另外一个策略是为它们自身的服务增加缓存层。例如, Memcached 和 Redis 就是两个高性能的缓存解决方案。它们作为自身的服务来运行。可以通过修改monolithic系统来通过这些缓存来直接查询。这有助于系统的扩展。
Tom曾在Stack Exchage公司( StackOverflow 的母公司)工作过。这家公司曾经就使用了一个相当monolithic的系统。他们后来将Redis是作为他们的缓存层,使用HAproxy来作负载均衡。通过分离出这些功能,对于整个系统的可扩展和弹性有了很大的改进。
通常monolithic系统只能通过整块的方式来进行扩展:要扩展服务给更多的用户,必须复制整个系统。作为子系统能够独立为单个的服务的话,每个都可以进行单独的扩展。这对那些其它服务使用的不多的、无须扩展的子系统更加的有效。举例来说,假如一个系统集成了一个不是很频繁使用的聊天系统,那么就毋须扩展此聊天子系统。换句话说,如果此聊天系统的用户增长了,就可以单独扩展聊天系统即可,而毋须去动其它的系统的资源。
作者团队:它是一个常识,但是很多企业都因为是处于“救火”模式下而走向相反的停滞道路。
手动的去做一些事情是线性回报的。需要做的事越多,就得雇佣更多的人来做。相反,如果分配给人们的任务是聚焦于改进过程(通过自动化、重组或其它方式),每一次的所发生的过程都是有利于公司的。这是一个超线性(指数级)的回报。
像诸如Google这样的公司是不会去自动化任务的,因为它们做更加有意思事情或者说已经超越了这个。在他们那样规模下没有执着于自动化任务被认为是几乎不可能的。他们不仅自动化,他们还创建了自助服务系统,所以即使不是系统管理员也可自己完成自己要的东西。一位工程师可以以完全自助的方式来启动一组web所需的资源,而毋须去麻烦前端团队、网络团队、或是其它的支撑团队。这些团队花费精力在自助服务上要比花在任务本身上更有价值。
另一方面,你得注意公司的备忘录。近来我们的一个朋友从一家公司离职了,因为他所在的公司禁止将他们安装和配置的Linux服务器操作系统的流程自动化。当初他应聘时被管理层告知公司有问题需要解决(需要配置大量的主机),然后雇佣他来每天点击、点击、点击、点击、点击、点击来配置它们。如果他休假了,没有新的机器被安装,也没什么。自动化会产生自助服务的流程而且他会被分配到其它的项目中(所有这一切似乎是新员工将无事可做)。
事实的真相是这些公司仍然能够生存,这证明了这世界毫无天理。
作者团队:如果你一年更新一次你的系统,你就拥有12个月的时间在部署之前做调整。如果有一个bug存在的话,你会很难发现是那些变更引起的bug。调试时间花费太久,因为开发者无法在几个月内看到代码中bug。同时部署更新也可能失败,12个月的环境变化足以挫败你的项目,这就像鳄鱼躲在沼泽中一样危险。
从财务的角度讲,就是你已经投入了资本(开发时间),在12个月看不到任何的回报可能。就好比你将钱放入股市,一旦交易完成,就禁止你访问一年内的利润,你会怎么想?我傻吗我。
如果你采用了持续部署,那结果就是,每周或每日进行升级。你将从“小步快进”效应中获益。每次发布只有很少的变更,那么一旦发现bug就会很快的将之隔离到坏的代码中。调试也将更有效率,因为开发者更加的熟悉代码(而不是让他们半年后再看自己的代码--译者注)。如果是在生产环境中部署变更的话,马上能够看到结果要好过于几个月后给来个“惊喜”。更加频繁的发布也会让完全自动化的测试更加的经济有效,这会导致更多、更好的测试。
然后持续部署并不能等同于追求速度。更为关键的是要有信心拥抱变化。额外的测试和小批量的改进更能对成功的发布下一个版本有信心,使其的变更更加的容易。当可轻松的做变更时,创新也就随之而来。
如果你所在的公司僵化、创新无从提起的话,那么你就该反思自己了,“生产和部署一代新的软件版本有多难?”,如果时端到端端流程包括了很多的陷阱,因为缺乏测试、潜在的升级失败偏见等,那么是你的发布解决方案步骤太多,而不是太少。
这里举个案例,SAP使用DevOps原则将他们的部署从可怕的每年升级转到了合理的每个季度升级。如果人们能够和SAP一样,就再也没有借口了。
作者团队:一般情况下,人们的自动化所使用的一些事情称之为“剩余原则”:我们自动化所有我们能够自动化的一切。那么剩下的由人来掌控的是什么:情况太罕见或过于复杂的自动化。此观点对于人的才能和适应性以及没有局限性做了不切实际的假设,最终导致的结果就是太多的运维自动化是盲目的,根本不清楚背后的机理是什么,以至于无法有效的去调试系统。
另外一种模式是补偿性原则,此原则提出一组所使用的属性来决定是否采用自动化。使用补偿性原则,当从上千台主机每隔5分钟去收集监控数据时,我们知道这事情显然让机器去做比人更加的靠谱。这就像我们去决定在高度核污染的地方人是不合适的一样简单,但是机器人就可以做到。
然而最新的思想围绕着一个完全不同的模型。即互补原则,它是从人的角度来看自动化的,它旨在帮助人们从长远的角度去有效的执行自动化,而不是仅仅着眼于那些短期的影响,它会更加关注人们的行为将改变结果,是自动化还是不要自动化。
在此方法中,其中一个就认为是人们应用通过手动的任务去长时间的学习,然后去改变自动化。另外也许是在自动化中针对同一个任务同时允许手动执行和自动化。这可以允许一些功能按照需要重新分发。人被认为是在系统中积极参与的一部分,而且人的自适应性、作为基本的资源充足的学习伙伴是整个系统中必不可少的功能。
遗憾的是,对于使用互补原则的自动化,也不是解决问题的终极办法,或者说没有“一招打遍天下”的功效。但是如果你记得考虑人的因素以及在有人运行的系统中对自动化作长期的努力,那么你就有更好的机会去设计出优秀的自动化来。
这里举一个使用了剩余原则的高度自动化的例子,其当发生问题时需要超高水平的技术手段,让人望而却步。IBM的UNIX版本,称之为AIX,系统的配置是在一个数据库中,结果就是一切都可以自动化,简单到几乎所有的运维工作就是操作数据库,实际的更新则是稍后进行,方可看到想要的功能变化。然而问题来了,如果数据库和实际的配置不能同步的话,你无法编辑任何Unix一般的文件,比如常见的/etc或其它地方,编辑也是无效的,因为它们影响不到数据库中的内容。虽然这让自动化更加的容易了,但是带来了系统的复杂性,而且一旦出错就的超级专家才能修复。如果它不出错的话,这绝对是一个优秀的系统。
作为对比,我们再来看下另外一个系统,如Puppet,它可以做到在一个地方编辑配置文件来管理整个系统。运维人员读取真实的Unix配置文件而且可以直接更新它们。是的,它必须能够解析无数的Unix配置文件的格式,但是它做到了这些,就非常得受运维人员的青睐。它非常的接近于互补原则所提出的理想情景。
另外一个互补原则的实例是在 Ganeti 开源项目中所用到的管理框架。那时候Tom还在Google工作,Tom和其他人合作开发了一个工具用来管理大规模的ganeti服务器,这个工具叫做Euripides。该工具就像是运维人员制造的另外一条功能强大的胳膊,而且可以独立完成绝大多数的任务。它甚至知道在某些情况下停下来寻求人的帮助。该工具做了运维人员需要手动执行的任务的80%。取代了原来每天3-4次的任务,现在是每周执行一到两次,甚至更少。虽然,这是因为技术人员合作开发的结果,他们没有浪费自己的技术水平,相反,它让一个小团队像一支小型的军队一样完成了大量的工作。
关于本书更多内容,请访问 the-cloud-book.com 。
Thomas A. Limoncelli 是国际上知名的作家,演讲者,具有在诸如Google、BellLabs以及StackExchange.com等知名公司做系统管理员超过20年的经验。
Strata R. Chalup 在IT战略、最佳实践、可扩展基础设施有超过25年的经验,而且所工作过的企业有苹果、Sun、Cisco、McAfee、Plam等。
Christina J. Hogan 拥有20多年的系统管理和网络管理的经验,在硅谷、意大利、瑞士等多个地方工作过。她拥有计算机科学的硕士学位,航空工程博士学位,且曾经是F1方程式赛车团队的一员。
查看英文原文: Book Review and Interview:The Practice of Cloud System Administration
感谢张龙对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群 )。