> 作者 Sai Yang,译者 杨赛 发布于 2014年8月5日
[OpenStack](http://www.openstack.org/)社区有一个CI和自动化测试小组,该小组为OpenStack社区的开发者们提供服务,而该服务所用的工具正是他们自己维护的一个OpenStack云环境。
对于这样一个囊括了十数个子项目,每月有300多位开发者提交代码的复杂项目,普通的CI系统是难以处理的。
我们跟该小组的负责人[MontyTaylor](http://www.hpcloud.com/author/monty-taylor)和[JamesBlair](http://www.linkedin.com/pub/james-blair/36/1b2/98a)沟通,了解他们在构建和测试过程中所面临的挑战,以及他们是如何解决这些挑战的。
**InfoQ**:你们的CI系统每天处理多少次提交?你预计到Icehouse版本发布时会有多少?(注:本采访完成于2013年11月,当时距离Icehouse发布还有半年)
**Monty**:
> 印象中,我们的系统最高处理过每日400 次提交。这些仅仅是通过测试的部分,实际上我们的测试量要大于这个数字,因为只有通过测试的代码才会进入CI 。
**Jim**:
> 每次提交被审查之后,我们在实施合并之前会再做一轮测试。
**Monty**:
> 对于每个被合并的提交,我们都会对其做8-10 个不同的测试任务。因为测试会在上传的时候和合并之前各做一次,相当于每次变更我们都会跑将近20 个测试任务。有一段时间我们的系统一天就跑了10000 个任务。
> 从Grizzly 到Havana ,我们的集成、测试量基本上增加了一倍。基本上每个新版本我们都会增加一倍的量,到Icehouse 应该也是如此。
**InfoQ**:你们都跑哪些测试任务?
**Jim**:
> 首先是代码风格检测。因为我们的协作开发者人数众多,因此代码风格统一是非常重要的,我们需要确保大家都使用同样的编码方式。这是个很简单的任务,但很重要。
> 然后是单元测试,仅仅测试被变更的子项目,不考虑跟其他子模块之间有网络交互的情况。我们针对几个不同的平台做测试,包括2.6 、2.7 和3.3 ,基本上我们在CentOS 上跑2.6 ,在
Ubuntu 上跑2.7 。
> 然后是集成测试。我们用
[DevStack](http://devstack.org/)
> 将所有的组件安装起来,然后在安装起来的这个单节点云实例上跑不同的模板。不同的模板对不同的模块进行不同的设置,比如使用不同的数据库、不同的消息队列。可以选择的种类很多,不过基本上我们只测试那些常用的,比如
[MySQL](http://www.mysql.com/)
> 、
[PostgreSQL](http://www.postgresql.org/)
> 、
[RabbitMQ](http://www.rabbitmq.com/)
> 这些。
**Monty**:
> 我们最近也在考虑引入
[ZeroMQ](http://zeromq.org/)
> 的测试。
**Jim**:
> 如果社区里认为某个子模块比较重要,使用的人也越来越多,也有更多的人愿意参与到
debug
> 工作当中,那我们也会将这个模块加入。
**InfoQ**:测试任务是由谁来写的?
**Monty**:
> 开发者自己写。我们的
QA
> 团队很小,基本上只关注测试系统本身的工作,不会有太多精力去关注测试任务本身。所以我们要求开发者自己提供单元测试和集成测试。
**Jim**:
> 我们最近在讨论的一个话题就是在这方面做更严格的限制,即只有写好了集成测试的变更提交才能够被接受。
**Monty**:
> 我们总觉得未经测试的变更就是有问题的。一般来说的确是这样。
**Jim**:
> 现在项目发展的这么快,有这么多组件,这里或那里的一个小错误可能就把整个系统搞死。
**InfoQ**:性能测试有在做吗?
**Jim**:
> 还没有,不过我觉得可能差不多可以启动了。我听说
BorisPavlovic
> 正在做一个叫做
[Rally](https://wiki.openstack.org/wiki/Rally)
> 的测试系统,
JoeGordon
> 则在进行一些可扩展性测试的工作——跟性能测试不太一样,不过关联比较大。这都是我们希望做的事情。
> 我们的测试显然没有覆盖所有的方面,不过我们最终希望测试所有的东西,当然这需要时间。
> 在本次发布周期内,我们关注于升级测试。现在我们已经在做一些,不过做的还不够,需要做更多。
**InfoQ**:在一个实例上运行一个测试任务大概需要多久?
**Monty**:
> 一般在20-40 分钟,具体时间长短跟实例的配置有关。
**Jim**:
> 我们花了很多精力让测试变得并行化。我们构建了一个叫做TestRepository 的框架,大多数单元测试在这个框架中已经可以并行处理,测试结果出的很快。
**Monty**:
> 还有Jim 写的[Zuul](https://github.com/openstack-infra/zuul) ,这个工具可以一方面并行的测试成套的变更,同时又保持他们的测试顺序不变。
**InfoQ****:运行测试用到了多少机器?用于运行测试用例的实例配置是怎样的?**
**Monty**:
> 我们自己是没有机器的。所有的测试都跑在公有云上,有些来自Rackspace ,有些来自
HP ,都是赞助的。他们没找我们要钱,而我们需要多少就可以用多少。
**Jim**:
> 上一个版本周期内,最高的时候我们并行跑了340 个实例,一个实例就是一个VM 。集成测试一般使用很基础的VM——8GB 内存,系统是UbuntuPrecise 。我们把这个节点搞起来,然后让
DevStack 在这个VM 上安装OpenStack 。
**Monty**:
> 实际情况要比这个复杂,不过大概意思就是这样。我们有一个
[nodepool](https://github.com/openstack-infra/nodepool) 用来管理这些VM ,通过缓存来预备这些机器。我们需要将DevStack 需要的依赖等东西都预先下载到本地,这样测试本身就可以离线运转。
**Jim**:
> 测试跑完之后,我们再销毁这些VM 。实际创建的VM 数量要比跑成功的测试数量多,因为
Zuul 的随机机制,有些时候它的测试跑到一半的时候才发现还需要一些其他东西,于是测试跑不下去了,我们会干掉这个VM ,起一个新的。一个大致的比例是,如果一天跑10000 个任务,那么启动的VM 数量差不多在100000 的量级。
**InfoQ**:可以认为用于OpenStack的Zuul模式是nviegit分支模式的一个改进吗?感觉Zuul似乎不适合分支过多的情况。
**Monty**:
> 实际上我们是不采用nviegit 分支模式的,因为我们用了[Gerrit](https://code.google.com/p/gerrit/) ,所以我们的代码提交模式跟Linux 内核的模式更像:人们在邮件里交换补丁。我们的做法不是建立很多的分支然后做合并,而是让每一个变更形成一个虚拟的私有分支。相对于将每一次变更生成一个新的commit 并增添至分支的顶端的做法,我们的做法是:在之前的一次修改之上再进行修改。我们的测试针对每一个独立的
commit ,而不是针对一个分支。
> 每一个开发者可以建立本地的分支,这些分支是私有的,没有什么发布机制。我并不知道
Jim 的笔记本上的分支是什么样的。我自己用git 的方式比较奇葩,我不用分支,而是每次在我的master 上重置ref—— 这是个非主流的用法,git 新手最好还是不要这么尝试。
> 所以,OpenStack 的git 补丁流程其实是基于Gerrit的。
**Jim**:
> 另外,我们需要确保审查人员审查的对象是每一个commit (而不是分支)。理想状态下,每一个进入项目的commit 都被人仔细的检查过。分支的话就会比较混乱。把每一个commit 把关好,把好的commit 合并,是比较精细的做法。
**InfoQ**:除了**Zuul**之外,你还提到了在**Jenkins**上使用**Gearman**来提高可扩展性,使用**Logstash**做**debug**,还有你上面提到的**TestRepository**将测试输出自动发给**committer**。目前的反馈机制是如何运转的?理想的情况是怎样的?
**Monty**:
> 反馈机制整体来说是越来越好的。你的问题涉及到几个方面。有关用Gearman 来提高
Jenkins 的可扩展性这一点,首先Jenkins 本身的设计是针对一个master 的情况,让它支持多个节点是通过hack 的方式来完成的。我们一开始的用法是跑一个Jenkinsmaster 和若干个
slave ,并行跑的测试任务数量要比正常的Jenkins 用法要多很多。Jenkins 在设计当中涉及到很多全局锁,所以要像我们这样用起来,会遇到很多可扩展性的问题。
**Jim**:
> 因为Jenkins 在设计的时候根本没考虑过我们这样的用法。
**Monty**:
> 所以我们就写了Gearman 插件,这个插件的作用是让Jenkins 将所有任务注册为潜在的
Gearman 任务,标记在Gearman 服务器上。这样一来我们就可以针对一组测试任务建立多个
Jenkinsmaster ,让Gearman 来做任务分发,如果一个Jenkinsmaster 开始遇到瓶颈,我们就让Gearman 把任务分发到下一个Jenkinsmaster 上。
**Jim**:
> 一般来说,一个Jenkinsmaster 带100 个slave 之后就会遇到问题。我们要同时跑
340 个任务,那就需要3.4 个Jenkinsmaster 来处理。
**Monty**:
> Logstash集群是个很有意思的东西。每一次DevStack 安装的是整个的云环境,然后针对这个小环境跑测试。仅仅是安装的过程就会制造很多日志,包括Nova 、Glance 等等。如果遇到问题,开发者根本无从下手去debug ,能够依赖的只有日志。所以,我们把所有的日志丢到一个很大的Logstash 集群当中,这个集群通过elasticsearch 的方式给所有的log 建索引。这样,开发者就可以进去查看日志,了解到底发生了什么问题。这里面的
[ElasticRecheck](https://github.com/openstack-infra/elastic-recheck) 是
JoeGordon 、SeanDague 和ClarkBoylan 写的。
**Joe**:
> 那个图表功能是我写的。
**Monty**:
> 比如我们发现有一个任务导致测试跑失败了,我们会在
LogStash
> 上运行脚本,来检测这是否是我们之前见到过的错误类型。如果有匹配,我们会在邮件通知里将之前的
bug
> 报告附上,这样会帮助开发者更快的定位问题。
**Jim**:
> 这其实是很酷,也很独特的。世界上像这种规模的项目是很少的,这种规模的测试、这种规模的日志,开发者很少能够在其他项目获取到。云平台这样的项目,开发者在自己的机器上是很难去发现代码可能会引起的问题的,因为很多问题都是要跑很多次不同的测试才能抓到——而我们的测试平台可以做到这一点!下一个发布周期内,我们会尝试让问题识别变得更加自动化,将变更和行为的特征更多的抽取出来,帮助开发者更快的定位问题。
**InfoQ**:你们做的这一大堆自动化测试的工作,感觉最难的地方是在哪里?
**Monty**:
> 开发者很多,代码很多,测试需求量每6 个月都会增长一倍。面对commit 数量如此众多、快速增长的情况,我们需要提前预见到可能发生的问题,做好准备——因为如果真的遇到了问题,那么那个时候再去开发系统来解决问题就来不及了。自动化解决的问题不是今天的问题,而是三个月之后的问题。
> 正因为所有的测试都在我们这里,我们就必须确保这个系统一直能够正常运转。你的测试一天跑10000 次,万一系统出了问题,给开发者发邮件说你的代码有错(而实际上根本不是他们代码出了错,是系统本身出了错),那就会很糟糕。误报比不报更糟糕,所以自动化必须做的非常靠谱。
> 还有就是,我们总是会遇到网络中断的问题——基本上我们有一半的时间都用来处理这个问题。所有的网站都会连不上:平时你自己去刷网页是感觉不到的,但如果你一天跑10000 次自动化测试呢?如果Github 平均有1% 的时间是不可用的,你作为用户去刷页面没打开,重试一次就好;而我的测试系统每天从Github 做10000 次抓取,1% 的不可用就相当于100 次失败。
> 由于我们在跑的这个系统,我们也成了RackSpace 和HP 云的性能监控器。很多时候我们发现有一个问题,就去问他们的运维:“你们这个数据中心是不是网络出问题了?”然后他们会说:“对啊!我们也刚刚发现!”
**Jim**:
> Rackspace 和HP 云都是基于OpenStack 的系统,所以我们的测试系统是在OpenStack 上运行、为OpenStack 做测试。用自己测试自己的代码,同时又测试自己的运行状态,这是个很酷的事情。
## 受访者简介
MontyTaylor是HP杰出工程师,OpenStack技术委员会成员、OpenStack基金会个人董事。他带领OpenStack基础架构项目、Ironic项目和TrippleO项目。
JimBlair现在是OpenStack基础软件组的核心开发者,也是OpenStackCI项目的核心开发者。他也是OpenStack技术委员会成员,OpenStack基础架构项目的技术领导者。他目前任职于OpenStack基金会。
**查看英文原文:**[MontyTaylor and Jim Blair on CI and Test Automation at OpenStack](http://www.infoq.com/articles/interview-openstack-ci-test-automation)
查看原文:[跟MontyTaylor](http://www.infoq.com/cn/articles/interview-openstack-ci-test-automation)[和JimBlair](http://www.infoq.com/cn/articles/interview-openstack-ci-test-automation)[聊OpenStack](http://www.infoq.com/cn/articles/interview-openstack-ci-test-automation)[的持续集成与自动化测试](http://www.infoq.com/cn/articles/interview-openstack-ci-test-automation)