云CI ZUUL应用方案系列(3)方案设计

每天读一篇一线开发者原创好文

DevOps微课系列旨在帮助用户学习DevOps实践。

1.方案框架

OpenStack CI典型的基于ZUUL框架的通信机制图如下:

开发者提交变更到Gerrit代码库后会产生Gerrit事件流,ZUUL会侦测相关事件并进行相关处理(比如准备变更测试的临时代码库),然后通过GearmanServer分发任务到Jenkins Master,Jenkins Master再分配节点进行任务执行,任务执行完成后执行结果再原路返回给Gerrit,形成闭环。

2.基于云CI的ZUUL方案框架

考虑到与现有云CI的兼容,基于云CI的ZUUL方案与OpenStack基于ZUUL的CI框架基本一致:

ZUUL-SERVER、ZUUL-MERGER、HTTPD(APACHE)和Jenkins Master封装在docker

里,作为一个实体存在,而Gearman Server则内置在ZUUL-SERVER中;项目配置(包括ZUUL配置)均挂载到容器内,实现业务逻辑与配置分离。

数据流如下:

① 用户提交代码到Gerrit

② Zuul侦听到项目gerrit代码库变更事件

③ Zuul Merger/HTTPD准备临时的变更代码库供后续测试

④ Zuul通过Gearman Server给Jenkins Master分发测试任务

⑤ Jenkins Master分发任务到Slave执行

⑥ Jenkins Slave下载临时变更代码库执行测试

测试结果再逆向返回给Gerrit形成闭环:Jenkins Slave >Jenkins Master>Zuul->Gerrit。

3.关键问题及解决

1) ZUUL与Gerrit保活

Zuul运行一段时间不时出现无法接收Gerrit事件问题,确认系Zuul与Gerrit保活导致,需要增加保活配置,修改zuul/connection/gerrit.py文件。

详情请参考:https://review.openstack.org/#/c/238988/

1) SSH保活

目前的云CI集群都是基于TECS2.0的,前期碰到SSH保活相关问题,排查确认需要应用层自己配置SSH保活参数,因此Jenkins Master的docker镜像中需要配置SSH保活参数。

修改server端的etc/ssh/sshd_config

① 修改client端的etc/ssh/ssh_config

Slave镜像如若用到SSH,也需要按上所述进行配置。

1) 先有鸡还是先有蛋

由于Mesos的资源调度是先有资源需求后Mesos才会根据需求动态分配资源,而Gearman的调度是先有资源了才会进行任务分发,因此这里存在"先有鸡还是先有蛋"的问题。

考虑以下几个方案:

① Jenkins上死循环执行一个空JOB

② Jenkins周期性(50s)执行一个空JOB

③ ZUUL设置触发JOB,该触发JOB限定在master上执行,通过该触发JOB的子JOB来执行实际的任务

经测试,结果如下:

方案a: 不会触发,Gearman调度框架只会识别空闲资源才会进行任务分发

方案b: 任务只会在该JOB所在的节点上固定执行,再多的任务需求Mesos也不会额外分配资源,无法满足并发需求

方案c: 满足需求

通过方案c可解决"先有鸡还是先有蛋"的问题,将master从节点个数设置为多个可满足并发需求,master上的触发JOB什么都不干,只是起触发器作用,后续如若有性能瓶颈,再考虑其它解决方案。

2) 只能触发一次

Jenkins Master上电初始化后会通过Jenkins Gearman Plugin创建Worker,并向Gearman Server注册相关Jobs信息。在Jenkins页面任何配置变更时,Gearman plugin都会重新注册Jobs信息。

经测试发现,在Jenkins Master启动后,Gerrit首次触发正常,后续均不能触发,且Jenkins收不到构建任务。经分析,在首次触发新分配的mesos节点在完成任务释放后,Gearman Server的worker注册Jobs信息全部清零,因此后续触发时Gearman认为无Job可以执行。

分析Gearman Plugin插件代码,发现有一处代码可优化解决该问题,该处代码的逻辑会导致在mesos节点完成任务执行释放后将Gearman Server上的Jobs注册信息全部清零。优化修改后问题解决。

src/main/java/hudson/plugins/gearman/ExecutorWorkerThread.java

4.ZUUL配置

ZUUL配置问题主要集中在zuul.conf和layout.yaml,zuul.conf主要针对zuul的一些账户信息的配置,layout.yaml主要针对gerrit工程与jenkins job关联触发关系的注册,需要将这两个文件的配置修改可视化出来。

经过分析zuul.conf中的配置只需要配置Gerrit User信息即可,其它信息都可以根据相关信息动态生成;layout.yaml可全部呈现出来,方便用户修改。由于这两个文件是ZUUL的核心配置信息,且ZUUL未提供配置reload渠道,这两个文件修改后需要重启ZUUL相关组件以重新加载载配置信息,因此这两个文件的修改不应过于频繁。

考虑到Jenkins上已有Gearman Plugin插件的配置,可以将ZUUL配置和Gearman Plugin配置放到一起,通过修改Gearman Plugin代码,增加相关配置满足需求。

配置情况如下图所示:

ZUUL配置请参考: http://docs.openstack.org/infra/zuul/zuul.html

5.Master从节点个数变更

采取如上5.3方案时,在需要增加项目并发度时可修改master从节点数目,但是修改maser从节点数目后Gearman Plugin/Server并不会感知,需要有个途径通知Gearman Server进行数据更新,因此考虑通过修改Gearman Plugin代码探测master从节点数目变更,然后由Gearman Plugin发起数据更新。

6.项目账号隔离

通过在Mesos Sand Box里识别该项目账号所在虚机的GID/UID信息,基于源ZUUL镜像创建项目账号生成该项目账号的镜像,然后在执行docker时以该项目账号执行,完成项目账号的隔离。

7.方案应用

基于ZUUL框架的云CI通过制度化的流程保证提交正式分支的代码质量,其核心是支持异地协作、多人并发修改代码及提交评审,并进行事前的逐单验证,确保主干分支绝对安全。主要流程:

① 开发者发起git review

② 触发Verify CI

③ 代码评审

④ 触发Merge CI,如果通过则Merge到正式分支

其中步骤①)和③是人工完成的,其它步骤依托ZUUL+云CI自动化完成。 目前该方案在CMS、Netnumen、5Gran、AIP项目落地实施,项目反馈较好,再也无需担心并发多单依赖问题了。 项目上线该方案也较简单,只需四步走:

① 项目发起申请,并准备好业务镜像(在原有业务镜像上安装Zuul Cloner组件)

② 起项目云CI实例

③ 项目配置Zuul参数:Gerrit User和Zuul Layout.yaml

④ 项目增加job配置,提交代码变更到Gerrit代码库,全流程测试通过

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180319B15ZRQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券