背景

最近很荣幸能参加饿了么和 tester home 社区合作举办的线下测试沙龙。 感谢大家对我的信任,让我有机会分享一些我再工作中的实践。由于最近一有时间就准备 PPT 和演讲稿。所以一直也没有继续更新关于 spark 的帖子了。 之后我会慢慢的恢复连载,不过我滴儿子要出生了哈哈 (狂笑中),可能未来要停刊一段时间了。现在我把之前为线下分享准备的演讲稿整理一下。分享给社区的小伙伴。里面有我这次分享的全部内容。也包含了一些我演讲中没有说出来的东西。 第一次演讲,有些紧张,好几段都没讲出来哈哈。

===================分割线,以下是演讲稿内容=================

自我介绍

大家好,我叫孙高飞,是自第四范式的测试开发工程师。由于工作的关系,最近一年都在研究一些容器技术。最近两年,容器技术非常火,随之而来的 devops 也流行了起来。运维开发这个职位也火了一把。那容器技术已经慢慢开始普及的今天,对我们测试人员有什么变革性的影响呢。今天我就想跟大家聊一聊 docker 在我们公司的测试环境中扮演了怎样的角色。

大家看到这个图了,这是 docker 公司在互联网上用 799 美元找人设计的 logo。 Docker 自己是这样说鲸鱼的:The logo is a Whale carrying a stack of containers. It is on its way to deliver those to you.它托着许多集装箱。我们可以把宿主机可当做这只鲸鱼,把相互隔离的容器可看成集装箱,每个集装箱中都包含自己的应用程序。鲸鱼或许代表着创始人 Solomon Hykes 眼中的互联网愿景,就像 20 世纪 50 年代集装箱颠覆了全球物资运输方式一样,它将会颠覆信息运输方式,让货物在互联网的火车、汽车、轮船之间畅通无阻。
这个跟我们今天的主题也很像。docker 就是这个鲸鱼,它有能力承载着我们庞大的测试环境。

困境

首先我们介绍一下背景,从我们曾经面临了哪些问题讲起,慢慢的介绍为什么我们的 docker 方案会是现在的这个样子。

解决方案

我们的工作效率很低。我们在测试环境上投入了很多精力但并没有显著的提高效率。所以我们急需一套测试环境的管理方案,起码提供以下三个能力:

Docker

docker 有很多的优势,要详细说明要很多时间,我就列一下我们主要关注的几点。

我们用 docker 做什么

就如上面的图一样,我们把所有我们想要的服务都放到容器里。 也一如一开始我们说的那个 logo。 docker 这条鲸鱼承载着很多的集装箱,集装箱里就是我们的服务。 那么我们的问题来了,我们如何跟这些集装箱中的服务通信呢? 我们知道容器并不是虚拟机,我们不能像以前一样做了。所以我们先介绍一下网络的玩法。

网络的玩法

端口映射

我们先说端口映射。容器并不是真正的机器,我们在外部与容器通信通常都是通过端口映射来解决的 --- 将容器的端口映射到宿主机上,这样外部可以通过宿主机 ip+ 端口的方式与容器通信。请看下图

细心的朋友可能在玩 docker 的时候就发现了安装 docker 的时候默认会创建一个叫 docker0 的虚拟网桥。而且 iptables 里面多了很多条规则。 实际上 docker 的网络就是在玩 iptables,尤其玩的是 NAT 这张表。当你使用 ip+port 的模式访问的时候,iptables 就会把你发的报文拆开并使用 DNAT 修改你的目标地址,转发到 docker0 上。然后 docker0 才会转发到容器上。 实际上 docker 的前三种网络模式:host,briage,container 玩的都是这种转发规则。这种方式的优点有两个:1. 使用简单,docker 默认的网络玩法就是这样的。2.安全,因为外部是没办法随意的访问容器的。docker 给所有容器分配的 ip 都是虚拟 ip,只能在一个节点的所有容器内部使用。
那这时候我们就有一个问题了,通过端口映射的方式很不方便。一个测试环境往往要对外暴露很多接口。例如我们做测试要访问 mysql,那就得把 3306 端口映射到宿主机的某一个端口上。要访问 web 服务可能要暴露 80 端口,为了能 ssh 到容器中又得暴露个 22 端口。而且你 ssh 的时候还得手动指定端口号了。也就是说一套环境你要记住好几个端口号。 总之就是很麻烦。如果我们能够像访问虚拟机一样访问容器就好了。只需要记住一个 ip 就可以。 所以就衍生出了下面固定 IP 的玩法

固定 ip

首先我们不用 docker0 了,删掉它。 在宿主机上创建一个新的 br0 的这么一个网桥,然后把宿主机的网卡指到这个网桥上,为网桥分配 ip。 修改 docker 的网桥配置,指定网桥为我们新建的 br0. 再修改 docker 启动容器的时候分配的 ip 地址段的配置,分配真实的,跟宿主机处在同一个网段上的 ip 地址范围。 这样,我们再启动每一个容器的时候,容器就会被分配到一个真实的可被路由规则的 ip 地址。 我们实现了可以外部登录容器的需求。 但是还有一个问题。这种模式是依赖 docker 的 briage 模式的。每次启动容器分配的 ip 是不可控的。那么下面要解决让我们自己设定固定 ip 的问题。 docker 的最后一种网络模型为 none,就是没有网络。 我们启动容器的时候指定 none 模式。 然后使用第三方的 pipework 工具给容器分配固定 ip。 这样,我们就好像是在使用虚拟机一样的在使用容器了。

固定域名

那这个模式看上去好像已经很完美了。 但是它还是有一个缺点的。 因为你要求的是固定 ip。所以你必然要维护一个 ip 列表。如果其他人启动容器的时候跟你的 ip 地址冲突的话,是很难能查出来的。其实你用虚拟机也会碰到问题。 那这时候怎么办? 我跟我的同事讨论的之后,觉得可以继续使用 briage 模式,由 docker 自己分配 ip。这样就不会冲突了。但是我们做一些手脚。 我们把 DHCP 和 DNS 跟 docker 打通。在启动容器的时候 DHCP 会分配 IP 地址的同时也会到 DNS 上注册一个跟容器名称一样的域名。这样,我们可以通过域名访问容器了。 不用维护 ip 列表,不用死记 IP 地址也不必担心 ip 冲突了。

缺点

后面两个模式当然也是有缺点的。这些容器都是暴露在真实的网络里的。也就是说它们和都处于一个广播域内,它们和我们真实的机器也是一个广播域内。 如果我们的容器变多的话,容易引起广播风暴。 同样如果我们的 docker 宿主机比较多,那再每台机器配置网桥,划分网段也是很麻烦的。 所以这种玩法不适合规模比较大的环境的。

测试环境的玩法

OK,搞定了网络以后,我们聊聊最关心的环境部署问题。 我们最初的模式是下面这样的

container 模式


这是我们最开始的模式,也是效率最高的模式。 开发人员很喜欢。 这个模式有以下 3 个优点

这种模式是开发人员最喜欢的。但是有优点当然也就有缺点。缺点也很纠结:

打包模式

这个就有点像我们经常做的模式了。 首先并发 N 个容器编译并上传到 FTP 服务器上。 然后删除编译容器启动部署容器拉包部署。 这个图里后面不是说就所有东西都在一个容器里部署。 我的意思是就按生产环境标准部署。 每家公司的都不一样。所以我就画一个容器在这上面了。
当然这套有优点也有缺点:
优点:

缺点:

测试机器的玩法

我刚才说过一些这方面的事。 就以 UI 自动化为例。 下载 grid-hup 和各个浏览器的 Node 的镜像。我们可以很轻松的组建分布式执行用例的环境。平时这些容器都是不启动的。任务过来的时候统一启动这些容器,由于都是 docker 镜像,秒级启动。测试结束后统一 kill 掉。

存储的玩法

在我们能够把服务放到容器中后就会考虑一些问题,我们的数据如何持久化出来。 例如如果容器不小心被删除了,那里面的数据怎么办?所以我们需要一些方式保存我们的数据

外部存储


把数据库这样的存储设备放在 docker 外面。自然就不需要担心容器被人删除了。 一切就跟虚拟机时代一样

volumes

通过数据卷将数据挂载到文件系统中。可以是宿主机的文件系统。也可以是 NFS 这种网络文件系统。docker 支持很多种类型的数据卷。

集群

当我们的测试环境越来越多的时候,必然会遇到一台服务器无法支撑的情况。所以我们扩展成 2 台,3 台甚至更多。 这时候集群化会显的比较有必要。统一接口管理,合理的资源调度。开源的监控工具等等都为我们的日常管理提供了便利。下面我先跟大家简单的介绍下容器界的 3 位大咖。

k8s 简介

其实最一开始的时候我们使用的是 swarm,因为够简单。 但是由于我们的 SaaS 环境也开始集群化并使用了 k8s。 为了统一技术栈,并且也考虑到 k8s 比 swarm 确实强大很多。所以就在前些日子开始迁移 k8s 上。k8s 的概念比较多,限于时间不能详细说明了。我先介绍一下最基本的几个概念,以方面我开始讨论。

上图就是一个我们为 PM 定制环境的方案。我们公司的业务比较独特,我们是 TO B 的模式。所以线上并没有最近的环境。 有些时候 PM 要跟客户和领导演示我们的产品。这些演示都是很重要的。所以环境绝对不能出问题。这个环境要是稳定的,没有 bug 的。 但我们都知道我们的测试服务器是比较容易出事的。因为好多人都在上面乱搞。 所以我们才有了上面这个图。使用 pod 编译,部署。 但是用 deployment 设置几组 pod 共同提供服务。当有一个 pod 挂掉后,deployment 会自动监控到并请求调度系统重新创建一个新的 pod 使用。 而 service 则提供负载均衡的能力。在这几个 pod 中分发请求。如果一个 pod 挂了。它就给另外的 pod 发请求。这样就组成了我们高可用的需求。

集群服务

为了能够管理集群,我们需要安装一些服务。好在 google 推行了容器化部署。所以这些服务都是有官方镜像的。只要我们下载下来直接使用就好了。下面我们分别来介绍一下吧。

所以我们有了以下的架构图

我们再看看 dashboard 的管理页面

我们再看看 Heapster + influxDB + Grafana 的性能监控页面

尾声

今天由于时间的限制呢,我们可能没办法将太多了。所以我做个总结吧,我觉得器技术的蓬勃发展不仅是给了 devops 用武之地,让运维开发这个职业火了起来。同时对于测试行业来说也是个机会。因为它无形中的为我们打破了很多技术壁垒。如果换做以前,我是绝对做不到今天讲的这些东西的。所以我建议没接触过 docker 的同学可以去学习一下。后续我也会写一个关于 docker 和 k8s 的系列教程连载在 testerhome 上。今天就先到这里吧。


↙↙↙阅读原文可查看相关链接,并与作者交流