理论派 | Theory
网易CI/CD实践(上):CI系统的技术选型与部署流程
云计算的普及,不仅改变了目前的IT基础设施与企业系统架构,同时也改变了技术团队的组织架构和企业内部的研发流程。而持续集成(CI)和持续交付(CD)就是企业内部研发流程提升交付效率的关键。
CI/CD的核心价值是效能与质量。效能提升的关键在于自动化,它包含了两个方面:一是整个软件研发流程自动化,降低人力成本;二是CI/CD平台在业务接入、资源管理、线上支持、问题排查等诸多方面实现自动化,从而减少技术支撑方面的成本。而质量保障,一方面是研发质量,需要提供相应的质量检查与测试工具;另一方面是过程质量, CI/CD平台需要能够持续采集研发流程中的指标数据(如交付频率、交付周期、交付成功率),建立起一个完善的质量度量体系。
目前各大公司的CI/CD平台,在工具选型、落地实现等方面各有不同,此次InfoQ采访到了网易杭州研究院高级产品开发工程师汪灿丰和高级服务端开发工程师梅光辉,他们分享了网易轻舟在CI/CD方面的实践。由于干货内容太多,我们将这次实践分为了上中下三篇内容,分别介绍网易的CI实践、CD实践、测试自动化及API版本管理。
网易CI/CD实践的背景
据了解,网易的大部分互联网产品业务团队都是使用统一的平台来进行CI/CD实践,目前平台上运行着数万个仓库,活跃仓库近万个,同时平台内还有大量副本数超过数千个的服务,这些服务每天承载着业务方大量的访问。
为了适应业务发展的节奏,网易内部广泛推行了敏捷开发,每天通过平台发布应用的次数达到数万次,产品迭代节奏快,交付周期短。所有业务使用统一的平台进行CI/CD,无需各自搭建,降低成本,使用统一的规范,避免了相同问题的多次采坑。
网易公司内部的CI/CD实践主要是轻舟CI/CD平台,该平台提供了可视化的流水线编排界面,一次配置,多次运行,支持团队成员共享配置。每次提交或者合并代码都会自动触发流水线的执行,自动将代码发布到环境上。数据显示CI/CD流水线相比传统的手工或脚本方式平均效率提升了5倍以上,发布效率提升了8倍以上。另外通过整合多种自动化测试工具帮助业务方实现高质量的集成。通过可视化度量平台从多个维度了解构建,部署的相关指标数据,帮助产品提高发布效率。
之前,网易内部有一套从主机部署时代发展过来的自动化部署平台,但是其对容器部署的支持不友好,部署之前需要先在服务器上部署agent,注册到内部CMDB,再下发指令执行。这样的执行操作注定了这个平台在大批量部署场景下会存在性能瓶颈。
基于原平台存在的性能问题,以及对业务容器化、微服务化演进的判断,网易研发了新的轻舟CI/CD平台,成为了网易云原生技术栈的重要组成部分,满足云原生环境下企业在能效、团队协作效率、产品迭代速度等多方面的需求。
在使用体验上,轻舟CI/CD是一体的,但是在系统架构设计方面,其实是分开的。下面,我们就分别来讲讲CI和CD的系统设计。
网易CI实践的整体架构及工具选型
与绝大多数互联网公司一样,网易内部各业务方的持续集成也大都是由研发团队的QA负责的,CI工具选择了比较常用的Jenkins,同时在流水线的上下游整合了其它的主流CI工具。整个流水线平台依托于Kubernetes,基于K8s的CRD(自定义资源)重新设计了流水线上层模型,并通过Operator驱动流水线执行过程。
当流水线触发一次执行时,将会产生一个PipelineRun对象,Operator将会根据对应的流水线预先定义好的阶段生成对应的Job,然后通过Jenkins的API触发Job执行。Job执行完成后,将会通过Webhook回调上层服务接口,将状态回写到PipelineRun中,然后触发下一个阶段的执行。
网易CI系统整体架构
CI工具选型
传统的持续集成实践本身就很占资源,编译构建对磁盘、CPU,甚至是网络都有一定的要求,如果在高峰期想要保证持续集成任务能够及时运行,通常需要预留大量的构建机资源,这不仅会导致资源浪费,同时也需要更多人力来维护管理,成本会很高。
所以,网易技术团队在进行CI工具选型时,就直接圈定了4个当前主流的工具,分别是Travis CI、Circle CI、GitLab CI和Jenkins,并详细对比了4个工具。
其中,Travis CI、CircleCI在Github开源项目中使用较多,但不支持私有化部署,不适合公司实践;GitLab CI可以与代码仓库无缝集成,且天然支持GitOps,但整体生态目前并不成熟,需要自己制作builder的镜像,并与Gitlab深度绑定;Jenkins作为传统的CI工具,社区和生态都比较完善,Jenkins 2.0版本提供了Pipeline as code的特性,可以将CI过程纳入版本管理,支持GitOps。此外,Jenkins社区也诞生了kubernetes-plugin这样的插件,可以将流水线的执行从传统的物理机转移到容器中,再依托Kubernetes强大的调度能力,就可以实现资源的动态调度和编排。
基于以上原因,网易轻舟最终选择了Jenkins,但是传统的Jenkins在系统运维、资源管理、使用方式等方面,存在很多问题。例如,Jenkins的master-slave架构比较经典,但由于诞生时间较早,所有配置和数据都是基于文件存储的(存储在Jenkins master节点home目录下),修改时,会先更新内存,然后异步写入磁盘,而当底层文件被更新时, Jenkins并不会自动reload更新后的数据,因此,很难做到高可用;Jenkins master实例对文件目录是独占的,不同Jenkins实例也无法共享底层存储…因此,网易技术团队希望能够在传统Jenkins版本中做出以下改进:
· 结合Docker/Kubernetes云原生技术栈,解决传统Jenkins使用中的痛点;
· 通过将业内最佳实践固化到产品中,解决易用性的问题,降低用户使用门槛,提高接入效率;
· 重新设计上层流水线模型,提供更加强大的流水线编排调度能力;
· 自研流水线底层组件,替代Jenkins插件,提供更加灵活的扩展能力,方便与公司内部系统进行集成;
· 提供丰富的企业级特性(如认证、鉴权、审计、告警、通知等),满足企业客户需求;
除了Jenkins,网易轻舟在整个流水线的上下游也整合了其它的主流CI工具,例如:
· 代码仓库:支持Git/SVN,可以适配绝大多数代码托管平台,并且对Gitlab做了深度适配,例如,支持从Gitlab Webhookpayload中提取各类参数;
· 代码扫描:集成了SonarQube,支持了所有主流的编程语言;
· 单元测试:整合了Java中常用的Jacoco工具,方便用户在运行单元测试时,生成对应的UT和覆盖率报告;
· 代码编译:Java支持了Maven/Gradle,并且内置了Nexus私服,方便做内网代理;Node.js支持了Npm; Golang支持了go mod缓存加速;
· 镜像构建:支持Docker out of Docker、Kaniko两种构建方式,用户可以根据自身需求选择使用;
· 镜像仓库:整合了Harbor,支持Harbor webhook,并且集成了Harbor的镜像扫描和镜像复制功能;
· 容器部署:支持kubectl原生部署、升级,以及轻舟CI/CD应用部署等多种部署方式;
· 自动化测试:支持Java语言常用的TestNG,同时整合了网易内部的GoAPI测试平台,支持在流水线中运行指定的接口测试集,并在执行时输出测试报告;
· 告警通知:集成了邮件发送、短信告警、网易POPO等多种通知方式;
据了解,目前国内大部分公司对Jenkins的使用方式依然停留在1.0的时代,很多人都还在使用Jenkins的UI配置方式,并没有使用到Jenkins 2.0提供的Pipeline as code功能,并且在使用场景上,大量依赖一些自定义脚本,这些脚本通常由QA同学事先预置在机器上,一旦机器出现宕机或故障,迁移起来成本也很高。相较之下,选择更新版本的Jenkins,使用更前沿的功能,并适时辅以其它CI工具,往往会有更好的效果。
网易CI实践的分支管理与协作流程
所有CI实践的源头一定是代码变更,好的代码分支管理和版本变更规范是做好CI实践的前提。网易轻舟是基于GitFlow进行代码管理和协作流程的,主要的阶段包括预发验证、测试验证和代码审查、集成、验证。
网易轻舟CI实践中的主要分支有devlop和master,辅助分支包括feature/*、release/v1.x.0、hotfix/v1.x.1。
· develop:集成分支,不允许commit/push,仅允许来自feature/*或hotfix/v*分支的合并
· master:版本分支,不允许commit/push,仅允许来自release/v*或hotfix/v*分支的合并,每次接受合并后必须在其上创建TAG
· feature/*:功能分支,从develop派生,不允许来自develop的合并,合并到develop后删除
· release/v1.x.0:发版更新验证分支,从master派生,派生时根据master分支TAG标记并递第二位版本号命名。不允许commit/push,只允许来自develop的合并,合并到master之后删除。
· hotfix/v1.x.1:补丁更新验证分支,从master派生,派生时根据master分支TAG标记并递增第三位版本号命名。允许commit/push,不允许来自develop的合并,合并到master后必须再合并到develop,合并后删除。
除此之外,关于TAG,网易轻舟也有一些特定要求:
· v1.x.0:发版更新,release/v*分支合入master后,在master分支上创建。
· v1.x.1:补丁更新,hotfix/v*分支合入master后,在master分支上创建。
· 此外,为了保证代码合入的质量,我们也制定了对应的代码review原则:
· 任何代码变更都必须提mr,不允许直接push到dev/master等保护分支;
· 任何变更至少必须有两名团队其他成员review过,才能合入develop、hotfix分支,只有被团队接受的代码才是团队的代码;
网易CI流程的具体步骤
通常,一个持续集成流程会包括以下步骤:代码检出、单元测试、静态扫描、编译、构建、镜像扫描和测试部署。好的持续集成流程一定是面向质量的,所以,在实践过程中除了工具和流程,还需要做好代码质量相关的工作。
对于大部分团队来说,CI可能是由QA维护的,因此在实际使用过程中,会将线下环境的CI和线上分离开,线上通常更加注重持续部署,主要由QA、PE等角色负责,流程上会简化一些,更加注重运维规范、上线审核。
代码检出:通常需要在流水线中配置代码源、ssh秘钥以及代码分支等信息,为了优化代码检出性能,CI/CD流水线会采用的git浅拷贝的方式来加速整个过程。
静态扫描:这是流水线至关重要的一环,运行时会将扫描的数据上传至用户预先配置好的SonarQube平台,并且通过SonarQube的QualityGate进行质量卡点,除了QualityGate,用户还可以自定义一些流水线特有的卡点规则,并且配置通过邮件、网易popo等通知执行结果。
单元测试:这是CI过程中必不可少的一环,CI/CD流水线整合了常用的Jacoco工具,方便用户在运行单元测试时生成对应的UT和覆盖率报告,报告的内容可以在流水线执行详情页查看,同时支持用户设置单元测试通过率、UT覆盖率卡点,并发送相应的邮件通知。
代码编译:支持大部分主流的编程语言,比如Java、Node.js、C++、Golang等,并且针对各类语言做了相应的编译加速方案,支持Maven、Gradle、C++、Go mod构建缓存。
镜像构建:支持Docker out of Docker、Kaniko等多种构建方式,同时整合了网易轻舟Harbor,集成了Harbor的镜像扫描功能,支持在流水线运行过程中执行镜像扫描、查看镜像安全报告,同时支持安全项卡点以及邮件通知等功能。
集成测试:CI/CD流水线与网易内部自动化测试平台GoAPI做了集成,用户可以预先在平台侧配置好相应的接口执行集,然后在流水线中选择对应的执行集执行,并在流水线详情页中查看执行集的通过率,同时支持卡点以及邮件通知。
流水线触发器:多种触发器,比如定时触发、PollSCM、Webhook以及流水线串联触发,其中Webhook还额外提供了对Gitlab、Harbor的支持,支持从Gtilab、Harbor的payload中提取相关参数,并在流水线阶段中使用。
采访嘉宾简介:
汪灿丰,网易杭州研究院高级产品开发工程师,专注于云原生以及DevOps领域,目前主要负责网易轻舟CICD的研发工作。
梅光辉,网易杭研究院高级服务端开发工程师,目前主要负责网易轻舟CICD研发工作,在云原生以及容器DevOps领域有过深入的研究和实践。