这次我想跟大家分享一下谷歌使用容器集群技术的案例实践,由于我个人在集群管理团队从事了3年的研发,这里带来的是我个人的经验和观点。
首先大家应该都听说过容器是什么,而Docker则是基于容器技术的现阶段最流行的一种容器产品、工具和生态。对于不了解Docker或者容器的人,一个简单的比喻(但不是最贴切)就是容器就是一个更轻量级的“虚拟化”和“应用隔离”工具。具体有多轻量呢?一个服务器可能可以运行10个虚拟机,但是一个服务器上可以运行上百个容器,不同容器里运行用户的应用,并在一定程度上实现了相互之间的隔离。此外,容器可以在秒级启动,相比于启动一个完整的虚拟机也有巨大的优势。除了效能上的提升,容器还是一种应用的打包格式,可以将应用和它运行时的依赖封装在一起,实现一次封装、处处运行的功能。
谷歌从2000年初开始使用容器,但是它所使用的是自研的一种叫做lmctfy的容器格式,其实是Let Me Contain That For You几个单词首字母的缩写。谷歌最早使用容器的初衷之一是节省物理资源,通过用容器取代虚拟化层(hypervisor和每个虚拟机所占用的物理资源)来极大地节省计算成本。谷歌在2013年对lmctfy其进行了开源https://github.com/google/lmctfy,但由于流行程度不如Docker,后面就没有再继续推广。同时,根据谷歌内部运行15年容器的经验来看,将应用程序装入容器仅仅是第一步,而后面的大量工作是如何管理、运维这一个全新的容器世界,因此谷歌在2014年将精力转入了开源容器集群管理技术,即Kubernetes项目:https://github.com/kubernetes/kubernetes
下面我们正好来聊聊谷歌容器集群的实践。谷歌在2015年已经达到了80多个数据中心,超过一百万台机器。其中大家所熟知的search,youtube,maps,gmail等所有产品,包括很多我们使用的内部工具,都是基于容器在运行。这个容器的数量是巨大的,官方称之为每周运行20亿个容器。那么紧接着我们面临的问题就是如何去管理这么多的容器,其包括:
-
决定哪个容器运行在哪台服务器上
-
如何实现应用容器的多副本部署来实现高可用、高并发,同时按需动态伸缩以节省、优化资源利用率
-
如何自动监测应用的运行状况,并在出错误时进行自我修复和故障转移
-
如何实现应用于配置的解耦合,使得一个数据中心的业务系统可以快速的“全盘”复制到另外的数据中心里(我们称之为cluster turnup and turndown,基本上是每个季度都会发生的事情)
谷歌为此建立了一整套集群管理(Cluster Management)机制,其中包含几十种不同的组建。如下图所示:
其中在外界知名度最高的容器任务管理组件:Borg。它之所以在外界更为人所熟知,一方面是由于谷歌发表了关于Borg的论文:《Large-scale cluster management at Google with Borg》, 另一方面也由于谷歌基于Borg的思想和实践开源了Kubenretes项目。Borg的最主要功能是一个容器任务调度和编排系统,负责将容器化应用自动地运行在何时的主机上,并对容器应用的生命周期(生老病死)进行自动化优化管理。下面我通过一个案例来描述一下这一整套集群管理系统的实践流程。我们以建立一个新的数据中心并在其上运行一套广告业务为例来看看谷歌的一整套运维、开发、管理流程。
1. 初始化
我们从硬件开始说起。当一台服务器从QA通过后,它会投放到数据中心里的一个合适的rack中。当硬件设施、网络都配好后,该服务器的信息会被写入一个集中的机器数据库里。这个数据库里不光记录了机器的硬件配置信息,还会记录这台服务器会被赋予哪些平台级别的特殊使命(例如运行Borg的master节点、运行Chubby服务器等)。默认地,每一个服务器上都要运行Borg的工作节点服务(Borglet),用来运行用户应用和业务。
随后,在集群管理系统里一个叫做“亚里士多德”的组件会定期(每15分钟)获取机器数据库中的最新数据,当发现有新的服务器时,则会按照指示对该服务器进行配置:
-
先通过调用一个叫做installer的组件对机器进行操作系统的安装(谷歌叫做Prodimage,是一个基于Ubuntu的经过安全改良的系统镜像)
-
然后根据数据库中的指示,在服务器上安装合适的平台软件(borglet,borgmaster,chubby等)。
这里指的点出的是,我们对于每一个生产服务器的配置和安装,并非是通过ssh进行,而是通过在机器上安装一个API服务(称为sushiD),并通过调用API进行。这样可以避免SSH所暴露出来的过多的权限和潜在的attack surface。这个流程我用图表总结如下:
2. 管理和监测系统平台
当服务器和平台服务都运行起来以后,集群管理系统则处于一个有限状态机的模式,对服务器和上面的平台软件(例如Borg,Chubby等)进行不间断、自动化的管理和维护。
-
每个机器上安装的一个“机器医生”agent会时刻关注服务器状态(例如通过观测/proc目录等),并根据自己的一个“症状规则库”判断机器是否出现问题,例如 bad-hda, slow-ethernet等,如有,则将此问题加入机器数据库中。
-
亚里士多德系统在定期检查机器数据库时会发现服务器上的问题,并采用相应的workflow和工具进行软件修复。在谷歌,有60%的“硬盘”或文件系统故障都可以通过此自动化在线修复工具完成修复,无需人工介入。
-
除了对机器的管理,亚里士多德还会通过预先定义的server 模块和健康检查机制检查平台软件的健康性(例如Borg等)。无论是出现软件问题,还是软件所在的机器出现了问题,根据策略我们会采取不同的修复手段和软件迁移机制。例如如果是Borg的master所在的物理服务器出现硬件问题,哪怕这个问题还没有影响到上面的服务(例如机器过热),亚里士多德会触发在线替换的workflow,主动在新的机器上部署Borg Master服务,做到未雨绸缪。
-
当修复机器问题时,我们要做的一个准备工作叫做drain,就是把机器上的业务和数据先删除掉(由于谷歌内部的应用、数据都采用分布式结构,使得删除某个节点不会影响整体业务)。然而在删除前,亚里士多德系统会询问一些安全把控组件,保证该服务器下线后不会影响整体的系统容量。
上述是一个非常基本的工作流,只是管中窥豹。我用流程图总结如下:
3. 发布并运行应用
谷歌的代码都存放在同一个庞大的代码库中,开发者在开发完代码后类似于Github里的Pull Request一样也要发一个Change List,进行code review。在谷歌,code review是严格执行的,否则代码无法提交(除了特殊情况)。大致的开发流程如下:
1)开发者写好代码后,先在本地进行编译。由于谷歌的代码库非常庞大,编译代码所需的依赖可能就需要很长时间。谷歌内部使用了一个叫做blaze的编译和测试工具,Blaze可以运行在Borg容器集群上,通过优化的依赖分析,高级的缓存机制,和并行的构建方法,可以快速地对代码进行构建。而谷歌也将这一工具进行开源:http://www.bazel.io/
2)构建完成后,我们需要在本地进行单元测试,而单元测试的运行测试由一个内部叫做Forge的系统完成,而Forge也是通过运行在Borg容器集群上从而实现快速的并行测试。
3)当本地的代码更新以Change List的形式发送出来以后,谷歌内部的人员通过一个叫做Critique的UI进行代码审查,同时Change List会触发一个叫做TAP(Tap Anything Protocol)的系统对该Change List进行单元测试,并保证这个局部的代码变化不会影响谷歌的其他应用和代码。TAP具有智能的依赖监测功能,会在谷歌内部浩瀚的代码库和产品线中检测到哪些部分可能会被潜在的影响到。
4)当代码通过测试和审核提交后,我们会等到下一个release cycle进行发布。如前所述,谷歌内部的应用都是以容器的形式运行在Borg上。因此发布的第一步工作就是通过一个叫做Rapid的系统,对代码进行容器打包成镜像(内部称为MPM格式),再通过Rapid发布工具进行发布(按照前述的灰度发布原则)。
用流程图总结如下:
4. 应用运行期间的自动化管理
最后,我来简单分享下谷歌是如何采用容器集群Borg来实现其应用的高可用和高扩展性的。由于Borg博大精深,我这里只列举一些经典的功能:
1)动态任务调度:开发者通过Borg的命令行来将应用跑起来。在一个Borg Cell里,Borg调度器将会动态的、自动的、智能的为不同的应用选择合适的机器来运行。如大数据业务、cron job、Google web业务、搜索业务等应用都会被动态的分配到集群中的不同主机上,调度算法会根据每个主机当前的物理资源情况来做优化,实现物理资源利用率最大化,并保证各个主机的流量平均分配,不会造成局部热点。不同的任务有不同的优先级,来保证大数据任务不会在用户流量高峰期抢占web业务的资源。
2)模块、服务间的自动服务发现:Borg内运行的所有应用都有一个类似于DNS的名称,我们内部称之为BNS Path。不同的服务间相互访问时可以直接根据BNS名称来进行连接,BNS系统会自动地将名称转化为实际的IP地址。因此,在不同的环境切换时(例如从测试到生产)、或随着主机的重启或更换而导致底层IP地址变化,应用程序也无需做任何修改就可做到无缝迁移,极大地减少了环境配置和人工操作来带的成本与风险。此外,BNS的方式也更好地支持了应用的多实例部署,在具体的实例发生变化时,应用的BNS不变。
3)多副本负载均衡与弹性伸缩:为了应对互联网应用的突发和难以预测的用户流量,用户在Borg平台部署应用时可指定所需要的副本数量,例如运行10个Nginx的实例。Borg会自动创建指定个数的应用实例,并且:
-
对应用进行实时监测,保证任何时候都有指定数量的实例在运行。如果由于主机故障导致2个Nginx实例失效,Borg会主动地创建2个新的Nginx实例来保证高可用。
-
当其他服务需要访问Nginx时,无需直接绑定具体10个实例中的任何一个IP地址,而是可以通过上述的服务名称(例如“Nginx”)来访问。Borg会自动将请求按照一定的负载均衡策略转发到10个实例中的合适实例。
-
集群管理中的其他组件如 Autoscaler还支持自动伸缩策略,例如当CPU利用率超过60%时,自动将Nginx从10个实例扩展到20个实例。
4)自我修复与故障应对:当应用程序出现故障时,Borg会自动发现并在新的主机上重启应用。Borg检测故障的方法可以针对业务和应用进行定制化,除了简单地检测应用是否在运行以外,还支持基于HTTP钩子的自定义监测(内部称为healthz和varz)。而其开源的Kubernetes也支持类似的自定义健康检查规则:
-
HTTP钩子:例如对于Web应用,检测其服务URL是否正常
-
检测脚本:对于任意应用,通过定时在应用容器中运行自定义脚本进行检测。以Redis为例,可以通过 “redis-cli”来进行自定义的数据检查。
-
TCP socket:可以通过检测TCP socket来判断应用是否健康。
5)配置管理:一个复杂的生产系统中存在诸多配置,除了不同组件的IP地址、端口,还有应用程序的配置文件、中间件的配置文件等。Borg充分利用了基于Chubby的配置管理服务,实现应用与配置的分离。用户可以将不同环境下的应用配置文件、数据库密码、环境变量等配置放入每个集群内统一的Chubby服务中,并为每一个配置项取名字(例如 “APP_CONFIG_FILE”, “DB_PASSWORD”等),而后应用可通过这些名字来在运行时获取这些与环境相关的配置信息。此外,Chubby支持watcher功能,因此应用程序可以动态监听其配置文件是否有变化,实现配置的热更新。感兴趣的朋友可以参考Chubby的论文来了解更多详情:http://research.google.com/archive/chubby.html
Q&A环节
Q:数据分析真的能驱动用户快速增长么?
A:一定能的!谷歌有非常庞大的数据分析团队,除了专门的团队,广告、购物等revenue产品都是基于数据。开发新功能前要通过理论验证和数据分析推演它对用户增长的作用(比如click through rate);此外,每一次新的release,一定是通过严格的A/B测试,通过数据分析,因此广告组和shopping组里有非常多的data scientist。
Q:谷歌的管理制度对你目前公司管理有哪些方面的影响和应用?
A:从我个人仅有的团队管理经验来看,有值得借鉴的地方也有不接地气的地方。在我的实践里,performance review中融入很多peer review的成分对于建立健康的技术团队氛围和互帮互助精神比较有利。此外通过planning poke来做规划也能充分调动大家积极性,让每个人都参与其中,同时通过“赚取点数”让大家感到这个形式比较有意思。
但是20%和团队轮换等,一方面是只有大公司才玩得起,另一方面是谷歌工程师的自我管理约束力和self motivation也是在一般公司可能难以找到的。所以在管理的灵活性上要打一些折扣。
Q:OKR制定后发生战略调整,是否也同时修改OKR?如果这一变化发生在考核期已经过了一半的时候如何处理?
A:是的,出现重大的战略调整,在审核OKR的时候往往会加上"blocked by XXX",这个会灵活调整的。但是客观上,确实会对这个OKR的assignee造成不可避免的影响。我个人经历了3次谷歌内部战略调整造成的被迫转变方向,这会影响个人绩效和工作的连续性。
Q:Google的技术和产品是两个团队吗?是产品提需求吗?有项目经理吗?
A:Google一般分为是userfacing product还有internal product(比如borg)。对于前者,有专门的产品经理,一般是产品经理提需求,技术团队实现并参与讨论,和传统的比较像。对于internal product,一般用户是谷歌工程师自己或是SRE,这种产品一般没有PM,由工程师或SRE自己提需求。
Q:谷歌怎么监控系统异常,如何预防和恢复?
A:首先,最重要的几点:1)监控系统一定要避免cyclicdependency,比如监控borg容器集群的系统不能运行在borg上。2)监控的指标一定要简单,actionable。具体的监控和预防除了一些黄金metrics,还要根据业务来制定,这个我不太好一概而论。从预防和恢复的角度,讲究三个层面:a) prevention, b) detection, c) resilience。具体展开的话有很多东西,可以私下细聊。
作者简介:
才云 联合创始人 & CEO 张鑫
曾为美国谷歌软件工程师,从事谷歌核心技术底层系统研发。2012年至2014年,作为主要技术人员从事谷歌数据中心(IDC)集群管理系统(Cluster Management)的研发,该集群系统自动管理和维护95%以上的谷歌集群机器;带头开发的自动故障应对系统将谷歌集群的故障率大大降低,为谷歌节省了每年千万美元的运维成本;作为核心技术人员参与了谷歌云计算平台的系统到产品的全栈式开发;开发的图形化应用部署(Click-to-deploy)、部署经理(Deployment Manager)等产品上线后即获得用户广泛使用;设计了谷歌倡导的新一代“云服务”(Managed Cloud)的设计,此理念获得了美国IBM,VMWare,Redhat等云计算巨头公司一致响应。
于2012获美国顶级计算机学府Carnegie Mellon University (CMU)大学计算机博士学位,发表国际学术论文数十篇,成为分布式系统和网络安全方向的学术专家,曾为美国个性医疗初创公司SMART-MD, AllPancreas提供应用软件平台构架、安全技术咨询和基于云平台的系统开发。
来源:oschina
链接:https://my.oschina.net/u/2668812/blog/725640