最近不太更新文章了, 主要是自从孩子出生以后天天的回家就是给孩子洗澡,洗尿布,洗奶瓶,洗内裤,洗衣服。一套程序下来差不多就 11 点了 。 有空的时候也在为刚结束的测试开发大会准备演讲稿和 PPT。 我这个人比较谨慎,比较担心临场发挥会出篓子,还是准备好详细的演讲稿再演练几次比较靠谱。 自从那次饿了么测试沙龙的时候就说过要更新一些 docker 和 k8s 的技术文章,但自那以后就过上了奶爸生活,这个计划就一直搁浅了。 现在打算兑现当初的承诺,把我在公司应用 docker+k8s 做的事情详细的记录下来。也算对我过去一年多的学习和工作做个总结。这个文章的标题是 devops,但你可以有不同的理解,因为这是个大部分内容都在讲用 docker 和 k8s 去搭建一个测试环境集群的系列文章,因为在这我是从技术的视角看待 devops 的,而我觉得实现 devops 的核心技术就是容器技术。而且如果你在外面听说过各种客户端的云测技术的话,那你也可以把这个系列文章做的事情当成是一种服务端的云测平台 (虽然它的作用不止如此),所以大家可以不被这个 devops 的标题限制住,你们可以随意的对内容进行不同的阐释。而且大家不要被云这个看上去特别高大上特别装逼的词汇给唬住。它没有你想象的那么高不可攀,究其本质它就是个集群,是一群基础设置组合在一起并由某种管理工具进行管理的机器的集合。我会一点点的从头开始讲述如何搭建这么一个集群,并会讲一些其中的原理,做到知其然知其所以然。我不是专业 sre,可能有些地方不够深入,还请大家谅解。
这次写的东西面对的是跟我当初一样想涉足 devops 但没有知识的测试同行,我相信我的经验可以让你们少走很多弯路。如果你是专业 sre,那你可以不必看了,我的 docker 和 k8s 的水平在你眼里估计就是个菜鸟。
其实我到现在都没真正搞明白 devops 到底是个什么样子的。每个人,每个公司都能给我不同的定义和实践。 所以我倒并不是很确定我的做法是不是符合大家对 devops 的定义。从表现上看我发现我们公司对开发,测试和运维的分界线没那么清晰了。 我们的开发干了不少测试的事,也干了一些进场运维的事。例如他们写了很多单测,自测了很多算法,写了 CI 工具,定制化了 jira。客户现场有问题的时候不经过运维和 QA,他们自己直接修复,测试,出包。 有时候甚至会跑到客户现场去做支持。 我们的 sre 也干了很多开发和测试的事。 例如线上的一些性能测试都是他们自己在做,我们产品的多租户模块,预估模块,SAAS 平台等等都是他们开发的。 QA 也没以前那么本分, 我们也干了一些开发和运维的事。 例如开发一些工程效率和测试工具给开发人员使用。 例如公司内部的容器集群是我搭建并维护的, 整个产品的编译,部署,出包也是我写的工具自动化起来的。现在我们都或多或少的做了一些以前不该我们做的一些事情。 而有趣的是这并不是我们有意而为之的,没有人喊着 devops 的口号推行改革,没有人举着 devops 的旗帜到处树立标杆。 我们都是自发的跑去做自己最擅长,最有兴趣的事。 所以如果有人问我怎么理解 devops 的,我可能会说是一个团队中的各种角色在一起合作开发出来一整套的工具链,这套工具链涉及到产品生命周期的各个方面。 让本来需要好几个角色才能完成的事情精简到只需一人。就像开发和 QA 有环境需求的时候不会去找运维,集群那么大,一个命令就能搭建一个完整的产品环境了。开发人员解决客户场地的 bug 的时候也不会再找 QA 和运维,他们可以很简单的进行自动化编译,部署,测试,出包。 运维和进场工程师想验证部署的环境有没有问题的时候也不会去找 QA, 自然有一套自动化测试脚本让他们一键运行。 所以就是这样的,在我看来 devops 的核心是一套工具链。一套能让大部分流程全程自动化的工具链。 那么这个系列文章要讲的,就是我再这套工具链中都做了什么,其实主要也就是主要讲 docker 和 kubernetes 的事情,以及自动化测试容器化之后应该怎么做的事情。
在公司做某一件事肯定是有需求进行驱动的。 没有需求的话就变成装逼和晋升用的 kpi 项目了。所以在文章开始之前我有必要先描述一下我们曾经遇到的业务压力和需求。我在前几天的测试大会中也提到过一些。
所以综上所述,能够支撑大规模测试环境的基础设施是十分必要的。 这也是为什么我们使用 docker+k8s 来做这件事的原因。
简单说一下 docker 给不熟悉的同学。docker 是一种容器技术, 没接触过的同学可以暂时理解为虚拟机 (但它不是虚拟机,暂且理解为虚拟机有助于你之后的操作。实际上在某种情况下,外界是分不清它使用的环境是虚拟机还是容器的,关于容器的原理我再下两个帖子会详细介绍它的分层文件系统和网络模型)。通过镜像我们可以迅速构建出不同版本的测试环境,而它制作一个镜像的方式又极其简单,就像写脚本一样。 如下:
这就是一个 dockerfile, 就像写脚本一样,在第一行就可以从一个已有的镜像继承下来 (分层文件系统的功劳,下一个帖子会说明这个机制)。继承镜像以后使用一些命令来增加一些内容。之后只有一个 docker build 就 ok 了。 最后一行的 entrypoint 是容器启动后运行的第一条命令。 平时我就是在这个脚本中运行编译,部署等操作。 通过 docker run 镜像名称 就可以启动一个容器了。通过这种机制我们就可以很方便的构建出标准化的测试环境。
k8s 是一种容器编排工具,可以统筹多台宿主机上的 docker 进程,从而管理一个容器集群。它能满足我们在需求澄清那一节中列出所有的功能要求。为什么选 k8s 而不是 mesos 和 swarm。 因为它拥有着比前两者更强大的功能的同时,还提供了更加简单的部署方式。 自动 kubeadm 和容器化部署出现以后,搭建一个 k8s 集群的难度就从地狱模式走向了新手模式。所以我十分推荐大家在公司内部使用 kubeadm 来搭建自己的测试环境。
我在测试大会中也发过这个图,大家发现好像我们搞了很多东西,包括图里展示出来的和没展示出来的。 当我们在单机运行 docker 的时候架构是很简单的,可以说几乎就没什么架构可言。但当我们扩展到集群的时候,复杂度就会成几何趋势上升。例如我们得考虑各个节点间的网络通信问题, 集群的监控问题, 集群中的服务发现机制 (ip 是自动分配的,而且不固定,不能依赖 ip 地址), 集群的资源管理和超买超卖,集群服务的高可用和负载均衡,集群环境的冗余和灾难恢复,集群的镜像管理和共享,如何对外暴露集群内的服务等等等等。 不过 kubernetes 有各种现成的解决方案,而且都是有现成的镜像供我们使用, 所以大家可以不用担心太多复杂导致我们 hold 不住。之后我会一点一点演示怎么搭建和维护这些服务。
这些就是这个系列文章序的部分了, 大体上写了一下要写些什么,为什么写以及能达到什么效果。 下一篇文章开始进入正题。先讲一下 docker 的基础之一:分层文件系统 的原理,分别讲述 aufs,device mapper,overlayFS 和 overlayFS2 的大概实现和其中的一些坑。 Dockerfile 为什么要那么写, 怎么利用分层镜像系统管理我们的镜像等等。