@gaoxiaoyunwei2017
2020-04-27T21:59:05.000000Z
字数 12884
阅读 1258
未分类
作者简介
京东工程效率专家,DevOps 标准核心编写专家
很荣幸参加第一次的CI/CDMeetup,也是我人生第一次直播,对着电脑一个人讲,希望大家有问题多多提出。话不多说,今天的主题是超大型移动APP的CI/CD实践,简单去自我介绍一下,其实我这几年来一直是在跟Jenkins社区在做很多的活动,那从2017年开始一直到今年,Jenkins大家也知道,从一个项目被捐献到了CD FOUNDATION里面,成为CD FOUNDATION里面一个初始的项目,所以后面我们会组织很多围绕CD的更大领域,而不仅仅局限于一个工具层面的线上活动,也欢迎大家多多参与。
在开始正式分享之前,其实还想跟大家聊聊,就是CI/CD其实是在说什么。因为我在公司里面包括很多外部的同学在交流的时候发现其实大家对于CI/CD的认知并不一致,所以我就简单找了一张图,这个就是我们正常的,一般来说的一个软件交付的流程,那CI/CD到底代表哪些环节?大家可以看一下。其实从软件开发开始,到开始构建、测试,包括一些检查,所以在开发环节的时候更多是在聚焦于CI环节,就是持续集成环节,那么持续集成环节更多的是在研发环节做一些开发活动。CD其实更多是从部署开始,从不同环境的部署开始,会逐步覆盖我们多环境,逐步的去放量。
所以简单来说其实CI对应开发的环节,CD的话就是对应运维环节,其实大家可以发现,开发环节和运维环节的打通,本质和DevOps一脉相承。简单一句话CI干什么的?CI的目标核心就是生成一个可运维部署的包。这个包对于移动应用来说应该是一个IPA或者是一个APK,对于运维端来说可能是一个跨包(音)。总之,不管什么样的类型的部署,其实CI最终想要产出的就是一个可以部署的包。CD是干什么的?其实它想要做的就是安全和自动化在多环境完成整个部署活动,而不是人手工的去部署,然后通过流水线把两个环境打通,从而实现了所谓的CI/CD。所以一开始想要跟大家说清楚,我理解的CI/CD到底覆盖到我们整个软件交付的哪个环节里面。
开始第一部分主题,大家发现这里的关键词,就是超大型,超大型是什么意思?联想到苹果的手机,在iphone6的时候出了一个特别有名的文案,叫做“比大更大”,后边还有“不止于大”。开个玩笑来说实际上超大型到底是代表什么?其实它是需要一个衡量标准。所以在我这里面给大家举几个数字来看看,就是超大型APP到底是一个什么样的概念。
首先第一有300多个组件,对于每个平台来说,不管是安卓还是IOS,都有300多个组件,每个版本都有600多个需求,上千人围绕这样的平台,或者一个应用去进行协作,而代码更多是百万级的,对于这样的APP发布频率,是要做到两周一个正式版本,每两周会发布一个正式版本。那么我说的其实就是大家经常提到的京东商城APP,对于这样一个超大型APP来说其实我们面临很多具体的挑战。我简单去罗列几个:
第一个会有数十个团队做协同交付。大家知道京东体量非常大,会有上千人,数十个团队在一起协同交付,包括前台、中台,那这样团队越多,你也会知道交付之间的壁垒或者瓶颈,这会导致整个交付效率受到团队交付的影响。这是第一点,就是人多,这事就乱,所以会影响我们的效率。
第二点,复杂多变的技术栈,可能没有做移动APP的同学觉得移动APP是不是就是一个APK的包或者API的包?其实不是这样,因为移动APP现在的技术非常复杂。比如京东为例,除了大家直观可见的APK、IPA,它还包含什么?还有服务端,也就是客户端,那还包含什么?还包含H5,还包含小程序,甚至还有一些新型的技术,像(10:03英)这样多端的技术。所以你会知道这样一个呈现在大家眼前的APP,其实里面呈现的技术栈非常复杂,远不是一个简单的APK所能够去涵盖到的。这样的话对于每一种技术栈,其实交付的频率和使用的架构,交付的流程,可能都是比较复杂,所以我们要适配这样多复杂的技术栈的持续交付的需求。
第三点就是内部的系统很多,大家知道大公司,内部有很多系统,那系统和系统之间的交互,实际上是非常痛苦的过程。我们在很多系统上实现自动化,系统和系统之间还是靠人肉去搬运信息的,所以这就导致在系统和系统之间带来很多效率频闪的点。
最后一个其实就是应用平台的管控制约。用过APPstore或者这些应用商店的同学知道,你想APK或者移动应用不可能一天给你发布10次20次,那这个用户就疯了,每天都在重启APK。另外的话像苹果商店他也不会让你想发就发的,每次发布其实你要经过他复杂的审核流程,这个过程中总会有各种各样莫名其妙的问题,导致你的应用不过审,甚至比较严重的情况下导致你的应用下架。所以大家知道现在对于一个企业来说移动应用其实就等于一个企业的门面,如果你的应用被下架,等同于你的服务被中止了,所以这个对公司影响非常大,这些都是挑战。
一句话总结,一个APP我认为现在这些场景是持续交付的集大成者,因为涵盖了多端,还有各种技术栈,还有非常复杂的团队协作的要求,所以这也是为什么我想要跟大家聊一聊移动APP的持续交付是怎么做。
前面说了很多都是一些背景和铺垫,接下来看看具体我们干了什么。简单概括,分为四个方面,就是流程还有工具架构,还有环境,所以大家可能觉得CI/CD是不是我引入了一个Jenkins工具就实现了CI/CD,其实也没有这么简单,因为刚才我也提到很多背景和约束,那么工具只是其中的一个环节而已,所以不要把工具等同于CI/CD的建设,我们要从一个完整的体系化的方式去解决这样的问题。所以我包含四个方面重点来做,流程+工具+架构+环境。
首先第一方面看看团队,对于上千人的团队来说,以前我们的分队方式是按职能划分的,所以这个对于传统企业来说大多也是这样。但是为了满足不同业务模块快速交付,实际上我们做了很多的组织方面的调整,很典型的话从一个职能型的团队变成一个跨职能团队,这个跨职能团队在京东这边叫敏捷团队,敏捷团队里面有什么人?其实包含产品,还有敏捷教练,还有开发,还有测试。你可以理解为它就是一个闭环的小团队,主要负责敏捷模块的开发和交付。在每个版本排期的时候也是按照每个敏捷团队做相应的计划和排期,这是在组织层面的调整。组织层面的事不多说,因为我们在聊CI/CD。
第二部分看看这么多敏捷团队,大家想要协同办公,协同工作,肯定需要一些标准化的流程和步调一致做交互活动,在这里面其实最重要的一点就是分支策略。经常有人说,什么样的分支策略是好的?分支策略其实我理解,最核心它要满足的就是满足你的节奏,如果你的发布节奏是一年发布一次,那其实你用长分支也未尝不好,如果你的团队每天都要发布,每天要拉一些分支,这样可能不合适。所以一个好的分支策略,首先是要匹配你的发布节奏,刚才也提到,对于京东APP来说发布节奏是每两周一个正式版本,这个节奏来说,我在业界看起来也是比较高,能在每两周发一个版本。大家知道正式版本里面还有很多不同的内部测试版本,所以基本上每天我们都会有新的版本出来。为了满足这样相对快速的发布模式,我们采用的方式就是主干开发,所以下面给大家放了一个内部的分支策略图,比较简单。看到中间的master其实就是我们的主干,单主干这样的模式,各个Feature其实会拉出自己的Feature的分支来,按照自己的开发节奏合并到Master主线上。这些Feature分支的负责人是谁?就是我刚才提到的一个一个敏捷团队。
大家看到每双周会发布一个版本,我们会把整个双周做细分,在每个节点上我们到底要完成哪些事情。所以简单介绍一下我们会通过第一周,主要是开发和集成,第二周做很多的灰度,还有正式包。虽然我们是主干开发,但是并没有每次都拉出发布分支,其实这个原因是在于说每次发布都有相应的标签,如果需要有拉出发布分支的话,随时随地都可以拉出。所以这样一种分支策略来说,其实对研发是比较简单,它所需要关注的就是在Feature分支上,然后在Feature分支上开发完成之后合并到主线。然后我们发布的话从主线发,所以这样的一种分支策略是极大简化了上千人团队在协作上的认知的复杂。如果说你的分支策略非常复杂,需要每一个人了解的话,其实它就应该尽量足够简单。
所以这是我们的分支策略。那么分支策略有了,大家协同办公,协同交付的步调基本对齐。接下来做什么?最重要建立一个端到端的线上化流程,并没有识别潜在的失控点。对于软件交付我罗列了一些阶段,其实在每个公司,每个业务来说都是大同小异,都是这些步骤。首先我们要做的就是要把这些东西搬到线上化。因为我见到很多公司还是通过一个excel、email去驱动开发,这个显然会离线上化的目标有很大的距离。
那我们在做线上化的时候,在很多公司基本都是这样,一段一段做,跟我们节奏划分团队划分有很密切的关系。比如说在开发阶段,其实会有测试平台,在提测平台有提测平台的发布,有发布平台,所以在大多数公司来说不会上来就有一个非常明确的顶层规划做一个一体化的平台,大多数情况下还是在每一段每一个团队里面内部去做局部的优化,局部的平台。所以这个是比较常见的现状,就是多平台会做覆盖到整个研发交付流程,而不是一体化平台。
那么好了,这个过程中至少我们做到了线上化,那接下来要做什么?就是要识别潜在失控点。所以我在这里面简单罗列几个例子,比如说在版本提测这个地方,因为前面这个平台跟我提的平台是两个独立的平台,这里面就会有一个潜在的失控点。你提测的版本是通过前面CI的版本吗?还是研发不知道随便拿一个版本过来就进行提测,所以这就是一个潜在的失控点。第二个集成也是一样,通过提测之后会开放我们的主干提测权限,那你开了权限之后,你集成代码是之前通过的版本代码吗?所以这个也是一个潜在的失控点。
对于生产发布来说同样的道理,你发布平台的系统和版本其实是不是通过前面的测试这样的版本,如果说系统跟系统之间没有做打通,其实这里面都是一些潜在的失控点,所以我们做流程治理的时候,其实对于写失控点,都要有相关的解决方案。比如第一例子,可以建立一个提测质量门禁,第二个做自动化代码集成,第三做上线版本检查。
那解决流程失控点的方法,其实不外乎就是这么一个公式,第一就是标准化,要有标准化的流程。第二要把这个过程做自动化,第三提供一些附加值,最后是强制约束。光看这个公式大家可能没什么感觉,我给大家举个具体的例子,比如说还是提测这个事,在没有做三个点的优化之前,其实提测都是研发自己做的,那我们要去解决这个问题,首先研发对于这个流程规范,其实天生并不是说一定要去很欢迎这样一些流程规范,其实研发都喜欢比较自由,想怎么做怎么做,你非要给他套一个流程规范的话,其实会有一些抵触情绪。所以我们先做了流程的标准化,你需要哪些东西。第二做自动化,就是节省你提测成本,当你手动提测的时候,你要体验二次的字段。
比如说你在流水线打完包之后通过一键提测,很多信息可以自动生成,可以简化研发的操作成本。第三个附加值什么意思?当你把系统和系统之间打通之后,你去自动化把这个版本相关的信息拉过来,在提测过程就会知道这个版本到底改了哪些东西,还有哪些需求,这对于比如说测试或者后续的验收环节,还是能带来一些附加值,能够帮你修炼你的测试的范围。那这三点做完之后,最重要还是有一个强制约束,其实我们发现,我们任何流程如果不强制约束,一定会有人还是按照老规矩去做,所以这也是大家的一种习惯,习惯的力量。所以其实在有些时候对于流程的管控其实需要强制约束,但不是说上来就简单粗暴,并不是说你不能这么去做,而是要在你做好标准化、自动化和附加值的情况下去做这个事情。
比如我举几个例子,对于系统来说,首先线上化的端到端流程是可视化的可以展示出来,大家可以知道我现在到底跑到什么阶段。左下角就是在解决我刚才提到的第二个失控点,就是代码的集成问题,那因为我们整个系统是组件化,所以你在提测完成之后在系统上可以直接选择你的组件去完成这个集成的动作,而不需要线下手工完成这个集成动作。但因为我们做了系统的线上化集成,其实这样的过程是可管控可追溯的,所以就会保证说你不会因为给你开通权限之后你自己私自再搭车提交一些东西。所以这就是系统要去做到的一些标准化和自动化的动作。那质量门禁大家比较好理解,我就不多说。
第二个方面给大家提提工具,也是我比较熟悉的持续交付流水线,其实对于这个流水线来说,大家基本上都了解,每个人我估计都能说上来,比如说提交、构建、测试,那就是当你看到这个图的时候,我在想,是不是每家公司你的流水线跟这个长得一模一样,其实流水线就是对于我们整个交付过程的抽象。但其实没有两个公司的流水线是完全一样的,所以你不能说简单按照这样的流水线的建模去设计你的系统,把你的系统设计为刚才我画的图那样的方式,就发一个固定的五个阶段,没有两个公司是完全按照那个东西做的。
所以流水线不应该成为制约灵活发布的一个瓶颈,为什么这么讲?因为我刚才也提到,对于大型的APP来说分很多技术栈,那对于服务端来说是会更灵活去发布上线,那对于客户端来说,会受一些外部因素的约束,更有节奏做这些事。所以你的流水线对于前端项目,对于后端项目,对于这个APP客户端的项目,其实你是需要适配不同的发布流程的。所以这里面最重要的一点就是你的流水线一定是要具备这样灵活的,可按照业务场景编排的,而不是一个固定的三步走的方式,所以这个是流水线不要让它成为你发布的瓶颈。
那么想到这一点,其实核心还是在于原子化能力的建设。就是我始终觉得流水线平台它更多就是一个架子,在这个上面核心是什么?核心就是原子的能力,所以一个好的流水线平台,一定是可以支持原子能力的横向的无限的扩展,但是你整体的架构来说,是相对比较稳定的原子,所以这是一个比较良好的流水线应该承载的目标。比如对我们的系统来说,我们现在就可以去灵活的选择你的流水线,去编排里面的原子,每一个原子里面都是一个颗粒度最小的功能。
比如说下载代码,不管是前端项目还是后端项目,其实下载代码做的事无外乎大同小异。所以把这些基础能力识别出来之后,在流水线里面做编排,就可以实现了我面向一个业务场景或者面向一个业务流的一个交付流程的定制化,所以这个是流水线需要去实现的灵活配置的功能。
那么想做这个事,其实分成两步,第一步是标准化原子结构的定义。其实像我们刚才看到每一个原子和原子能力,其实你都要定义他的标准化的结构。为什么要定义标准化的结构,因为大家知道,每一个原子其实它的能力对外输出的可能是右边这张图上的一些参数,对吧,比如下载代码来说就需要地址,分支,这些点,什么参数,那这些参数会随着原子的能力不断迭代去不断升级,比如说,你的能力支持了一些新的功能,可能会暴露出来一些新的参数。如果你的原子能力所暴露出来的页面你是需要通过开发代码去实现的,那显然你每一次升级原子你的这个系统或者你的流水线平台就会跟着修改,这样显然是不合适的。
所以我们要做的是什么?就是定义一个标准化的原子结构。这个结构如左图上的显示,大家可以看到除了图里有的信息之外,其实就是一些参数信息,当你想要添加一些新的参数的时候,你只需要修改标准化的结构就可以。对于用户可见,右边的图,用户可见的交互界面来说,它是会通过你标准化的结构定义,自动渲染出来,自动生成,也就是说当你左边的原子定义里面新增一个参数,当我在系统上加载原子的时候就可以显示出来这个参数,这个就导致我们的流水线和原子定义足够灵活。所以这个不能写死在代码里面,而通过DSL方式去自动生成,这个是保证原子可以扩展非常重要的一点。
那么我们这样的一个平台,其实后边也是基于Jenkins在做,Jenkins大家比较熟,也不多说。那么想要做到灵活编排原子的流水线,我们要经历哪些阶段?其实我们自己在摸索和尝试过程中,其实也是经历三个阶段,简单来说。
第一个阶段叫做共享库,就是你用过Jenkins Pipeline 就知道,应该真得像右边的形式,生命式的语言,可以描述出来我整个交付的过程是什么样,那做第一步,原子其实什么是原子?你可以理解为在右边我用红框框起来的部分,这样的代码,其实就是代表原子能力,所以第一步要做的就是在你现有的流水线里面这些能力单独抽出来,放在共享库里面成为一个统一的方法,那你在流水线里面做的就是去调度这些方法,而在流水线的 Jenkinsfile 里面就不会有相应的实现。
那在这里就相当于把 Jenkinsfile 和具体的实现做一个结藕,首先做了第一级的解耦,那它的好处在于说你有了一些公共方法,比如说原子要升级了,你要修改一些代码,你是不需要把所有的流水线都去修改一遍,比如你有十条流水线,那你不需要把每个流水线都去做一些修改,你只需要把这些公共方法里边的实现做修改之后,其实这样对每个流水线可以自动生效,这是第一步,先把你的步骤抽离出来,成为一个共享库,成为一些方法。那至于说到底你现在的实现里面哪些可以成为原子?这个就看你整体的业务情况。这个其实我们自己可以灵活定义,如果一开始原子粒度很大,可以拆细的话,你可以做后续的一些拆解,这个没有关系。
所以第一步我们先实现共享库。第二步做的事就是结构化,因为在整个 pipeline 里面,其实相对来说还是比较局限的,比如说在步骤里面要实现的功能其实就是你现在写的这些功能,所以它并没有什么可扩展的余地,刚才也提到对于流水线来说其实它的可扩展性非常重要。所以第二步就做了结构化的工作,所谓结构化就是把之前的流水下做了更高层的抽象,所以简单的示意图大家可以看示意的代码,其实我们在流水线里面,除了通用的第二步,就是执行步骤之外,我们在前面和后面做了相应的扩展,比如说before这个阶段,其实里面可以定义一些数字化的动作,像after就可以做一些后置的处理工作,像qualityGates就是一些质量门禁的工作。
其实这些步骤来说,其实是对于整个原子执行能力的进一步抽象,你抽到执行不是简单执行这样的能力,而是抽象成一些更细粒度的步骤,所以如果我们想在原子的后面增加一些质量门禁的管控功能,那通过这样的更高层的抽象,其实你就可以快速实现这样的一些功能。其实这是对于流水线的第二层的净化,叫结构化,是一个结构化流水线,而不是简单的把刚才 Jenkins 里面的代码拿出来做一个方法。
第三步叫动态化,动态的流水线做完之后是什么样?就是这样,所以对于每个Jenkins里面就两行,所以你可以看到里所有的实现都是被屏蔽到了整个的原子设计里面去,所以这也是目前我们在做的事,一个目标,为什么做这个事?其实就是为了让整个流水线和 Jenkinsfile 做充分的解耦,所以所有的步骤其实都是动态去生成的,而不是像刚才预定义出来的,所以这一块可能比较细节,接下来可以请我们这边的架构师跟大家做进一步深入的分享,关于流水线应该怎么做才是比较高效。
刚才我也提到扩展能力,为了满足不同技术栈,不同发布需求,不同节奏的定制化需求,其实你不仅要设计原子,还要提供很多可扩展能力,像一些自定义脚本,这些比较简单,你可以自己执行一些脚本,比如说像自定义邮件,你可以去设计自己的邮件内容和标题,还比如说你可以定义一些自定义的HTTP的请求,是干什么?其实我们在做系统间打通,大部分情况都是做进口调用,所以其实大多数情况都在发一些HTTP的请求,所以当你设计比较通用的原子之后,当你想要跟任何一个系统,比如说接口交互的系统做交互的时候,你只需要去使用这样的通用的原子能力,去定义自己的head和body,然后去你的地址,这样的话就把这个跟系统之间做配置化的能力开放给我们的用户,他就可以去用相应的参数去完成系统之间的联动。所以这些都是在做流水线的可扩展化。
其实我们的工具能力还是要去结合一些具体问题,解决一些实际的问题,对于APP来说,我看了之前的也有人提,对于APP的发布有没有一些比较好的解决方案。其实这也是我们所面临的非常实际的问题,因为比如说像APP的发布,不像服务端,你把这个包或者镜像怎么样扔到服务器就可以生效,是自主可控的。但是对于尤其像苹果这样的生态系统来说,其实你的整个的发布过程是强制约于APPstore这样的平台,那么在以前是怎么做的?就是有专人去上传,在系统上上传应用,然后等着他去审核,等着他去生效。但是你知道苹果的审核是有时差的,而且也是有时间成本的,所以在没有系统支撑之前,基本上就是提交一个包到苹果平台,就等着收苹果的邮件,那什么时候苹果有邮件,你再进行下一步的操作,这个过程实际上非常烦琐。
所以为了解决这个痛点,我们做了一个自动发布的系统,那自动发布系统想解决的是什么?就是CD的能力。它能做什么事?包括版本的提交,自动版本的上传,然后自动状态的一些查询,系统会去查询整个苹果商店的通过appconnect?去查一些接口,去获取我们版本生效状态,然后去自动通知到人,比如说生效之后给人发一些信息,不用人再去等着。还能做什么?正式版本的提审,文案的编辑,还有一些预选操作,因为大家知道,你依赖外部系统的时候其实很多数据你是没有的,所以当沉淀到我们自己的系统上,所以很多预审被拒这样的数据我们可以积累到我们平台上去。那我们就可以在整个公司范围内沉淀整个被拒的案例,把它成为预审的自查的自检库,这些库对于一个企业来说是非常有价值的内容,因为大家知道像京东这样的公司不止一个应用,京东内部可能两百个应用。那所有的预审的操作,会沉淀到预审的自检库里面,其实每一个应用发布的时候都可以运用商城的一些经验去完成它的预审动作来提升过审的几率,所以这些都是系统去沉淀下来的非常有价值的内容,除了自动化之外,自动化也是很重要的步骤。
所以你可以看到当我们发布的时候其实非常简单,对于现在人们想去发布应用,只需要在系统上选择一个版本点击发布,剩下的交给系统做,每一个步骤其实清晰可见,而且每一个状态你可以看到就是什么时候开始,什么时候完成,这个对于我们去统计每次发版的整个时长,还有这个时长精细化的分布,做一些精细化的研发的一些运营,其实这些信息都是非常重要的,就是系统把它沉淀下来我们才能做相应的改进。
那接下来再提一些我刚才提到的工具,第三部分是什么?就是架构,对于一个超大型应用来说是百万行代码,一个百万行代码的应用你要去编译一次,这个时间成本会有多高。所以基本上对于大型公司来说,或者说对于一个普遍的解决方式,其实都是组件化,我们公司其实也有一些自己组件化的系统,组件化其实相当比较好理解,有点类似于我刚才说的流水线的原子化,它就是把一些通用模块做抽离,当我想去生成一个新的应用,只需要把这些模块组合在一起就会成为一个应用。这样做的好处在哪里?其实有很多,其中之一就是说我们在打包的时候,就是编译的时候,它的速度非常快,因为什么?因为每次不需要把这一百行代码都编译一次,因为很多都是二进制的组件,可以快速生成一个APP。
那对于一个App的创建来说其实也是非常简单的,再结合我们刚才提到的敏捷团队,敏捷团队每个团队都附着在自己的模块,这样的话其实大家工作就运行不备起来了。对于一个版本来说,其实我们要做的事其实很简单,就是有这样的表,这个表记录了里面有哪些组件,哪些组件的哪些版本,这些版本的一些变通说明是什么。首先会有这样的一个表格,这个表格就是传统配置管理里面提到的基建的概念,对于整个应用来说是通过一堆组件去集成出来的,对于这个开源方案有人提到有什么好的开源方案,像什么(38:05英)什么的都已经比较熟悉,我了解的一些业内大厂其实大多数也是基于这样的开源方案去做,所以你不妨可以去了解一下。
那带来的效果是什么?对于这样超大型的应用,我们去新搭建一个应用,之前内部起了一个新的应用,只需要一天就可以把这个应用完整搭建出来,因为全是复用质量化。对于编译效率,比如说对于我们的京东商城这样的大体量的APP,单次编译的话可能只需要一百多秒,不到两百秒,也就两三分钟这样的时间成本,就可以把这个包打出来,所以这些都是组件化带来的效果。
整个组件的过程,就是如图所示,它会包含几个部分:第一个是组件化系统,组件化系统里面会有公共组件库,还有业务组件库,还有工程配置库,这个工程配置库是啥?就是仓库里面的工程,工程描述,包括图表资源,包括证书配置等等,这些通用的配置,说白了就是一个架子或者一个壳子,但是这个壳子里面实际上是有一套工程的一些逻辑配置,在里面集成我们这些二进制的组件,就完成了整个应用一个数字化的过程。
那构建系统做什么事?做应用打包,签名证书的管理,还有一些安全加固。所以这些都是构建系统做。通过这两部分结合可以得到一些基础应用,基础应用再去打上渠道信息就成为了渠道包,所以基本上就是分成这么一个三阶段的步骤去完成,组件化系统,构建系统,再加上渠道发布系统,就可以实现对于APP来说整个CI/CD的过程。
那说完了第三部分,是叫做架构,第四部分是什么?就是环境。其实环境里面有一个非常重要的理念,叫做一切皆代码,这个大家比较熟,什么基础设施即代码,环境即代码,CI/CD也是代码,刚才提到流水线,包括Jenkins,其实它也是代码的一种形式。
那么对于APP的环境管理,我们要怎么做?其实我们的目标很简单,就是像管理服务器一样管理Mac机,大家知道,你这个苹果APP机打包的时候是强依赖于你的Mac环境的,因为苹果也不会支持你去做一些什么虚拟化这些东西,因为它要卖设备,那我们怎么管理 Mac 机,因为我见过很多公司基本上都是办公区里面一台笔记本,然后这台笔记上去打这个发布包,所以这个其实是现实,虽然听起来没有这么正式,但是其实在很多公司确实这么做。那我们怎么去像服务器一样管理Mac机,其实我理解几个大步骤:
第一个就是配置代码化,大家对这个图标都认识吧,所以整个Mac的环境,包括什么(41:07英),包括一些什么Python的基础包,所有的技术环境同样是通过 Ansible 去完成批量化的配置。所以这一点其实配置服务器并没有什么差别,只不过Mac机里面会有 Mac 系统的优化配置,所以总体来说还是通过Ansible统一完成的。
第二块叫做 VNC,为什么用到 VNC,因为我也知道,其实很多公司把Mac机放在办公区,其实也没办法,因为很多配置你是需要通过图形化尽量去做,你必须要有UI完成这个操作和配置。那我们为了提升这个效率,是把所有的 Mac 机丢到机房里面去,丢到机房里面的话一般情况下你就没有办法在用户界面交互,所以我们就通过VNC的方式,跳板机和VNC的方式实现了远程界面交互,这样一方面可以在公司机房里面享受这样的高带宽和安全网络的条件,另外一方面可以通过WINC的方式不去影响我对它的图形化的操作的需求。这是第二个。
第三个叫做长连接,就是Mac机其实也是挂在Jenkins上,大家知道Jenkins通过SSH方式长连接的方式,也可以通过就是短向连接的方式,所以我们采用的是SSH长连接的方式,这样做的好处显而易见,当你 Jenkins 重启或者怎么样的时候,其实它的连接是会自动重建的,如果你是用JNLP这种反向连接你是需要手动连接。当一个公司有上百台机器的时候,你手动连接那你直接就疯了。所以长连接是我们所推荐的一种方式,但是长连接其实要解决一些证书的配置问题,所以这些要解决之后就可以实现整个像服务器一样来管理Mac机。
那对于工具来说也是一样,对于很多系统来说,我们所有的工具都是统一配置的,但是对于不同应用来说,它的应用版本其实不一样,尤其像Xcode这种东西,每次升级都是很复杂的一个过程,对于不同应用可能会选择不同的分级节奏,所以对于这些用户可见的工具,我们都会提供一些在线的配置化,所以所有的环境是一套标准环境,当你在执行的时候,运行这个任务的时候,它会去获取你这个工具的需求和配置,然后自动完成这个工具的初始化,来匹配你这个应用或者技术栈所需要的环境要求。所以这些都是在去做的一些工具版本动态化的支持,包括像JDK,Xcode都是可以支持,尤其像(44:07英),这些工具其实都是可以支持手工配置的,所以这样的话其实把我们整个Mac资源变成一个资源池,它不再是说这台机器专属于发版,另一台机器专属于调试,动态化就可以实现资源池。
最后一点其实就是证书的自动化管理,大家知道对于像 ios 平台来说,这个证书体系是一个非常庞杂和复杂的体系,包含很多部分,像证书描述文件,还有一些属性文件,这里不一一念了,为了屏蔽这样的复杂证书配置成本,我们要做的就是多样的配置,所以在使用的时候就用到了Xcconfig 这样的方案,这个是Xcode提供的方案,这个方案就可以实现多证书的自动化配置,通过把这些功能一些能力整合到系统上,就是右边的图,可以看到在系统上你可以选择导出包是什么样的类型,你的证书是选择哪些证书的方案,所以结合了整个和一些ID就可以实现我们整个配置,就可以在线化,就不用在人工手动选择证书,再配置证书,这些的话其实都搬到线上完成,就可以简化整个环境管理的复杂度。
所以总结一下,其实想要做到移动APP的持续交付分为四个部分,流程、工具、架构、环境,指导思想就是流程标准化,工具流水线要原子化,架构要组件化,环境配置化,所以这也是我们的一些经验和总结。那时间有限,我们抓紧进到第三部分。
可感知的持续交付,因为我做这个 CI/CD 也挺长时间,之前在很多公司做的时候也更多会关注于工具和CI/CD本身的实践,但是其实你在公司做的时间越长,你会发现你的持续交付是不是能去做到可感知的,什么叫可感知?就是说你的这个效率的提升一定是人肉可见的,大家可以有目共睹的,而不是自己在PPT或者在邮件里面可以说出来的,所以CI/CD虽然是一个理想国,比如说大家都知道,持续交付会有这样的阶段,其实你看这个东西,你是没有办法落地的,你没有办法只看这样的示意图就实现持续交付的落地,所以肯定是一个体系化的过程。
所以我想跟大家说的就是我们在做持续交付的过程,最重要的就是结合场景,比如说刚才提到的IOS的自动发布的场景,然后我们再去梳理流程,做工具平台,这样才能解决实际的问题,而不是说我们每天再去说我们要做持续集成,但是研发又没有直观感受到持续集成带来的好处,这跟你去推行持续交付和落地持续交付来说其实是会带来非常大的阻力,而且现在大家也发现,远程办公而且对经济形势的影响,其实现在对整个研发生产力的关注点是越来越重要,所以在内部其实不管是测试团队也好,运营团队也好,大家是在做一个合作共建的过程。而且我发现一个特别明显的趋势,我们在做集成答辩的时候,其实每个人都会提效率,效率这个点是每个人都绕不过去的一个。
所以这也是为什么我们想去组织这样的CD的在线活动,大家感兴趣也可以了解一下,就是所谓的CD FOUNDATION它到底要做什么,它里面提供出来的一些服务到底是什么,这个是大家可以去下面自己去了解一下,我不在这里多说了。
最后其实就是再给大家分享一句话,这是我们去年年会,京东商城的CEO徐雷总,给我们说的一句话,叫做在成就他人的过程中收获自我成长。其实我是个人非常认同的,像我们做这些内部提升效率来说,其实我们最核心的目的就是成就他人,成就我们的团队,所有人提升自己的技能,因为在成就团队的过程中才能收获实际的场景来解决实际的问题。还有一些给大家推荐的书,这个都是我觉得做持续交付,如果你对持续交付比较感兴趣,应该都是一些必读的书,不在多,而在精,大家可以关注一下。时间刚刚好,感谢大家的聆听,我一个人对着电脑讲半天,也没有得到任何的反馈,所以有兴趣的话可以加我的微信,可以深入交流。下面是我之前写的一个专栏,感兴趣的话大家可以扫码查看,我的这个分享主题内容就到这里。