0%

携程持续交付平台的演进、变革与展望

本文转自:https://mp.weixin.qq.com/s/HqyJQMRHh2KrdFmNtPbX3w

越过山丘:携程持续交付平台的演进、变革与展望

2018-01-23 王潇俊

本文整理自国内首届 Jenkins 用户大会演讲:《越过山丘:携程持续交付平台的演进、变革与展望》

讲师 | 王潇俊
编辑 | 黄晓轩

讲师简介

王潇俊
携程 系统研发部总监
多年致力于云平台及持续交付的实践,15年加入携程,参与携程部署架构的全面改造,主导设计和打造新一代的适用于微服务的发布系统。同时负责基于携程私有云的,兼容虚机与容器的持续交付平台。ROR狂热粉丝,敏捷文化的忠实拥趸。

阻碍是什么

持续交付其实是解决阻碍问题。解决阻碍首先要知道阻碍是什么,其实我们阻就碍是一堵堵的混乱之墙。如果你读过DevOps宣言的话,可能很容易理解,DevOps说的混乱之墙是指开发和OPS之间,从开发产物如何变成线上跑的产物之间的一堵墙。

在整个研发过程中处处出现这样的墙,这些墙出现在不同研发的角色上,简单来说就是这样的一幅图。


这个图出自《持续交付》。这中间有三堵比较重要的墙,项目经理和开发工程师,测试工程师,Ops工程师。

每个工程师之间都有一堵墙,都有一些方法论和学术上的东西,或者说最佳实践来解决这些墙所在的问题。分别是敏捷开发(通常说的Agile和Scrum),解决了产品经理到开发到测试之间存在对需求不理解的墙。

有持续集成,继续集成是提出最早的概念,解决的就是开发工程师和测试之间的墙。有DevOps,最近比较火,十几年前就提出,最近开始火起来了,主要是因为Docker的原因。他解决的就是开发工程师、测试工程师和OPS工程师之间这堵墙问题。统统加在一起的概念叫做持续交付。

有的同学在聊持续集成、持续交付,其中需求、发布、交付都没有提到。超出这个图之外,其实还有持续交付的过程。

这个产品特别是像互联网的产品,交到用户手上以后,你会不会跟用户之间有墙,一定有。不止隔着墙,也隔着山和海。后面持续交付还要继续往下走,就要解决一些与用户之间的墙。这就留给大家或者我们将来慢慢解决的问题。

删除误区

刚刚知道了我们墙在哪里,接下来的问题就是怎么拆除这些墙。平时我在公司里面一般说的是,我们这样的团队,我们叫持续交付也好,工程效能也好,其实都是拆迁大队。通常就是把原来有的东西全部拆光,拆光以后重塑我们整个研发流程。

携程做了两年多这样的事情,后面我会分享一下在携程实践的经验来跟大家做一下交流。

对于方法论或者怎么拆这个墙要有一个统一认识,我们有一些错误的观点,这里可能要撇除一下。持续交付是什么,持续交付生命周期是从需求没有开始,到需求最终落到用户手里,并且不断迭代的过程,他叫持续交付。

这个链是非常长的,所以我们很多在提的包括Jenkins也仅是解决了一部分的问题,解决了代码上线发布的问题,发布后的问题都没有解决。

还有一个误区是,我们做持续交付团队,做工程效能团队都会被老板问一个问题,今年的KPI是什么,你想给自己立的KPI是什么。包括你做的自动化测试,你觉得这个问题头痛吗?肯定很头痛,累死了,我不知道怎么回答老板。

老板问我这个问题我就会告诉老板“让我死吧”。因为我改进了所有的东西,最后老板都可以说一句“可能是我们技术进步了,是我们市场变化了,是我们人员本身的素质提高了”。好像都跟我们没什么关系。

持续交付也好,工程效能也好,到底改的是什么?老板让你最好给个数字。百分比怎么算?让我死吧。

这里我想说的是我们在这个事情上一定要有一个度量方法给到老板,这个度量方法也是在不断改进。几年之前我跟老板提的概念是这样的,有一个指标TTM(Time To Marketing,产品上线时间),从这个产品想法的出现到最终这个产品落到用户手里时间花了多久。

腾讯说以前爆长,现在变短了,这个绝对可以拿给老板作为很好的指标,但也看到了腾讯用了巨大的成本,做了那么多的系统最后得出这个值。对于小公司或者这方面还不是很成熟的公司是拿不到的。光花在计算上的成本就非常大。

最近几年我也不跟老板说这个问题了,换一个方式跟老板说,我们做的事情是给工程师提供武器和弹药。我们去看工程师做的每一个事情,比如说工程师提交代码需要多长时间。一个资深工程师到了公司,从写第一行代码到这个东西产出完,上测试环境需要多长时间。一个初级工程师什么都不知道,到了公司有第一份产出需要多长时间。

这是非常重要的指标,老板发现如果我一个工程师是外部来的,哪怕是应届的也好,有经验的也好。我们说有经验的,到一家公司比如说腾讯,如果不熟悉刚才的流程,我估计我也不行。

在携程我们不讲这个的,我们讲的是任何一个工程师到我们公司,给你一套系统入口,你多长时间能够产出。你的产出在半天之内,你的工程效能就做的很好了;你的产出在一个月,你要研究各个部门在干什么,要研究每个工具要干什么,这就不好了。

我们现在得指标就变成了,看做一件事情端到端的时间是多长时间,而且是不同的人,任何人做这件事情是否都是这样的时间。如果都是这样的时间,说明你的工作就做到位了。

这是乔梁老师几年前给持续交付定义的七巧板,包含了七块主要内容。其中包括数据及环境管理、测试管理、配置管理、构建集成、发布及监控管理。

这里划了很重要的一条线,原先Jenkins没有说,持续集成也没有说的东西,系统架构的适应性和组织协作的机制,如果这两块没有被拼上去的话,你会发现做上面的持续交付就非常困难。

后面我会讲一下这两块对于持续交付有多大的重要性。

随着时间的变迁、技术的发展,这块七巧板也不太够用了。我偷偷的改了改,改了两块东西。第一个是把配置管理去掉了,改成资源管理。

为什么加这个东西,Jenkins里面压根没有说资源管理怎么搞,你的机器哪来的,计算资源哪来的,存储在哪里,这些东西都没有怎么交付。我想跟KK说的是要把这块加起来。

除了这块以外还有测试管理。测试管理不是我想去掉的,而是想弱化的,因为测试管理太难了。而且每家公司的测试管理方法都不太一样,“手Q”有“手Q”的,携程有携程的,阿里有阿里的。

因为业务不同,关注测试质量点也不同,测试管理很难做标准化。但代码管理可以加上,因为大家都认识到代码管理是可以被抽象标准化的。所以我把这两块进行了一些改变。

这个是携程的PaaS平台。七巧板这个图很有意思,把这两块东西改掉以后你会发现,整个东西有点像什么?配置为什么被剥离出去,因为现在大部分互联网公司,配置管理都变成了统一配置,有配置中心,不再采用配置文件或者让SCM帮你管理环境上的配置的方式。

这样变迁以后就是一个PaaS平台。最终你会发现,你要做持续交付、要做工程效能,最后可能做着做着就是一套完整的对公司内部的私有云或者内部的PaaS平台。

接下来我逐步讲一讲携程这几个方面大概是怎么做的。

一、代码管理

代码管理在携程做的还是比较简单的。我们是基于Gitlab做的。可以看到有一些二次开发的东西,Sonar,issues就直接加上了,这个在官方社区版里没有,企业版的Gitlab可能是有的,我们提前自己做了。

Sonar的扫描我们提炼了一些标准,大概100多条,在代码每次 check in 的时候都会被扫描的。如果扫描没通过就没有办法Merge,这是我们做的方法。

这边我要提一下的是我们没有强制的分支管理的方法,我们是随便管理分支的,单分支开发也可以、主干开发也可以,Feature开发也可以。我们用的是Gitlab,可以有多分支的开发。

我们会做一件蛮有意思的事情,我们每次合并的时候,并不是把主干的分支或者测试的分支覆盖掉。而是我们会产生一条临时的在内存中假存在的分支。这条分支会做一次真正的合并,这个分支会发布到测试环境当中。

这样的好处是什么?当我的用户测试完,或者开发发现他自己的Feature分支有问题时,只需要在我们配置系统里面把我要合进去的分支删掉就可以了,并不会污染我真正的主干分支。这个假的Merge是在每次发布之前做的。

这样的好处是,冲突检测可以很早的进行。即使真的出现冲突也不会有污染,也减少了我们很多revert和cherry-pick的工作量。另外一个是对代码仓库的管理。

携程是一个标准化的往微服务走的方式,所以我们的代码仓库都很小,每个应用的代码能解耦的一定要解耦,用代码包管理的方式和包依赖的方式来解决最后集成的问题。因此每个仓库都不会很大,编译的速度以java为例平均一个项目一次编译是40秒。

二、集成构建

下面看一下集成构建这套系统,40秒怎么做出来的。我们集成构建系统,着重提的是两个字:第一个是“构”;第二个是“成”。分别代表的是我要编译我自己本身的这份代码,还要拉取我自己的依赖。

核心的概念是每一个编译其实都会产生一个带有唯一版本号的发布包。这是在携程做的事情,所以你去看带版本号的发布包是我们的最终产物。

这个平台上可以看到我们整个这一个应用,其所有历史版本的变迁,包括在每个环境上部署的情况,包括一些测试是否通过的数据。基本上编译就这么简单,没有特别复杂的。

复杂的是后端看不到的编译平台,我们在Jenkins之上又封装了一层。我们的Jenkins是跑在K8s上的,这是有坑的。

Jenkins本身有Master/Slave的方式,但其又不共享workspace,所有的Docker容器要实时调度,都要做到无状态,但workerspace是有状态的,而且这相当于你的缓存,相当于你提速的机制,在无状态下怎么做到兼容Jenkins有状态,到现在没有特别好的解决方案。

这个在存储方面可能要进行深度的加工,我们暂时现在是用快存储的方式进行共享。所以我们编译是根据你的编译需求,实时弹性产生编译资源的,所以我们会一直保持在40秒的平均水平线上。

这是我们的监控也会一直在追求整个编译的速度是否够快。我们目标是编译的时候不让开发有喝咖啡的时间,连抽烟的时间都没有。

三、灰度发布

在携程,灰度发布有两个概念,第一个是分环境进行发布测试。

携程有四套环境,第一套叫FAT,是用来跑Feature分支的,就是跑功能的,任何开发都可以往这套环境上部署你的代码,测试你自己的功能。

第二套环境是性能测试环境,主要是测性能的,我们不希望性能测试压力对我们正常持续交付过程产生影响,所以是套独立的环境。

有一套公共环境,我们叫FWS,我们把底层公共的service放在这套环境里面。这个可能涉及到本身服务治理的问题。

服务调用的顺序,首先根据开发配置的地址调用,如果没有配置则优先调用同一个子环境中的服务,如果同一个子环境中也没有这个服务,就调用公共环境中的。如果还有没,首先零级别是调用你配置上的。

最后一套是UAT环境,相当于一套集成的环境,所有携程的应用都会拷贝在UAT环境里面做集成。但这个在几年以前UAT环境被使用的特别多,现在越来越被弱化了。

走到微服务以后,会发现服务和服务之前解耦性很强了,我在功能测试环境测试完成了,在UAT中只要跑一些很简单的公共用例就可以了,不需要再做大量的测试。

然后是生产环境,生产环境我们有一套独立的发布系统,是灰度发布的系统。

这里有两张图,一张图是未发布时的,版本和历史的情况,包括机器的分组,我们把所有发布最小的单元称之为group。一个group可能包含多台机器,也可能一个应用在多IDC,同一个IDC里面可能会有多个分组的机器,可以根据开发自己定义的分组,进行不同阶段的发布。

每个分组过程中本身也有一个灰度发布,可以控制实时拉出的机器比例,这些流程用户是不能打破的。

我们这边有一些数据,携程每周的发布次数大概是8000次,我们一共有活跃的应用是3000多个。每周生产发布次数是8000次。测试的发布次数是20000多次。

可以看到携程发布效率非常快。这样的好处是任何一个很小的变更就可以进行发布、测试、上线。这样解决了很大的问题:版本冲突没有了,写完就上,谁写的快谁上,没什么冲突。一旦发布解决了问题以后,对你代码也有一定管理推动的作用。

四、资源管理

资源管理简单来说就是怎么拿到我的计算资源——机器。这是我们携程拿机器的一个主页面。

可以看到在这个页面上,我们划分了不同的IDC,每个IDC可以申请不同分组,申请不同机器的数量,可以是Docker也可以是虚拟机,甚至还做了云上的。

携程通过这个页面可以直接申请到阿里云或Amazon的机器。然后通过刚才的发布系统将代码包发上去就可以了。Docker我们不是发的代码包,是Docker镜像。

我们Build的过程中是两份产物,一个是可部署的代码包,第二个是可以直接部署的Docker镜像。这样针对终端用户是透明的,他不需要关注我发布的是什么,把代码部署好能跑起来就可以了。

然后在这样的环境下我们甚至是可以在这样页面上处理一些入口的问题,比如说我的域名,我的访问路径都是可以在这里一页解决掉的。右边会有一些不一样,应用每个group的基本信息。

这个是机器的情况,包括现在的版本,机器的发布状态,还可以对机器做一些简单受控的操作。

所以可以看到我们在解决一些什么问题,并不是让OPS去做这些事情,我们是让每个开发小组的开发人员或者测试人员,能够做这样事情角色做这样事情的,这才是刚才我说我们想做的事情是提供工具和提供给开发人员一些武器,让你在受控的时间自己去完成这些事情。

我们统计过申请一台机器,包括完成部署平均是1分钟左右。1分钟就可以拿到想要的东西。

五、测试环境

我们看一下测试环境的问题。对于所有的测试来说,测试环境才是最重要的。自动化测试都是有解决方案的,但测试环境目前没有统一的解决方案。

测试环境最头痛的问题就是一个,一家公司或者说我们公司到底需要多少套测试环境,或者需要多少套独立的测试环境,跟别人隔离的。

影响到我做预算,每年会做预算,明年我的业务怎么增长。要多少套配套。因为我同事并行开发的时候都会受到不隔离的影响,这些事情又是非常痛苦的。

在没有弹性,没有DevOps支撑,没有刚才我所说的资源管理支撑之下,你只能说很固定的做这个事情,每年采购机器,装机器,等着QA来用。最后发现这个项目砍掉了,没有用。我们携程有两个打造测试环境的依据和我们想做的目标。

第一个是我们想打造强大环境的克隆能力,这个克隆能力包含三个部分,第一个是我要版本+资源+发布融为一体。也就是我前面说的几个,集成构建、资源管理,加上灰度发布。

三大能力打造完之后,就会自然形成一种克隆的能力。这个克隆的能力恰恰又是我们现在碰到任何的Jenkins也好、Docker也好都没有办法企及的东西,Docker不解决环境问题。

任何环境工程师碰到Docker都会骂娘,因为实际上Docker在说一个概念就是不变化的部署,希望说产生一个镜像,一个镜像走天下。

但不可能的,你的测试环境跟生产环境一样吗?机器配置一样吗?不一样,网络环境一样吗?不一样。你要测的东西、辅助的工具一样吗?也不一样。

一个镜像走就是让所有环境工程师下岗,他根本没有解决方案,Docker根本没有想过这个问题。

只有当你有了很强大的克隆能力之后,你才可以解决这些问题,Docker一个镜像可以快速部署,但整个环境没有办法帮你部署的。他只能帮你部署起应用实例。

还有一个更讨厌的东西就是DB。微服务的解耦,所有的解耦到最后都会碰到一个核心的问题,就是DB是解耦不了,数据是耦合的。测试的时候没有办法脱离。

比如说最简单的问题,我是测试机票购买的,但我脱离不了用户数据,我必须得有用户数据才能测我的购买,否则怎么测。

所以就会变成我需要多少套完整DB的问题,携程的解决方案是我们对每套DB要求建立一套基准库,就是可测的,包含最少可测的数据结构、数据记录的基准库。用于被不同的子环境、测试环境克隆。

第二个就是刚才说到的,所有的服务要有非常清晰的路由控制能力。携程的RPC服务,是基于http协议的,做起来会比较简单,但是你只要有服务治理的系统,都是比较容易做到根据用户的需求来指定我要调用哪里的服务。

有时候一套子环境是不能充分支持你的测试的,必须要跨出子环境,调用别人的服务。这个必须是受控的,这个不被控制的话,你会发现你的环境没有办法做到隔离。

既使是你做到了隔离,你会发现被隔的太严重了,在一个孤岛上,没有办法跟别人进行互通。

所以你就在隔离孤岛和完全互通的概念中,形成一定的平衡,也就是有完整的路由控制能力之后,才能够很好的解决你测试环境的专用独立环境的目标。

六、架构适配

刚才说到的这些东西,多多少少都带出了一些架构适配的东西,包括路由也好,包括Docker整个环境架构。我下面会列一下到底有多少东西,如果架构给到我们支撑,我们持续交付能够很好的做到。

七、组织适配

组织适配我最没有想明白的事。什么人适合做持续交付。很多公司持续交付的团队都是由原来的SCM团队、QA团队转型转过来的,这些人是不是真的适合?在我看来不太适合。

因为他对我所说的架构,应用的运行,不能很好的感知,没有掌握到很多技术核心点。单单从这些组织转过来的,很难最终达到我们想要的持续交付的效果。

这样的情况下必须要有架构团队,应用团队,ops团队合力协作,最终才能完成整个持续交付的过程。

八、容器交付标准

容器技术现在比较火热。携程在做的事情,就是容器时代我们怎么做一些持续交付。

第一个是容器带来的非常大的剧变。剧变原因是什么?他把交付的标准改变了,所有人的交付产物变化了,以前大家都说环境这些东西是SCM或者QA团队提供的,现在变成开发一个人独挑。

开发给你一个可部署的镜像,包含环境,包含运行时的任何东西,把所有的标准都颠覆掉了。

举个简单的例子,我们现在很多人在跑Pipeline,是不是有一个开发说我特别牛,我不要这个Pipeline,我本机产一个镜像给你,我告诉你跑在哪些物理机上,或者连物理机是什么和宿主机都不告诉你,直接去跑吧,能跑起来的。

你敢不敢发布?巨大的问号。所以容器这个世界有很多东西是很模糊的,需要慢慢的摸索,也许我们传统的Pipeline方式,工程流的方式有他一定的作用来保证质量,能够提高效率,也许过几年回头看,也不一定。

这里容器我能给大家的分享和建议,至少在携程来看就是所有的平台、工具、应用都要往Cloud Native方式靠拢。什么叫Cloud Native?很难解释。我们现在采用的标准很简单,我一个应用或一个平台,能不能在阿里云马上跑起来,能就是Cloud Native,不能就改造。

最后我引用一句话做为我分享的结束“PaaS平台的能力,直接反应持续交付的能力”