Docker 测试开发之路 -- 环境管理

孙高飞 · 2016年10月06日 · 最后由 Eward 回复于 2018年11月09日 · 3438 次阅读

背景

他姥爷又来了,他姥爷又忍不住寂寞打算码字了。 今天他姥爷想聊聊环境的问题。因为这里面有很多的坑,环境管理的好能让生产力翻倍,管理不好会团队痛苦不堪。这个是我的感受。记得也就 3 个月前吧,项目刚启动。开发,测试,产品都在使用同一套环境。是每个模块的开发人员出一个人临时糊出来的环境。我们有个习惯就是每个迭代结束后都开一个总结会,记得那时候大家抱怨最多的就是环境了。这么多人公用一套环境,难免互相影响,一会这个服务要重启,一会那个服务因为哪个 bug 挂了。再搭建几套环境也不现实,系统太复杂了,暂时没人能独立搭出来,维护的成本也太高。反正那时候大家都挺痛苦的。正好那时候基本没开发出什么功能,我还比较闲。而且本来我就在研究 CI 的方案,正好涉及到环境部署的问题。于是就想换个思路,以前做自动化部署大多是给测试人员服务的,这次给所有人定制环境。让每人都人手一套自己的环境。于是就这么干下去了。

准备工作

万事开头难,整合所有模块的部署细节往往是苦难的。因为这时候还没有配置管理,所有配置都是散落在各个不同的目录里。而且可能会变化。反正这时候就克服一下,以后有了配置管理方案就好了。

技术选型

谈到环境,首先想到的就是自动化管理。我们之所以只占用一个 QA 很少部分的时间就支撑起 20 多套产品环境,依靠的就是高度自动化。一般自动化部署要么就是传统的脚本驱动模式,要么就是虚拟化技术。我选择了 docker,有多方面的原因吧:

  • 一个是公司本来就是用 docker 搭建的基础服务,大家对 docker 也都熟悉了,起码使用上没什么障碍了。
  • 二是我希望给每个人都搭建一套独立的环境,未来可能起几十个甚至上百个环境,所以传统的脚本模式就不行了,新建环境成本太高,要解决很多依赖问题。而且产品中有几个模块的语言是 node.js,scala,c++。都是编译时间长的典范,用传统的脚本驱动搭环境感觉一定会慢的像蜗牛。换成 docker 就很好了,首先由于虚拟化技术,做好镜像以后我们就没有依赖问题了。同时分成几个容器去部署不同的模块也可以加快部署时间。
  • 三是对资源的利用,docker 本就是以轻量级和使用方便闻名。搭建这么多环境,我觉得也就只有 docker 能把资源利用到最好了。不会搭建个几套环境就把资源占满。

成型的结构图


画的不好大家见谅。每一个模块都是一个容器,每套环境都有独立的数据库,共用一个 hadoop 集群和 config server。但是有一个容器装了单机版的集群做备用,以防万一。记得第一次启用的时候,一下子开了 13 套环境(这个数字还真不吉利。。。),到现在将近 30 套。基本做到了人手一套环境。其中细节不表了,有兴趣的学习一下 docker 吧。总之多语言构成的产品比较麻烦,每种语言在部署的时候都或多或少的有些问题

开发环境定制

一开始就说了,环境不仅是给测试人员用,还要给开发人员用。于是就需要定制一些东西满足开发人员的要求。为了满足开发人员的需求就必然跟传统 CI 中的环境部署冲突。传统的测试环境部署方式一般是下面这样的:

这样的部署方式有一个问题,环境中可能只有一个部署的 jar 包。也许这对测试人员来说足够了,能看 log 就行。 但对于开发人员来说就有诸多不便。我们发现开发人员很喜欢在环境中直接编译源文件做开发。有时候可能 fix 一个 bug 很简单,直接在环境中编译一下重新启动服务就试一下了。 这比写代码,push,merge,重新拉取代码,重新部署要快速简便的多。我们开发人员大多都用 idea,大多都配置了 remote debug。所以只有一个 jar 包肯定是不行的。我们要在环境中保持一个完整的开发环境,例如完成的项目的 git 目录,git client,ssh,mysql client,local 编码设置等等等等。同时要有很方便的方式重启服务,不能让开发人员在重启服务的时候那么麻烦的走重新启动容器,拉取代码等等这一套流程。那么解决方案是:

  • 抛弃编译服务器,直接在容器内编译,启动服务。做法也很简单,使用 docker 的 entrypoint 机制。在启动容器的时候拉取代码,编译并启动服务。
  • 在基础镜像中安装 git client,ssh,mysql client 等等等服务
  • 定制好各种重新启动服务等等的方便的功能性脚本。反正能自动化的就自动化起来。

测试环境定制

测试环境跟开发环境又有一点不一样。 我们在测试环境中最怕的是什么? 部署一个环境的时候发现连冒烟测试都过不去。bug 直接 block 测试流程,这时候只能等着开发修好 bug 再重新部署了。这很影响效率。 对于产品人员呢? 也一样的,产品人员有时候要跟老大,要跟客户演示,因为客户可能会来公司的。产品人员要演示最新的功能。但最新的功能可能还没有发布。需要在公司内找个环境演示。 所以不论是测试人员还是产品人员,都有一个稳定环境的需求。但其实我们避免不了 bug 的,我们部署一次环境的时候难免当时就有什么严重的 bug。解决方案一般有两个,一个是把以前的部署的包做备份。另一个是学运维在线上的策略 -- 蓝绿部署。 我选择了后者,所以测试环境的结构就变成了下面这个样子:

两套环境共用一个数据库和集群。 开发人员在提测的时候部署在 stable1, 下一次部署的时候我们就部署在 stable2。如果 stable2 是有问题的,例如冒烟测试没过。那么就切换回 stable1 测试。stable2 就打回去让开发修 bug。如此循环往复。我们保证始终有一套环境是可用的。

线上部署的定制

通过刚才的介绍我们发现我们是没有编译服务器的,我们在各自的容器里自行编译。这时候运维的同学就比较蛋疼。因为他们需要部署包来在线上或者进场进行部署。而我们的产品是比较复杂的,多语言构成的产品。让运维同学再搞一套编译服务器来生产部署包的成本也比较高。所以我跟运维的小伙伴商量了一下,还是复用我们现有的东西。其实就是我们新加了一个脚本。在已启动的经过测试的容器中把部署包 copy 出来。也就是说,我们的环境被当成了编译服务器

配置管理

这个东西单独拿出来说是因为它比较重要,我们在没有配置管理方案之前,部署是很痛苦的。因为配置文件散落在各个地方,掌握这些信息的成本太高,而且十分不利于扩展。增加或者修改配置的结果往往都是要更改 docker 的镜像并让所有人重新部署环境。所以大家在做环境管理的时候,一定要先推配置管理方案。否则你会痛苦死。这是血淋淋的教训。

总结

暂时就分享到这吧,其实我们做的还有很多不足,毕竟我们的项目才成立了几个月,好多东西不完善。现在 docker 的容器都是跑在一个机器里。之后一旦环境多了,肯定把 docker 做成集群。还有一些镜像的减肥,脚本的优化,环境自检的机制等等都需要完善。这里就当抛砖引玉了。大家晚安,俺陪媳妇睡觉去了

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 8 条回复 时间 点赞

国庆不忘码字,高老师可以开个个人公众号了哈哈哈

#1 楼 @jamesparagon 额,其实我朋友有个公众号叫 QA 之道,我总在哪上面写

#2 楼 @ycwdaaaa 差距好大。。。。国庆带了笔记本电脑回来说学习充电,今儿才第一次开机。。。。唉

#3 楼 @jamesparagon 其实理解哈哈,国庆一般都忙,各种应酬么。 我是因为媳妇怀孕了,在北京伺候她才有时间的。

多谢分享,等稍微空点我好好的去研究下 docker,其实现在很多互联网企业说搞自动化,但实际技术还是老,新技术推进挺不易

—— 来自 TesterHome 官方 安卓客户端

这里 hadoop 是 docker 资源管理用的 mesos 吗?

#6 楼 @cobbxia 木有~ 还是用 yarn 管理的

楼主,我请教一个问题,测试环境定制的,stable1,与 stable2 两套测试环境,但是对外的域名只有一个啊!这种怎么解决呢?谢谢

ABEE ycwdaaaa (孙高飞) 在 TesterHome 的发帖整理 中提及了此贴 01月12日 13:47
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册