编者按:据统计,在上周结束的OpenStack温哥华峰会中,关于CI/CD持续集成和交付的议题超过40个,CI/CD成为了整场峰会最热门的话题之一。而Zuul作为CI/CD模块中耀眼的明星,被大家所熟知,在本次峰会上更是引起了业界高度关注。在这里小编将简单介绍下Zuul,包括Zuul 的CI简单流程图、组件及架构等。
什么是Zuul
随着OpenStack持续集成的推广,基于OpenStack开源项目的性质,项目大,全球各地的开发人员多,变更提交频繁。Jenkins不能解决并发多、单依赖的问题,拉长了问题反馈时间。为解决该问题,源于OpenStack开源社区的基于ZUUL框架的 CI方案出现在我们的视线中。
CI简单流程图
Zuul组件及工作流程
为了更好的理解什么是Zuul和Zuul到底是怎么工作的,需要介绍一下Zuul有哪些组件。
Zuul整体架构
Zuul-server
Zuul-server是Zuul的主要的服务,zuul-server是作为zuul的scheduler,zuul-server从gerrit接收消息,一旦消息被接收到,zuul-server就建立工作流程,并把处理结果返回给gerrit Zuul-server跟gerrit组件交流是通过执行“gerrit stream-events”,然后等待gerrit返回的信息,另外,zuul-server也与Gearman进行通讯。
Gearman
Jenkins的设计初衷并不用于并行执行,它设计中某些点使用到了全局锁,因此在Jenkins的slave节点增加到一定数量后(大约100台),Jenkins的master节点就会出现问题而成为瓶颈。同时master节点是单点部署,无法完成HA等处理。为了扩展Jenkins而引入了Gearman。
简单来说,Gearman是一个用来扩展Jenkins的一种协议,而且Gearman一开始并不是专门为Zuul开发的,但是Gearman很好的符合了Zuul的需求,因此OpenStack采用Gearman来扩展Zuul对Jenkins的调度。 在配置的时候可以选择单独创建Gearman-server或者是使用Zuul来部署Gearman,具体在/etc/zuul/zuul.conf里面进行配置:
1 [gearman_server]
2 listen_address = 127.0.0.1
3 log_config = /etc/zuul/gearman-logging.conf
4 start = true
5
把start改成true,zuul服务就会启动并管理Gearman进程。
Zuul-merger
这里不要被这个组件的名字所误导了,这个组件并不是当代码全部通过测试后用来merge到主干的。当开发者提交一个change后,zuul-merger把这个change merge到一个本地forked repository中 ,这样就可以进行下一步的测试了。
可以把zuul-merger单独部署在一台服务器上也可以进行高可用部署,即部署在多台服务器上组成zuul-merger的集群。
在zuul的配置文件 /etc/zuul/zuul.conf下可以对zuul-merger进行配置,在 [merger] section下面:
1 [merger]
2 git_dir = /var/lib/zuul/git
3 log_config = /etc/zuul/merger-logging.conf
4 pidfile = /var/run/zuul-merger/zuul-merger.pid
5 zuul_url = 127.0.0.1
6
git_dir是zuul对Git repository的一个copy
Log_config是配置zuul-merger的log目录
zuul_url是zuul server的url,这个url可能有多个(zuul集群的情况下)
Zuul-cloner
Zuul-cloner不像其他组件,它没有Damon,只有一个client,用来创建job的workspace
Zuul Workflow
下图解释了当一个patch提交给gerrit的时候zuul的workflow是怎么样的:
Gerrit
用户的patch是提交给Gerrit的,也可以是一个新的commit,一旦这个patch被提交上来,Gerrit就会publish一个event,通知其他服务来处理这个event,如Zuul、Jenkins等。
Zuul Server
Zuul-server根据zuul.conf的配置来启动相应的关联进程,Zuul server会先起一个进程叫GerritWatcher,用来listen从Gerrit那边传过来的event(步骤3),在注册好所有的连接后,zuul-server会起一个Gearman,zuul-server同时会启动Gearman和Scheduler。
当一个Gerrit的event被publish后,GerritWatcher就会通知scheduler,scheduler先会去检查这个event是否合法(根据layout.yaml里面定义的规则),如果通过,便会触发一个trigger event(步骤4)。
Scheduler接着处理这个event,并把这个event添加到一个相关的pipeline里面(步骤5,也是根据layout.yaml里面定义的规则),接下去就是pipeline来处理这个event了,scheduler也会去检查这个event是否依赖于其他的event。
Zuul Merger
当scheduler触发完成trigger event后,把整个代码克隆下来,并把更改的代码并入主干的工作是由zuul-merger来完成的。在步骤6中,merger会从gearman那边获得一个“merge job”的信息,里面包括项目的名称,分支信息,change number和ref等信息。第一步merger需要确认这个commit是不是重复的,如果是,那么就返回已经发生的commit,如果不是,那么继续下一步工作。
HEAD ref重置完成后,如果ref指向了一个不可用的分支,那么zuul就会自动选择第一个可用的分支,然后merger会通过“git fetch”来update repo,再checkout。
接下来merger尝试merge更改到repo上,如果merge成功,那么就会在zuul-server中创建一个新的reference到repo中,最后,merger会返回一个动作完成的信息。
Gearman & Jenknis
现在repo已经准备完成,在上面merger的工作完成之后,现在需要测试这个代码的更改。这步操作其实是scheduler来做的,但是需要配合Gearman来执行。Scheduler发送给Gearman,scheduler也会发送一些变量给Gearman,一般是 ‘ZUUL_’ 开头的。
Gearman接着把数据发送给Jenkins,Jenkins可能是一个集群,Jenkins在测试完成后会把结果返回给zuul,zuul再去通知gerrit是否去merge这个更改。
是否必须使用Jenkins
OpenStack社区考虑过不再使用Jenkins,只使用Zuul来代替,但是如果你的CI系统跟Jenkins强绑定的话,系统中使用了很多Jenkins的plugin,那么再去转换到non-Jenkins的环境中会有比较大的困难。当然可以慢慢利用Zuul来替换Jenkins,但是如果一定要使用Jenkins的话,那么就需要“Jenkins Gearman”这个plugin来提供支持。
Pipelines
Pipelines是Zuul重要的组成部分,每一个gerrit的change都会由一个或者多个Pipelines来进行处理。
Upsteam
非Openstack核心团队的人员可以在评审代码后作出+1(好)、0(无评价)、-1(不建议合并)的评价。核心团队的成员可以给出非核心成员可给出的所有评价,此外还可以给出+2(好,approved)、-2评价(不要提交)。
标签属性中另外一列为“Verified”。只有Gerrit的非交互用户(non-interactive users)如Jenkins,才能在此属性上添加Verified标签。Verified一列可设置的值为+1(check pipeline测试通过)、-1(check pipeline测试未通过)、+2(gate pipeline测试通过)、-2(gate pipeline测试未通过)。此外,第三方搭建的外部测试平台也属于非交互用户,但是只能设置+1、-1。
Pipeline也有很多种:
periodic – 周期性工作的pipeline,比如用于非工作时间做常规的测试
expermental – 如果你有一个新项目,但是不知道它是怎么工作的,那么可以用于这个expermental pipeline
pre-release – 触发的job是归于一个新的pre-release tags
release – 触发的job是归于一个release tags
定制化Pipelines
可以通过配置Zuul来定制化pipelines,可以通过更改zuul layout配置文件,下面是一个配置例子:
1 - name: test
2 manager: IndependentPipelineManager
3 source: gerrit_internal
4 trigger:
5 my_gerrit:
6 - event: patchset-created
7 success:
8 my_gerrit:
9 verified: 1
10 failure:
11 my_gerrit
12 verified: -1
13
可以自定义一个pipeline,取名为test,如果pipeline运行成功,那么返回给gerrit +1,如果失败,那么返回给gerrit -1。上面的配置文件中还有
1 manager: IndependentPipelineManager
2
这个是用来决定pipeline具体是如何工作的。
IndependentPipelineManager
IndependentPipelineManager是当pipeline在处理信息是不需要关心信息处理的顺序的时候使用,在一些patch提交时,在其他test正在运行的时候,也不会对这个patch提交产生影响,当前提交的patch相对独立,就可以使用IndependentPipelineManager。
DependentPipelineManager
DependentPipelineManager则是当pipeline在处理信息是不需要关心信息处理的顺序的时候使用,如果当你同时提交了多个patch,当一个patch test failed的时候,那么同时提交的相关联的patch都需要再次test一次。
Zuul同时还可以很好的处理具有复杂依赖关系的多个patch。它能监控正在执行的任务,并可提前结束掉因依赖的patch测试失败而必定失败的测试任务。
参考文献:
http://stackeye.com/2014/06/openstack-ci/
https://docs.openstack.org/infra/manual/zuulv3.html
关于九州云99Cloud
九州云(99Cloud.Inc)成立于2012年,是中国第一家从事OpenStack和相关开源服务的专业公司。公司成立六年,秉承“开源 · 赋能变革”的理念,已经从单一的OpenStack产品提供商,发展成为涵盖云核心、云运营、云运维和云安全等多个领域的开源软件和服务提供商。九州云已支持了国家电网、×××、中国银联、中国移动、中国电信、中国联通、中国资源卫星、中航信(航旅纵横)、eBay、国际陆港集团、中国人寿、万达信息、东风汽车、诺基亚等重量级客户。在2018年最新的Queen发行版排名中,九州云在核心模块贡献跃居全球第四,中国第二,其中在容器部署Kolla项目、NFV编排Tacker项目等重量级项目上贡献全球第一。
原文地址:http://blog.51cto.com/99cloud/2122453