基于Docker和Git的持续集成工作流

jopen 6年前

本次主要分享Git 多分支 pull request 工作方式配合 Docker 在持续集成方面的应用。

首先介绍我们公司和团队的情况,kingdee 云之家,主要是做企业社交,其中包括 im,微博等,我们的服务主要包括免费的公有云服务,和各个企业的私有云部署,其中万科、海尔都是我们的客户。

再看看我们现在的系统和技术栈的情况:

  1. 现在的系统中存在 449 项目。
  2. 开发使用的技术栈有Java(标准容器项目使用 Jetty、Play 项目)、Node.js、PHP等百花齐放。
  3. 两条产品线,将近 100 来号开发人员。
  4. 我们还有很多企业的私有云部署需求。

在如此多项目和人员情况下,产品迭代又非常快,这就要求我们能够支持开发部门。下面我们说说在如此情况下我们遇到的一些实际问题:

开发工程师说:
  • 谁又收走了我 MQ 中的数据?
  • 谁改动了 API 的代码,导致我的程序代码报错?
  • 本地程序修改部署,其中出现个以上问题,一上午就过去了。
  • ……

测试工程师说:
  • dev 环境老是在部署,导致没有办法测试。
  • 测试一个 bug 时,别人提交了代码,导致另外的 bug。

产品经理说:
  • realease 分支的代码合并导致了将其他没有完成的功能发版正式环境。
  • 由于相互依赖导致自己开发好的功能必须等其他人。
  • 以上问题导致功能进度不能如期。

上面的各个角色都有自己的痛点,我们来分析下上面的情况造成的原因,其实大部分的情况是由于各个环境的隔离不够造成的,知道原因后我们来看看我们的应对策略:
  • 划分好各个角色的边界;
  • 采用 Pull-Request 的做法。

那我们先来看看我们的基础设施和角色:
角色和现在的基本设施.png

  1. 开发工程师
  2. 测试工程师
  3. 产品
  4. 其他

然后我们再来划分下各个角色的边界:
各个角色的关注点.png

  1. 开发工程师应该只用关注 GIt 上的代码和 JIRA 上的 bug 和 new feature。
  2. 测试工程师只关注 JIRA 的 bug 和 new feature 的测试。
  3. 产品和其他人只关注 JIRA 提交的 bug 和 new feature的解决。

角色的划分,和我们的基础设施看完了,来看看现在 Git 上的分支视图,假设我们现在有两个主分支
git_上的视图.png

  1. master:代表的开发部分稳定分支
  2. release:代表线上稳定分支

我们的角色边界和基本涉及到的设施够看完了,现在看看开发工程师如何工作的:
开发工程师和_git_的交互.png

  • 第一步:根据 jira 上 bug 或者 new feature 从 master 上 fork 一个对应的分支 iss001。
  • 第二步:开发工程师,在 fork 的分支上提交代码,git hook 会通知 jenkins build 相应的 image。
  • 第三步:jenkins 会把相应的 image 部署到服务器集群中,开发者就可以通过iss001.kingdee这个域名访问刚刚对应分支的服务了,iss001 对应的 fork 分支的名称,我们要求唯一。

我们来看看测试工程师是如何工作的:
测试工程师和_git_的交互.png

  • 第一步:测试工程师经过验证后,这个 bug 或者 new feature 的功能完成,会把代码 merge 进入 master分支,在这分支上做性能测试和冒烟测试。
  • 第二步:经过性能测试和冒烟测试后,就可以通过 cherry pick 挑选要发布的功能。
  • 第三步:经过发版后的,测试工程师关闭 JIRA,我们通过 web hook 通知后端Kubernetes集群删除对应分支分配的资源。

这就完成了整个系统的流程,这其中每一个分支都可以分配资源部署环境测试和开发。

Q&A

Q:开发每提交一个bugfix,都会触发jinkens去构建镜像,那么多的开发者,岂不是要构建很多镜像?
A:没有错,我们是每次都触发构建 image,由于 image是分层的,底层已经存在的父对象,是不用存储,只存储变化的部分所以再用的磁盘空间很低,在系统开始初,我做过统计,1000 个 image 也不到 9G,这其中还有很多基础镜像。
Q:想问一个集群相关的,像Docker部署这部是直接调用Docker部署容器,还是通过Ansible或其他工具?
A:有了 Kubernetes 管理集群后,发布的工作就比较简单了,用不上 Ansible。但是 Ansible 还是有它的用处的,比如清理集群中过时的
image,和已经退出的 Container等。
Q:你好,以前也做过类似的服务“第三 步:Jenkins 会把相应的 image 部署到服务器集群中,开发者就可以通过 iss001.kingdee这个域名访问刚刚对应分支的服务了”,单独一个分支解决了对应的bug,但实际生产中非常容易修改一个bug引起其他的 bug,你们是怎么去把控整体的稳定性?如何提高这种单个bug分支单个测试环境的意义?
A:这个 pull-request 的工作方式是应对功能开发的,如像长期开发某个 new feature,你刚刚说的一个 bug 产生另外一个 bug,我们的做法是有回归测试,我们有一个 smoke 分支,持续不断的对其做功能回归测试,只有通过的才能 cherry pick 到 release 上。
Q:测试环境依赖的redis/MQ之类的外部服务如何做的隔离?每次测试单独拉起来一套外部依赖的服务吗?
A:我们通过多个手段来实现共享数据:master、smoke、release 分支测试都有自己独立的中间件,要是不用访问共享的数据,可以部署如 MQ image,代码层面的,如 MQ key 的名称加上机器的 IP。
Q:有没有用到Mesos?是否容易遇到问题?这方面的文档好像并不多。
A:Mesos 是个二级调度,适用于像存在多套集群的情况,来均衡资源,如:部署了 Hadoop 和 storm ,一般会使用 storm 来处理实时的请求,Hadoop 做离线工作。晚上和白天就存在一种可能就是 Hadoop 闲置,但是 storm 可能很忙,这时 Mesos 这样的二级调度就可以平衡资源,节约成本,我们暂时没有这样的需求。至于文档方面我也没有深入研究,建议看官方文档。
以上内容根据2015年12月22日晚微信群分享内容整理。分享人: 胡 世,kingdee 云之家工程师,主要负责架构和性能调优方面的工作,比较熟悉 Java、JVM 相关的技术, 关注 Liunx kernel,对于 Docker 技术栈有浓厚的兴趣,目前研究 Docker 和 Kubernetes 在实际生产环境中的应用。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesx,进群参与,您有想听的话题可以给我们留言。

来自:http://dockone.io/article/916