
07 爱奇艺研发工具链实践
作者介绍
赵慰 爱奇艺基础架构部门容器云及工程效率负责人,全程参与爱奇艺私有PaaS和研发工具链建设。
案例综述
伴随着微服务、DevOps、上市审计、新业务孵化等浪潮的出现,爱奇艺研发团队在工程效率方面遇到了极大的挑战。借助工具提升迭代速度、保证研发质量、规范交付流程是每一个研发团队的期望,但是在现实生产中,并不是每个研发参与者对工具的了解程度都足以支撑以上目标。因此,开发一个提供功能丰富、便捷易用、适配私有基础架构的研发工具链服务,成为一项迫在眉睫的任务。
基于此,我们要解决的核心问题如下。
1)确定工具链的研发目标。
•是遵循传统的项目管理理念、流行的DevOps,还是在工具层兼容。
•分析研发现状,寻找痛点,确认重点提升方向。
•确定提供工具链服务的形式,是纯方案,还是要用到实际的工具。
2)选择一套适合自己的工具链。
•分解工具链的关键环节。
•常见研发工具的分析与抉择。
3)如何完成研发与推广工具链。
•研发路线如何确定。
•具体任务的分解。
•如何让工具链适配研发团队,真正发挥作用。
案例实施
1.工具链的研发目标
(1)DevOps与工具链的关系
DevOps是如今最流行的研发流程管理理念,它本身没有描述具体的实现方法,仅仅是一种理念,我们可以找到基于这个理念的实践经验。从字面意思来讲,DevOps关注的是开发(Development)与运维(Operations)之间的协作,而从广义的角度去看,我们需要关注并尽力消除所有研发环节间的隔阂。和很多经典的管理理念一样,DevOps对参与者也有着自己独特而苛刻的要求,甚至会涉及大规模组织结构调整和职能角色的变更。在业务优先的研发体系中,严格遵照这套标准实施的难度显而易见。
虽然全盘落地DevOps山高路远,但从工具链的角度来看,我们可以从结果出发,吸纳它的优势,先行一步。DevOps支撑了研发项目的工程性(流程规范、质量可靠)与效率性(快速、高频),其闭环之所以能够顺畅流转,主要得益于各环节之间的高效、精确对接,减少人为因素带来的不确定性与等待,主要包含:精确的研发状态描述(产品状态、需求状态、开发状态、测试状态、运行状态)和优秀的状态流转效率(流转速率、流转可靠性)。
因此,工具链有两个目标:将每个环节自动化与减少环节间不必要的人与人沟通。确定了目标之后,接下来我们就要从现状出发,将目标具象化。
(2)分析研发现状
在《极客与团队》一书中,前Google工程副总裁Bill Coughran留下一句至理名言:“工程问题都很简单,人际关系才是最难的。”诚然,这句话中的“人际关系”并不是在描述研发流程中合作者之间的关系,但是今天用来描述这些也未尝不可。
许多公司可能面临着和我们同样的问题,项目参与人员越来越多,职责越分越细,效率却越来越低。其中有几个突出问题:
•项目负责人或项目经理人工追踪流程状态,精力消耗大,错误率高,人际关系紧张。
•职责边界不明确,常有跨环节沟通,互相无法理解的情况。
•关键概念未对齐,各角色对整个流程的理解如同盲人摸象。
这些问题一旦引发故障,将会逐渐引发团队内部的互相不信任。这些负面因素日积月累,轻则导致每个人做任何关联到他人的事情时都需要反复确认,浪费大量时间,重则将团队割裂,脱离正轨。人为强调文化、强调流程只能降低错误率,若是能够通过工具保证流程,便可从根源上杜绝问题。
从对业务的直接影响来看,重要性或者错误代价依次为上线行为>产品行为>测试行为>研发行为。但从自动化需求或对自动化接受的程度来看,排序却恰恰相反,即研发行为>测试行为>产品行为>上线行为。显而易见,越重要的环节,策略越保守,这也为工具链不同模块的设计实现提出了不同的要求——优先保证方便易用或者优先保证精确严谨。
在业务优先的大原则下,让人去适应工具显然是不可行的。这就对工具链提出了更高的要求:如何在保证工具性能的前提下,让工具去适应每一个研发角色,去适应工程能力参差不齐的研发活动参与者。
(3)工具链的服务提供形式
目前市面上的DevOps工具数不胜数,几乎所有传统或新兴的研发工具都在向覆盖全流程的方向迅猛发展。在这样的环境中,工具链服务应该以怎样的面貌呈现在研发者面前,是一个非常有趣的问题。可以做布道者,将一个先进开源的工具交给业务线,让其自行解决,可以选择一个工具全盘托付,也可以按最佳实践找几个工具拼凑成一桌“满汉全席”,又或者尝试背起历史包袱负重前行。
结合公司研发体系的现状和历史积累,我们最终选择了一条遍布荆棘的道路——将开源和商业版的工具与自研工具结合起来,搭建一条覆盖产品研发全流程的工具链,并尽可能尊重开发者现有的使用习惯。以经典的SWOT方法分析,可以得出如下结论。
•优势(Strength):深度集成私有基础架构;深度集成私有项目规范;专业支持,共享资源;扩展性和成本优势。
•劣势(Weakness):脱离业务线,过于理想;难以完全支持每个工具的灵活性;容易偏离开源标准。
•机会(Opportunity):大量小项目缺少工具化流程管理;微服务拆分,项目孵化,迭代频率升高;IT审计规范。
•威胁(Threat):迁移成本,存在自建的工具的可能;部分开发者厌恶严苛的流程;开发者期望过高导致的心理落差。
2.工具链架构选型
前面提到,可供选择的研发工具灿若繁星,有的历史厚重、积淀深厚,如Jenkins;有的英姿勃发、风头正劲,如Docker。爱奇艺是如何选择的呢?
(1)工具链关键环节分解
如图7-1所示,我们将研发流程分解为如下状态节点和状态转换节点的合集。
这样拆分的原因很简单,这些都是研发数据实实在在的流动路线,也是工具唯一能理解的东西。工具和人的区别就如同硬件和软件,工具的优势是固定、精确,缺点也在于此,它不能理解自己在做什么。举个例子,工具无法理解我们所讲的“将需求F上线”是什么意思,因为这是人想象出来的,实际存在的过程是,需求F涉及代码库R,因此对R来说需要有一个开发任务T,开发完成后用来上线的是R的一个完整代码分支B构建出的产物P,最终产物P上线,使得T的状态变更为上线完成,从而继续向上传递到F的状态变更中。
图7-1 研发流程分解
需要强调的是,这里分解的是底层数据流转,绝非工具链服务整个产品对开发者应该展现的形态。产品层面还要做更多贴近使用场景的封装。
(2)工具分析与抉择
选择哪些工具通常取决于四个方面,按重要性排列依次为基础设施、知识积累、规模、兼容性。基础设施直接限定了工具的选择范围,而知识积累决定了其中哪些工具能发挥出最大的作用,这两项是必须考虑的因素,规模在可用性方面带来挑战,扩展能力差的工具不太适合大规模应用,而兼容性则更多与基础架构演化相关。
爱奇艺内部的研发工具链伴随着基础设施的演进,呈现出不同的形态,也逐渐覆盖了越来越多的环节。在这个过程中,我们也走过很多弯路,吸取了不同程度的教训。首先,在2015年我们过早地推进Pipeline as code模式,忽略了基础设施和研发团队知识积累的严重不足,错过了大规模协同CI/CD工具的机会。其次,我们过于集中于Docker,但Docker实际只解决了最后一步的问题,反而由于Docker镜像的封闭性,导致本已杂乱的基础环境更加难以统一。最后是一个看起来无关痛痒但实际很严重的问题,各种依赖的公共仓库未统一,私服泛滥,包管理规则互相冲突,这直接导致后续统一构建环境、运行环境的工作寸步难行。
在进行最近一次工具选型时,我们从上述四个方面进行了考虑,为各个状态和状态转换过程挑选合适工具,其中涉及的主要因素如下所示。
1)基础设施。
•Gitlab基本统一。
•运行时管理混杂:PaaS占50%,IaaS(部分团队自研、人工)占50%。
•监控:公共监控报警拨测工具,少部分团队自研。
2)知识积累。
•副本集与配置管理:基本接受。
•Pipeline/Infra as code:接受度较低。
•云原生与Kubernetes:兴趣较高,基础设施支持不够。
3)规模。
•几十万实例。
4)兼容性。
•历史包袱:CI/CD工具混杂(公共GitlabCI、大量私有Jenkins、人工)。
•未来发展:混合云、Kubernetes、云原生。
最终我们在诸多工具中选择了Jira、Gitlab、JFrog Artifactory和Docker Registry,自研持续集成、交付、部署工具和DevOps Dashboard,并集成在已有的IaaS、PaaS、监控系统上。
3.工具链研发与推广
(1)研发路线
基于上文所述的规划和研发过程中的痛点,我们制订了自下而上的研发路线。底层工具链包含两部分,一是从代码开发到产出物交付,二是上线与运行状态管理,二者由规范的产出物仓库衔接。上层以统一的DevOps Dashboard展示,将各个系统中的信息串联展示,再附加尚在规划中的产品流,组成一个完整的工具链,如图7-2所示。
每个工具在工具链中承担着不同的职责,在开发时便有着不同的侧重点。下面将一一做简要分析。
Gitlab承担代码托管和Code Review功能。它是直接与一线开发者交互的窗口,也是整个开发层面的起点,Gitlab的服务质量是整个研发系统的命门。由于Gitlab本身的架构扩展性有限,因此只能尽量从系统本身和诸多依赖的优化着手,此外,还要限制不规范的使用方法。另外,代码库也是每个互联网公司最重要的资产,代码数据安全是重中之重。在Code Review方面,相对Gerrit等系统,Gitlab开源版提供的功能几乎可以忽略不计,需要进行一些二次开发。
公司内部使用的语言、工具种类繁多,产出物仓库在工具链中起着承上启下的关键作用,因此我们采购了商业软件JFrog Artifactory快速完成支持。这里我们只需要注意一点,管理规则一定要严格,绝不可向随意的包命名习惯妥协。
图7-2 完整的工具链
对于CI/CD工具,最关键目标是易用,将用户从纷繁复杂的工具维护、语法学习、权限配置等工作中解放出来;其次是与内部系统完美集成;最后,要尽可能提升可用性。
我们基于Jenkins Pipeline研发了QCD(iQIYI Continuous Delivery)作为持续集成交付工具。除此之外,还开发了一套插件化的流水线编排系统,支持用户自定义发布流程。其基本的任务类型包括构建、脚本执行、远程调用、上线审批、子流水线等。
(2)应用推广
1)解决痛点
时至今日,为自己参与的研发项目配置工具,仍然是一个颇具个人英雄主义色彩的行为。除非万不得已,大多数参与者都不愿意对已有的配置做哪怕一丝丝的改动。因此,我们需要做的是抓住业务线的核心痛点,给出一套完整的解决方案,而不是单独地推进某一个工具。
在爱奇艺内部,粗略地将项目分为大型项目(对外的业务系统等)和小型项目(内部系统、孵化项目等)两种类型。前者的痛点在于部署环境的管理和流程管理复杂,一旦出错影响很大;后者的问题在于人力不足,经常需要一个人维护多个服务,因此解放人力是第一位的需求。针对不同的项目,我们要寻找不同的切入点。
2)工具实现流程
流程仅仅是一个虚拟的过程,真正需要做的,是把工具一个一个放进去并串联起来。由于开发者并不会有足够的耐心研究工具(尤其是完全不了解的自研工具),因此,帮助业务线分解流程串联工具的工作也是必要的。在此基础上,可进一步归纳出常见模板,供类似场景直接复用。一个简单的流程分解如图7-3所示。
图7-3 工具实现流程
3)文档支持
文档很重要,但几乎没有人去看。这是一个残酷的事实。白皮书也很重要,可以拿来复用的成功案例和模板更加重要。
案例总结
1)兵马未动,粮草先行:基础工具不能因为没有明确的需求而一再推迟,实时关注最新进展,走在用户(业务团队)前面。
2)与基础架构相互促进:向开源标准、公有云标准靠拢,用社区的智慧减小维护成本。