持续集成 测试开发之路--k8s 下的大规模持续集成与环境治理

孙高飞 · 2018年07月15日 · 最后由 yen8890 回复于 2020年03月18日 · 145 次阅读
本帖已被设为精华帖!

前言

这篇帖子其实已经写好快两个月了,一直放在公司的 wiki 中做内部分享。 但因为今年的大会里我们组的超哥也专门去讲一些关于 k8s 和 CICD 的事情,内容很像所以一直没发到社区来。 所以既然大会已经结束那么今天就贴出来好了。 同时也很遗憾今年没能到场参加测试大会,感觉特别对不起大家,没帮上什么忙。我赶上了公司最忙的一段时间。 上周还发帖子说战斗已经告一段落,没想到从这周 3 开始又是每天半夜 3 点的节奏。

大规模持续集成

今天主要说一说 k8s 对 CI 能有怎样的支持。持续集成这个话题并不陌生,基本上大多数人都参与在其中。 我做面试官的时候,几乎绝大部分候选人都会说自己做过持续集成,实际上也差不多是这样。 找个虚拟机或者实体机,用 shell 写个部署环境的脚本,在 jenkins 上配置一下 pipeline,git 上一提交代码就触发 pipeline, 单测,编译,出包,部署,自动化测试一条龙就出来了。技术上并没什么门槛,属于懂点技术的都能做的范畴,更重要的可能还是在策略和思想上。大部分还没入门的同学感觉很神秘很高大上,大部分跨过这个门的同学感觉不过如此。 这也造就了一种情况,就是当我问一些候选人关于持续集成的问题的时候, 大部分会有两种反应,一种是觉得这玩意没什么好问的,说来说去就那么几个套路。 第二种是,口若悬河把持续集成吹的上天入地,实际一问其实他的场景特别简单。

持续集的原理确实属于说的烂大街的了。 属于业界很成熟的理念,算是大家的共识。 在很久以前它还是一个很高大上的概念,但自从 jenkins 普及了以后,实现难度已经到了一个很低的程度了。 我记得几年前的时候,我也属于觉得这玩意不过如此的。 但是我记得以前有个人跟我说过,你觉得简单只是因为你面对的场景还不够复杂。 是的, 如果你只是面对一个模块或者几个模块的持续集成, 面对一套测试环境甚至只面对一套测试环境的某几个模块,那确实是简单的。 但如果你面对的是一个有几十上百个模块 (每个模块都有独立的 repo) 组成的产品, 要维护数套甚至数十套测试环境,达到每日构建次数数以千计的时候。 你就不会觉得这玩意那么简单了。 这就是我曾经和现在正在面对的情况。 所以说在持续集成中,如果按技术难度分类的话,环境治理一定是 top 1。 当你面对如此之多的构建次数和测试环境的时候,当你面一套环境这么多个模块以及这么复杂的部署架构的时候。 想用单纯的 jenkins + shell 来搞定环境基本上就是痴人说梦了。 所以才有人说想玩微服务就要先搞定部署。

K8S 带来的环境治理

尤其是大家都知道我们公司是做机器学习的,为了能够保证机器学习平台的研发和测试效率,一个能够支撑大规模测试环境的基础设施是十分必要的。为什么这么说呢?

  • 首先但凡是涉及到机器学习的业务,运行时间都非常慢。 有时候做测试的时候跑一个模型要几个小时甚至一天都是有的。也就是说,我们运行测试的成本比较高。如果在运行测试的途中环境出了什么问题那么损失还是很大的。多人共用一套环境难免会有互相踩踏的情况,例如一个 RD 在测试自己的模块,另一个人上来把服务重启了。这时候我们心里一般就是一万头某种动物飘过。所以我们一般希望能有多套环境分担这个压力。这就增加了测试环境的数量。尤其是团队越来越大的时候,测试环境的数量已经到达了一个恐怖的量级。
  • 其次如果各位所在的公司也像我们一样做 TO B 的业务,那么我们的测试环境就需要多版本管理,要有能力随时快速的搭建起特定版本的产品环境供开发,产品,测试,以及技术支持人员使用。所以这无疑又增加了环境管理设置的复杂度。
  • 再有就是随着环境数量的扩张,我们的环境从单节点走向集群,这时候我们对环境调度能力的要求会比较高,例如我们要对环境的资源进行计算和限制,保证最大化利用资源的同时不会撑爆系统。例如我们要保证系统有足够的冗余,在某些环境出现故障的时候能够自动检测出来并在冗余节点进行恢复。例如我们需要能够实现多租户管理,执行资源管控,限制超售行为. 例如我们希望系统有一定能力的无人值守运维能力等等。
  • 团队越来越庞大,引入微服务架构后对于运维和测试更是灾难级的影响。 对性能更是有着苛刻的要求,因为微服务架构下的模块数量是恐怖的,大量的研发人员提交代码触发 CI 流程,造成了每日的构建次数达到了千量的级别。随着团队的扩展,以后还会有万量级别的压力。 所以单机编译构建已经是一个不可容忍的方案。 我们需要横向扩展能力。

所以我们经过一段时间的讨论和实验,引入了 k8s+docker 来完成这个目标。首先 docker 它具有以下的优势

  • 标准化:所有环境一个镜像,解决环境差异性。避免因为开发环境和测试环境不一致带来的问题。
  • 快速化:启动时间短,秒级。
  • 隔离性:namesapce,cgroups,联合文件系统提供除内核外完整的隔离性,解决互相影响的问题。
  • 易扩展:使用镜像迅速搭建 N 套环境,无间隙。 版本管理 -- 镜像的版本管理对应测试环境的版本管理,易操作。
  • 易用性:Dockerfile 编写简单,会写 shell 的人就会制作镜像

而 k8s 也有很多的优势:

  • 天然的解决方案:玩过 k8s 的都知道,使用 k8s 你几乎可以不用太担心负载均衡,弹性伸缩,服务发现,路由转发等等令人头疼的问题。 它的 service 和 deployment 自动帮你做负载均衡,HPA 自动的弹性伸缩,kubedns 为你提供域名解析,实现服务发现。 官方的 ingress 直接为你实现好了 7 层路由。
  • 自动化运维:k8s 的自动化运维能力也是让人津津乐道的。它的健康检查能全方位的检测容器状态和进程状态。出现问题的时候自动销毁,自动修复。 容器出错重启容器,节点宕机漂移到其他可用节点重新部署。期间负载均衡模块自动导流。
  • 强大的调度能力:在 k8s 中实现多租户是很方便的。 quota 可以隔离资源,namespace 可以隔离应用。 node selector 和节点亲和性更是可以细粒度的控制应用部署在何处。 强大的调度能力使我们的维护成本降到最低。
  • 简单易用的横向扩展能力:一个命令既可扩容,创建应用的时候调度系统动态分配资源。
  • 强大的社区:google 支持,强大的社区阵容,不用担心没有解决方案

那么 K8S 在实际的场景中能为我们带来什么呢? 我举几个场景吧。

横向扩展提升性能与容量

刚才我们说过面对大规模的持续集成与测试环境时。 面对的每日数以千计甚至数以万计的构建次数。上面还要运行着很多的测试环境。 所以一台机器搞这事铁定是没戏的。如果是以前,我们基本都是在 jenkins 上加入大量的 slave 节点并用 shell 脚本来维护。 但是当节点越来越多的时候,维护这些节点和环境的成本就越来越高了。 所以如果我们能让 k8s 来搞定这些事情,扩容与调度都交给 k8s 来做。 jenkins 只负责 pipline,这就解决了我们自己开发和维护这些节点程序的成本。k8s 的扩容是很简单的。并且它给你一个统一的接口,让你对所有节点和容器的操作只有一个入口。 不会像以前 shell 脚本那样满天飞的节点配置和逻辑判断。 而且 k8s 能够对自我管理这些节点,自动决定把容器调度到哪个合适的节点上,不必我们操心。

精准的按需调度

在一个复杂的场景中,我们不仅需要集群的调度系统能按照当前节点的资源使用情况进行调度,也就是尽量把任务分配到较为空闲的节点上进行负载均衡。 我们还需要更精准的按需调度。 K8S 中有一种策略叫 node selector, 我们通过给集群打上不同的 label 给节点分类,在提交任务的时候可以选择不同类别的节点进行运行。 比如我的数据库是需要存放数据的,而这些数据只存在那一个特定的节点上, 这样我们能通过这样的机制把数据库容器调度到固定的节点上。 当然我们还可以有更强大的调度。比如 GPU 资源再哪里都是稀缺的,我们并不希望大量的普通任务调度到拥有 GPU 的节点上,免得它们把资源占满后会导致真正有 GPU 需求的任务无法调度上来。 k8s 有一种策略叫污点,任务除非在特别指定的情况下,否则是无法调度到这个加了这个污点的 GPU 节点上的。 但这样也有问题,因为这个策略太排他了,实际上如果我的 GPU 任务没有那么多,站不满资源。 那这些剩下的资源还不能被其他任务调度,这个资源利用率是无法忍受的。 所以 k8s 也有第三种调度,叫亲和性和反亲和性。 这个有点复杂,但是它能达到一种效果。 就是它可以优先把普通任务调度到其他节点上,其他的节点不够用的时候,才把这些任务调度到 GPU 节点上。 这样能最大程度的保证其他任务不会影响 GPU 任务还能最大化增加资源率用率。

资源治理

上一点说按需调度的时候,也讲过资源利用率的问题。 我们面临大规模的测试环境的时候, 资源治理是一个非常重要的问题。 公司不是土豪, 我们的资源永远是有限的, 在有限的资源中支撑更多的环境是我们的目标。 我们总在计算着一个节点上能抗多少任务,什么类型的任务。服务起少了,资源利用率低,服务起多了,可能直接把节点撑爆了。 这是一个挺两难的事。所以 k8s 中有 quota 的概念,是一个非常重要的特性。首先启动 k8s 的时候可以设置为系统预留多少资源,这些资源是 k8s 不会使用的,专门留给 linux 系统,以免过多的使用撑爆集群。而且 k8s 把每一个资源都分为两种申请方式。 request 和 limit, request 代表着预留资源,也就是说如果我们为一个设置为 request memory 为 2G。 那么 k8s 就会为它预留 2 个 G 的资源,即便这个任务只用了 1 个 G,但其他任务也无法使用另外一个 G 的资源。 这种策略保证了服务绝对拥有启动服务的最小资源,因为只要申请了,系统就会为你预留这些资源使用。 但是这样的策略有个缺点,就是我们一般无法准确预估出一个服务会用到多少资源,也许他只用了申请资源的一半。 所以我们还有一个中申请资源叫 limit, 他跟 requeset 配合着使用,request 是系统预留的资源,是给任务独占的资源,即便任务根本是用不了这么多的资源,但他也会预留出这些资源给他使用,给一个任务设置过多的这种预留资源肯定是不利于资源利用率的, 但是预留资源少了,也可能造成其他任务抢占资源导致本任务无法运行。 所以 request 一般都是设置成需要运行任务的最小资源。 但是最小资源不代表着他永远都使用这么小的资源,在服务的高峰期的时候他会使用更多的资源。 所以我们有 limit 这种资源申请的方式, 如果说 request 设置的是资源的下限,是任务申请的最小资源, 而 limit 就是任务申请资源的上限,代表着不论如何,任务使用的资源都不可以超过此上限,超过了就会被 k8s kill 掉。确保一个任务不会超出它的预期占用过多的资源。 这样, request 和 limit 相互配合,就会产生更弹性的资源治理方式。 尤其由于他们这两种申请资源的方式存在,我们的系统才会拥有超卖的能力。 超卖是一个在集群管理中常见的词汇。 意思是一个服务本来申请了固定的资源保持平时的开销 (request 方式),但是在服务高峰期的时候,准许分配给他更多的资源,也就是超卖给他更多的资源来抗住高峰期的压力 (limit 方式)。这样就给了我们更加弹性的资源利用方式。

健康检查

之前说过 k8s 有自动化运维的能力, 其中一个重要的能力就是健康检查和故障恢复。 一般来说,在我们面对数量庞大的部署实例的时候, 最头疼的就是如果环境不稳定,比如节点故障,或者进程本身故障的时候,我们该如何维护这些部署实例。 在部署实例还比较少的时候这些都不是问题,我们人肉维护都是可以接受的。 但是当我们有微服务的时候,有多套测试环境的时候,数以百计的部署实例会让所有维护人员都疯掉。 尤其是有些服务的故障可能是很临时性的,比如仅仅是进程 oom 了,或者部署的当前节点发生了什么故障。 并不是进程本身的问题。可能只需要重启或者换个节点重新部署就能解决的问题。那这时候 k8s 的调度能力就起到了很大的作用。 首先 k8s 能够自动监控每个节点的健康状况, 如果 A 节点发生了故障,k8s 会监控到 A 节点是不健康的状态, 那么原来启动在 A 节点上的服务,都会自动的漂移到其他的可用节点上重新启动,来保证我们环境的可用性。 这是节点上的健康检查 。 同时我们也有用服务的健康检查, 在 k8s 中,没启动一个服务都可以为它配置相应的健康检查策略,包括资源的和进程的本身。当任务服务出现异常退出的时候,k8s 都会自动的检测到并在合适的节点上重启该服务,这其中不会有任何的人工操作。这种故障恢复能力,是在我们面对大规模测试环境中要拥有的重要能力。

k8s 还有很多有助于维护我们测试环境的特性,比如驱逐策略,负载均衡,弹性伸缩,init container 等等。这里就不多做介绍了。

下面介绍一下 k8s 最简单的玩法。

  • 在 k8s 中,我们使用 1 个或多个 master 节点来控制集群,之后启动多个 node 节点接入集群。 集群中所有的节点都共享公共的镜像仓库。这样我们把所有需要部署的服务都制作成镜像,就可以为团队提供稳定的测试环境和测试服务的基础 PAAS 平台。 重要的是我们从此拥有了相应的自动化运维和横向扩展的能力。 通过统一的入口可以维护多套测试环境,资源不够了就加节点。 说白了,我们就是在拿钱砸效率。我们在推行微服务之前,在高峰时期曾支撑过 70 套左右的测试环境。 其中包括了各种版本以及对接各个团队的需求。 当然了为了能够维护这种量级的测试环境。 我们需要一些机制上的支撑。

  • 跨主机通信:weave 或 flannel, 玩过 docker 的人都知道网络是第一个要克服的难题。 每个 docker 进程都会自己维护一个私有网络,那么在集群中不同节点上的 docker 容器如何互相通信是一个问题。 所幸目前已经有一些插件支持 k8s 组件一个 overlay 网络。 比如我们曾经使用的 weave 和现在正在使用的 flannel。 它会在集群的每一个节点上都安装一个路由容器,帮助我们转发网络请求。 通过这样构建一个 overlay 网络的形式达到跨节点通信的目的。 而且这些组建都已经有成熟的容器化部署方案,我们直接拿来用就可以

  • 服务发现:kube-dns,docker 容器的另一个特点是容器的 ip 也是随机分配。我们在启动前无法获取 ip,并且在容器重启后 ip 也会发生变化。 所以个成熟的服务发现的机制就比较重要了。 k8s 官方提供的 kubedns 是满足我们的需求的。 在 k8s 中有 service 的概念,我们只要创建一个 service,k8s 集群就会在 kubedns 上创建一个域名指定到这个 service 上。 而每个 service,最后都会转发到我们的容器里面。

  • 7 层路由:ingress, 我们可以通过 dns 和 flannel 这种网络组建解决服务发现和跨主机通信的问题。 但是从集群外部访问集群内部还没有解决。 因为即便是 k8s 的 overlay 网络也只是一个私有的虚拟网络。 如果我们想要从外部访问集群的服务,还需要做一些处理。 最简单的方式是 nodeport,这是一种端口映射规则, 利用 iptables 建立转发规则,把集群节点的端口和容器端口绑定, 这样用户使用 ip+ 端口的方式就可以访问集群服务了。 但是这种方式有一个缺点是需要维护大量的端口映射列表。用户使用起来也很麻烦,起码要记住每一个服务端口号是什么。 所以在这个前提下我们引入了 7 层路由的概念。 其实这个 7 层路由就是一个 nignx, 只不过不同的是它是使用 k8s 中的 hostnetwork 模式启动的,它的特点是直接使用宿主机的网络,而不是使用集群的 overlay 网络,所以这个 nignx 容器是可以和集群外部网络通信的。 同时由于我们安装的 weave 或者 flannel 会在每一个集群节点上安装一个路由容器,它会帮助这个 nginx 容器做转发,所以它也能够访问集群网络。 所以这个使用 hostnetwork 的容器就变成了一个可以同时和集群网络以及外部网络通信的容器。 它也就变成了一个 7 层的路由。 这时候我们在公司内部的 DNS 上配置一个泛域名解析, 凡是以固定域名结尾的请求都解析到这个容器的 ip 上。通过 nignx 识别不同的 service 转发到不同的容器中。就实现了这个 7 层路由的功能。 比如,我们在 nignx 中创建的规则是解析一个域名的 service 部分,然后讲请求转发到对应的 k8s 的 service 上。 一个名字叫 test01.n1.com 的域名和 test02.n1.com 的 service 部分是 test01 和 test02。 nignx 会解析出来然后转发到不同的 k8s service 上。 这块我就不具体详细说明怎么实现的了,大家在网上搜一下 ingress 就可以了。 这是官方的 7 曾路由的解决方案,除了这个 nginx 外还要创建单独的 ingress 规则。 而我们使用的是自研的,省略了这些步骤。

监控:官方的解决方案是 Heapster+grafana+InfluxDB。 可以在 github 上找到现成的镜像使用。我们一开始也是使用这种方式。后来我们慢慢演进到了使用 filebeat 来收集容器日志,灌入 es 中做更精细的日志监控的机制。最近我们已经迁移到另外的一套架构了,不过监控这块不是我负责的,我就不说了。

上面这些都是偏运维的东西,我就不再细讲下去了,

总之我们通过 docker+k8s 就有用了很强大的测试服务能力。 一般我们使用这种机制做一下 3 种事情。

  • 搭建测试环境 (其中包括了 CI,CD 的构成搭建)
  • 搭建测试服务,比如 jira,jenkins,testlink 等
  • 搭建测试执行环境,比如 UI 自动化,接口自动化,线上线下一致性对比测试的执行环境。

这些是我们对于测试的基础 PAAS 平台的架构设计, 对于像机器学习这种复杂度如此之高的系统来说, 我们对这方面有着很高的要求。尤其是在后期我们的产品引入微服务的架构以后,它的复杂度到达了一种空前恐怖的程度。 所以这就需要我们的测试人员能够支撑住这样的基础设施。

CICD

一个高度工程化的团队离不开 CICD,但是面对机器学习平台和微服务架构,我们的 CICD 又有了不一样的难度。 之前说过我们在微服务架构下每日大量的构建次数对 CICD 的性能和自动化流程的要求是很高的。这里我们使用的是 k8s+bamboo+jenkins 的架构。 当然了,所有的构建都是基于 k8s 来做的,使用 k8s 的分布式调度来做横向扩展,解决环境对性能的要求。 利用 bamboo 和 jenkins 的 pipeline 衔接整个 CICD 自动化流程。整个的流程如图:

  • 研发人员任何的提交代码行为都会触发 bamboo 上的 plan,plan 会拉取代码运行单元测试和集成测试,运行成功后会打出一个包作为产物上传到仓库中。如果运行失败,将中断流程,该模块自动报警。
  • 上传成功后触发 bamboo 的 deployment 任务去制作镜像并 push 到镜像仓库中。 这里有一点,如果这里有 CD 的需求,如果这个分支是联调分支,或者是稳定环境。就会触发 CD 任务,利用最新的镜像升级环境。
  • 同时 jenkins 上的 pipeline 每日或触发或定时, 在 k8s 集群上拉取最新的镜像,部署环境,执行 UI 自动化测试,API 自动化测试。并汇总测试报告。

通过这样的 cicd 流程加上 k8s 强大的调度能力,我们支撑着每日千量级别的构建次数的同时,保证了最快的响应速度。 托了 k8s 的自动化运维能力,我们也能够用最少的人去维护这样一个庞大的系统。

机器学习平台下的自动化测试

我们说机器学习平台已经是一个产品了。 所以一个产品该有的东西都会有,我们测试人员关心的 UI 和 API 都会有。 该有的模块也都会有, 比如用户,权限,quota,项目,计划,监控,数据管理等等等。 所以除了机器学习特有的一些特性外,他跟我们普通的测试策略也比较像。 构建测试体系的时候,也符合金字塔原理。 但在这里我们的 CICD 流程中就有了
另一个挑战,那就是测试运行的速度。做机器学习的研发也好,测试也好。 都要面对一个无法避免的问题。 那就是任务运行很慢。 在大数据的情况下,一个模型要用几个小时甚至几天的情况也是不奇怪的。即便我们用一个很小的数据走通业务流程,一般也需要数分钟甚至数十分钟。 所以如果我们像以前一样,使用一个浏览器运行的话,在海量的 case 面前,我们的自动化测试会跑到天荒地老的。 所以在我们早期的时候就会使用多浏览器的方式来为我们的自动化测试加速。 我们使用的技术栈是 java+testng+selenide。 testng 的并发测试模式大家可以了解一下,调整并发的线程数我们就可以在一台机器上启动多个浏览器进行测试。

通过类似上面这样的配置,我们把测试分成了两个组并且并发的去测试他们。 这样在初期的时候还是可以接受的。 但是随着 case 慢慢的增长, 算法越来越多。 我们又出现了一个问题, 那就是单台机器已经无法支撑更多的浏览器了。我们说架构扩容有纵向扩展和横向扩展两种,纵向扩展是通过提高节点的硬件配置来提高性能,但是即便是再优秀的机器它的纵向扩展也是有极限的。 而横向扩展是通过增加节点的方式分担压力。那么目前我们面对的就是在纵向扩展遇到极限的时候,引入横向扩展的能力。 而 testng 本身是不支持跨越多台机器进行分布式执行的。 所以后来我们引入了 selenium gird。 这是一种基于 selenium 的分布式 UI 自动化测试解决方案。 它通过启动一个 grid hub 作为 master 节点,负责接收测试请求以及分发任务。 再通过启动多个 node 节点向 hub 进行注册。 这样 grid hub 会接收到我们的测试请求,并适当的把测试任务均匀的发送到各个 node 上去。 在测试结束后汇总结果返回给 testng。 它的架构是下面这个样子的。

通过这样的架构,我们的自动化测试就拥有了横向扩展的能力。 支持更多的浏览器帮助我们进行并发测试。当然大家可以看到在这个图里我们各个节点上都带有 docker 的标记, 为了方便管理和节省资源。 我们也使用容器管理的方式来建设自动化设施。 我们讲 grid hub 制作成镜像,可以运行在 k8s 中当做一个服务。 然后将不同的浏览器制作成不同的镜像。 比如把 chrome 和 Firefox 做成不同的 node 镜像,也通过 k8s 启动服务,注册到 grid hub 中。 当然大家可以发现我们在上面的这个图里在 IE 的镜像那里画一个叉,因为目前 docker 还是无法制作 ie 的镜像的,这涉及到 docker 的原理,docker 使用的是宿主机的内核也就是 linux 系统的内核。 还是无法驱动 windows 的 GUI 的。 所以这部分没有办法,只能够通过在外面启动虚拟机的方式接入 ie 浏览器了。 不过其他两种浏览器还是可以很简单的使用的。 并且通过 k8s 的自动分片的功能,我们可以很方便的启动多个 node 来支持自动化测试。 k8s 强大的调度能力也会在资源上做权衡,做到资源利用最大化,而不会把这些 node 都启动到一个节点上。 同时健康检查机器可以监控到每个 node 和 hub 的状态,如果出现异常会自动的找到可用的节点重新部署。 资源管理能力也可以限制和申请适当的资源,很方便实现的超卖功能。 这样通过 k8s 的自动化运维的能力,我们可以很好的管理我们的浏览器集群。 当然也许会有同学问都是使用 docker 启动的浏览器,那么我们怎么样能够实时的看到浏览器在发生什么呢?以前使用 windows 的时候我们是可以通过界面看到发生的所有事情,方便调试。 其实我们在这里也是可以做到的。 我们在一个 node 镜像中都安装 vnc 服务,并向外暴露端口。 我们在自己的本机上使用 vnc viewer 就可以看到浏览器上发生的一切。

这时候我们的整体工作流程就是下面这个样子的了。

这里我们有两种做法, 一种是 jenkins 直接调用 k8s 的 job,job 执行自动化测试,执行完毕后 jenkins 拉取 report。 另一种做法是直接利用的 jenkins 的 slave 机制,把 slave 直接用 k8s 中的容器的形式启动起来。 这样 j8s 中的一个容器就是 jenkins 的 slave 了。 如果为了简单,我们可以选择后者,利用 k8s 的自动化运维能力,提供稳定的服务。 在 jenkins 上的 job 上绑定测试的 repo,jenkings 触发测试的时候,jenkins 的 salve 会到 git 上拉取代码,并执行自动化测试, 由于我们的 slave 就是启动在 k8s 里的容器,所以他们的访问是无障碍的,甚至完全不需要端口映射和 7 层路由。 slave 的测试请求会发送到同样是启动在 k8s 中的 grid hub 上,gird hub 会把任务发送到同样在 k8s 中作为容器启动的 node 上面去执行。 之后将测试结果一层层的返回,汇总到 jenkins 的 job 中。 这里使用 k8s 的优势就是完全的自动化运维管理,出现任何异常 k8s 都会帮我们处理,这比搭建多个虚拟机来管理要方便便捷很多。 通过这样的架构,在我们的公司的日常测试中使用 40 个浏览器并发测试的方式,可以在 30 分钟内结束战斗。 极大的提升了测试效率。这里在安利一波 selenide,这是一个 github 上面的开源项目, 基于 selenium 做了一层封装。 可以很好的支持我们的这种架构。我们只需要两行代码,就可以对接这种分布式架构了。 如下:

上面的第一个配置指定使用的浏览器类型,第二个配置指定 grid hub 的地址。 这样就可以让我们的代码测试代码迁移到这个分布式架构上了。 其他的任何代码都不需要改变。 之后的工作只需要在 testng 的配置文件中指定并发数量就可以了。

尾声

今年测试开发大会我特意推荐了我们公司的两个同事去分享 topic, 一个是机器学习算法架构的测试,一个就是 k8s 下的 CICD。 可惜算法架构测试的那位同事掉链子了,而推荐的另一位蚂蚁金服的同学分享这方面的内容因为公司层面规则的问题也无法分享了, 我打算明年自己申请一个 topic 分享来弥补这方面的缺失。不过好在超哥的 k8s 的 topic 还是保留了下来。 我一直认为 k8s 将会是一种趋势,前年 k8s 击败了 mesos 和 swarm 成为容器编排界的扛把子。去年 tensorflow on k8s 开始流行, 就在前不久 spark 宣布支持 k8s 调度平台, google 宣布 tensorflow 将天然支持 k8s 调度。 在微服务和机器学习大行其道的今天,我觉得及早掌握 k8s 技能对于测试人员来说将会是很重要的一步。将来会有越来越多的应用和框架运行在 k8s 中, 而拥有了 k8s 能力的 QA,将会抢占一定的先机。

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

关键在于达不到那种的高度,我们测试环境就一套 数十套测试环境,为什么会有数十套测试环境呢,都是干什么用的?请教下

怒赞,干货满满! 我就是你开始说的 jenkins 写个 shell 就敢说自己自己搞过持续集成,越了解才知道自己是坐井观天 不光持续集成,就环境治理这个绝对是头等大事!环境治理!环境治理!环境治理!重要事说三遍~ 测试有完全自己独立的测试环境,并且同步线上,在很多公司感觉都是奢望,但是这是必然趋势

先赞后看~终于等到更新👏

我们现在用的 gitlab+docker+k8s+helm+prometheus+efk,还在不断完善

真大佬!

watchdog 回复

就是避免环境冲突的。 有产品给客户用来演示的 demo 环境, 有给公司内部试用的环境, 有培训用的环境。 有给不同的研发团队搭建的环境。有给技术支持用来复现问题和做验证的环境。 在测试组内部也会针对不同的目的搭建不同的环境。 有做性能测试的, 有做兼容性测试的,有做功能测试的, 也有针对不同的产品版本搭建不同的环境。

分享的内容扩涨了眼界,以前也是觉得会 shell 那套就会持续集成了 多学多学~

楼主这个看着真高大上啊,都看不懂😅 😅 😅 赶紧 mak 下以后学习。培训了三个月测试开发,以为懂得挺多了,但是一看楼主的觉得自己好 low

陈恒捷 将本帖设为了精华贴 07月16日 14:14
孙高飞 回复

我配置的 ci 是面向移动端的,比如支持客户端各种打包的需求,但是对于服务端的 ci 还接触不到,这块公司有专门的运维,而且 base 在异地,没机会接触到各种环境的配置,想尝试怎么办呢?

个人准备加机会吧。 我当初也是没机会碰整个 CI 系统的。 但是我来公司早, 我是 28 号原来。我来的时候还没有运维呢。 然后我自己学习了一段时间以后就把活接了。 对于 QA 来说, 有些时候真的是个人努力加机遇。

666,兄弟,你们 GPU 调度怎么做的?有没有多容器共享 GPU 卡的需求?

沈凯 回复

暂时没有这种强需求,但是正在调研中

孙高飞 回复

大公司就是厉害,

仅楼主可见
王亮 回复

我在第四范式工作, 有兴趣加我微信 ycwdaaaa

有兴趣好好研究下,关键是有业务驱动~

赞!了解一下你们这么多环境的服务器是在哪家云服务上?

在路上 回复

我们公司自己机房,自己搭建的服务

孙高飞 回复

飞哥, 想请教下你们的测试环境 数据库 是怎么处理的,对于 分布式 服务开发 ,当某一个分支提测 涉及到数据库 变更时候, 是一个服务一个数据库 还是 所有服务 公用数据库

白纸 回复

我们使用 mysql,一个服务一个数据库。 微服务么, 应该都这么玩把

孙高飞 回复

一个服务 一个数据库 ,那测试完,合并的时候 有些服务是公用某些数据库 比如用户表 怎么处理的呢

白纸 回复

负责用户的模块会提供 API 对用户进行 CURD 的, 其他模块是不准许直接访问其他模块的数据库的

孙高飞 回复

多谢 多谢~清晰了 很多

感谢分享,干活满满 感觉很多东西需要自己学习才能真正了解这里的精华

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 06:44

android 上能部署 kubernetes 么?

simple [精彩盘点] TesterHome 社区 2018年 度精华帖 中提及了此贴 01月07日 04:08
29楼 已删除
仅楼主可见

楼主 您好 文章看下来 受益匪浅 正好我司的测试/开发环境也不够 同一套服务对应的不同的项目需求只能一个一个测试 不能并行测试 极大的拖慢了测试效率 但是有以下几点疑问 1:这里说的节点 node 是每个 node 对应一台物理机吗 2:每个节点使用的时候,是同时部署多套测试服务,还是单套?如果部署多套相同的服务,怎么做到区分访问的? 3:每个 pod 里面是是部署的单个还是多个服务呢? 应该有哪些理解有误的地方 望楼主能予以解答 非常感谢(开发狗一枚。。)

CrapeMyrtle 回复
  1. 恩是的, 每个 node 就是一个物理机, 我们公司目前都是使用物理机搭建 k8s 集群
  2. 是的,一个节点可以启动多套环境。 k8s 中有 namespce,每个环境用 namespace 隔离,对外使用 ingress 提供不同的域名访问机制
  3. Pod 中有部署多个容器也有只部署一个容器的,看业务特性吧。 以前的时候我们是使用 sidecar 模式在一个 pod 里部署两个服务 ,一个主服务,一个 filebeat 容器收集日志。
孙高飞 回复

谢谢楼主😃

孙高飞 专栏文章:在社区与范式的 4年 中提及了此贴 10月22日 18:29

楼主,请问您讲得 “直接利用的 jenkins 的 slave 机制,把 slave 直接用 k8s 中的容器的形式启动起来”,这个是只有 Jenkins 的 Slave 的 node 在 K8S 里么,Jenkins 的 master node 不会部署在 K8S 中么? 因为我在网上看到得资料是把整个 Jenkins 都部署在 K8S 中,比如这个https://www.kancloud.cn/huyipow/kubernetes/716441 但是目前我们公司已经有一套比较成熟 Jenkins 的 CI/CD 环境,如果全挪到 K8S,还是会有工作量,我看您提到得好像就是把 Slave 的 node 放在 K8S 中,不知道我理解是不是正确,具体方法能不能再讲一下,多谢!

xiye2017 回复

不好意思才看到你的留言, 之前漏掉了。 实际上 jenkins 的 master 节点放入中并不是必须的。 master 节点是可以放到 k8s 外面独立部署的, 只是配置略有不同。 首先你需要为 jenkins 创建一个 service account, 然后为它配置相应的 rbac 规则。 在这个 sa 下找到它的 screct 中的 token 复制下来。 然后到 jenkins 中的配置中添加一个云配置。 在云配置中填写 ca 证书 (kubectl config view 中 cluster 那部分内容就是证书,注意需要用 base64 转码)。 再添加一个 jenkins 认证, 选择 screct 认证,填写这个 token 内容就行了。 其他的配置都一样了。 抱歉你么晚才回复你。 希望对你有帮助

孙高飞 专栏文章:持续集成的开源方案攻略 (一) 概述 中提及了此贴 02月11日 10:06

看了博主的文章,受益匪浅,虽然我在持续集成这一块工作了 2,3 年,文章提到的环境治理,我也都有在做,但是没有博主的这种总结思维,经常被其他同事鄙视我的工作简单,就几个脚本的事情,以后可以怼回去了,感谢博主。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册