作者
刘春明,责编
Carol
封图
CSDN下载于视觉中国
目前公司为了降低机器使用成本,对所有的AWS虚拟机进行了盘点,发现利用率低的机器中,有一部分是测试团队用作JenkinsSlave的机器。这不出我们所料,使用虚拟机作为JenkinsSlave,一定会存在很大浪费,因为测试Job运行完成后,Slave处于空闲状态时,虚拟机资源并没有被释放掉。
除了资源利用率不高外,虚拟机作为JenkinsSlave还有其他方面的弊端,比如资源分配不均衡,有的Slave要运行的job出现排队等待,而有的Slave可能正处于空闲状态。另外,扩容不方便,使用虚拟机作为Slave,想要增加JenkinsSlave,需要手动挂载虚拟机到JenkinsMaster上,并给Slave配置环境,导致管理起来非常不方便,维护起来也是比较耗时。
在年,运维团队搭建了Kubernetes容器云平台。为了实现公司降低机器使用成本的目标,我所在的车联网测试团队考虑将JenkinsSlave全面迁移到Kubernetes容器云平台。主要是想提高JenkinsSlave资源利用率,并且提供比较灵活的弹性扩容能力满足越来越多的测试Job对Slave的需求。
本文就是我们的实践总结。
整体架构
我们知道Jenkins是采用的Master-Slave架构,Master负责管理Job,Slave负责运行Job。在我们公司Master搭建在一台虚拟机上,Slave则来自Kubernetes平台,每一个Slave都是Kubernetes平台中的一个Pod,Pod是Kubernetes的原子调度单位,更多Kubernetes的基础知识不做过多介绍,在这篇文章中,大家只要记住Pod就是JenkinsSlave就行了。
基于Kubernetes搭建的JenkinsSlave集群示意图如下。
在这个架构中,JenkinsMaster负责管理测试Job,为了能够利用Kubernetes平台上的资源,需要在Master上安装Kubernetes-plugin。
Kubernetes平台负责产生Pod,用作JenkinsSlave执行Job任务。当JenkinsMaster上有Job被调度时,JenkinsMaster通过Kubernetes-plugin向Kubernetes平台发起请求,请Kubernetes根据Pod模板产生对应的Pod对象,Pod对象会向JenkinsMaster发起JNLP请求,以便连接上JenkinsMaster,一旦连接成功,就可以在Pod上面执行Job了。
Pod中所用的容器镜像则来自Harbor,在这里,一个Pod中用到了三个镜像,分别是Java镜像、Python镜像、JNLP镜像。Java镜像提供Java环境,可用来进行编译、执行Java编写的测试代码,Python镜像提供Python环境,用来执行Python编写的测试代码,JNLP镜像是Jenkins官方提供的Slave镜像。
使用Kubernetes作为JenkinsSlave,如何解决前面提到的使用虚拟机时的资源利用率低、资源分配不均的问题,并且实现Slave动态弹性扩容的呢?
首先,只有在JenkinsMaster有Job被调度时,才会向Kubernetes申请Pod创建JenkinsSlave,测试Job执行完成后,所用的Slave会被Kubernetes回收。不会像虚拟机作为Slave时,有Slave闲置的情况出现,从而提高了计算资源的利用率。
其次,资源分配不均衡的主要问题在于不同测试小组之间,因为测试环境和依赖不同而不能共享JenkinsSlave。而Kubernetes平台打破了共享的障碍,只要Kubernetes集群中有计算资源,那么就可以从中申请到适合自己项目的JenkinsSlave,从而不再会发生Job排队的现象。
借助Kubernetes实现Slave动态弹性扩容就更加简单了。因为Kubernetes天生就支持弹性扩容。当监控到Kubernetes资源不够时,只需要通过运维平台向其中增加Node节点即可。对于测试工作来讲,这一步完全是透明的。
配置JenkinsMaster
要想利用Kubernetes作为JenkinsSlave,第一步是在JenkinsMaster上安装Kubernetes插件。安装方法很简单,用Jenkisn管理员账号登录Jenkins,在ManagePlugin页面,搜索Kubernetes,勾选并安装即可。
接下来就是在JenkinsMaster上配置Kubernetes连接信息。JenkinsMaster连接Kubernetes云需要配置三个关键信息:名称、地址和证书。全部配置信息如下图所示。
名称将会在JenkinsPipeline中用到,配置多个Kubernetes云时,需要为每一个云都指定一个不同的名称。
Kubernetes地址指的是KubernetesAPIserver的地址,JenkinsMaster正是通过Kubernetesplugin向这个地址发起调度Pod的请求。
Kubernetes服务证书key是用来与KubernetesAPIserver建立连接的,生成方法是,从KubernetesAPIserver的/root/.kube/config文件中,获取/root/.kube/config中certificate-authority-data的内容,并转化成base64编码的文件即可。
#echocertificate-authority-data的内容
base64-D~/ca.crt
ca.crt的内容就是Kubernetes服务证书key。
上图中的凭据,是使用客户端的证书和key生成的pxf文件。先将/root/.kube/config中client-certificate-data和client-key-data的内容分别转化成base64编码的文件。
#echoclient-certificate-data的内容
base64-D~/client.crt#echoclient-key-data的内容
base64-D~/client.crt
根据这两个文件制作pxf文件:
#opensslpkcs12-export-out~/cert.pfx-inkey~/client.key-in~/client.crt-certfile~/ca.crt#EnterExportPassword:#Verifying-EnterExportPassword:
自定义一个password并牢记。
点击Add,选择类型是Cetificate,点击Uploadcertificate,选取前面生成cert.pfx文件,输入生成cert.pfx文件时的密码,就完成了凭据的添加。
接着再配置一下JenkinsURL和同时可以被调度的Pod数量。
配置完毕,可以点击“TestConnection”按钮测试是否能够连接到Kubernetes,如果显示Connectiontestsuccessful则表示连接成功,配置没有问题。
配置完Kubernetes插件后,在JenkinsMaster上根据需要配置一些公共工具,比如我这了配置了allure,用来生成报告。这样在JenkinsSlave中用到这些工具时,就会自动安装到JenkinsSlave中了。
定制JenkinsPipeline
配置完成Kubernetes连接信息后,就可以在测试Job的Pipeline中使用kubernetes作为agent了。与使用虚拟机作为JenkinsSlave的区别主要在于pipeline.agent部分。下面代码是完整的Jenkinsfile内容。
pipeline{agent{kubernetes{cloudkubernetes-bj//JenkinsMaster上配置的Kubernetes名称labelSEQ-AUTOTEST-PYTHON36//Jenkinsslave的前缀defaultContainerpython36//stages和post步骤中默认用到的container。如需指定其他container,可用语法container(jnlp){...}idleMinutes10//所创建的pod在job结束后的空闲生存时间yamlFilejenkins/jenkins_pod_template.yaml//pod的yaml文件}}environment{git_url=git
github.