Jenkins Kubernetes Slave 调度效率优化小记

摘要:
Jenkins K8SSlave调度效率优化#bykimmin使用kubernetes作为Gatling大规模压力测试的测试工具。在压力测试过程中,发现Jenkins调度压力测试实例的速度很慢,单批数百个实例需要大约十分钟才能确保完成调度。结合JenkinsMaster源代码和JenkinsKubernetes插件源代码,对调度进行了详细优化。调整后,生成动态JenkinsSlave的主要耗时瓶颈是JenkinsMaster任务队列的填充。目前,用于监控队列和计算消费者侧预期实例数量的算法可能已调整为最积极的策略,但生产者对队列的低效供给导致消费者的饥饿状态。
Jenkins K8S Slave 调度效率优化#

by kimmin


使用kubernetes为测试工具Gatling进行大规模压测,压测期间发现Jenkins调度压测实例较慢,单批几百实例需要十分钟左右也不能保证完整调度。

结合Jenkins Master源码Jenkins Kubernetes插件源码,对调度进行了细节的优化。调优过程中目标实例个数都设为300,调优后可以大体上允许一分钟内从Jenkins Master调度完毕。如果目标实例个数线性增加,调度的时间也不会有明显变化。
经过调优后,目前生成动态Jenkins Slave主要的耗时瓶颈是在Jenkins Master的任务队列的填充上,目前可能已经将消费者端监听队列并且计算期待实例个数的算法调整到了最aggressive的策略,但是生产者喂Queue的效率低下导致消费者出于饥饿状态。

Jenkins Kubernetes Slave 调度效率优化小记第1张

继续对Queue生产者端进行调优,应该需要修改Jenkins Master的源码并且会对正常的构建任务进Queue产生未知影响,可能短期不会考虑。

如果要对Jenkins Master进行调优,可以从以下几点着手:

  1. Jenkins的Master核心是由一系列定时任务组织起来的,目前瓶颈是在Jenkins Master的Queue生产者端,主要是调度任务在多级的Queue里面状态迁移,这个做Queue内Job状态迁移核心任务的执行间隔在Jenkins源码里面是hardcode为5秒钟,所以最坏情况下一个任务需要等待5s,才会在Queue内变化一次状态,即使发生了状态变化,没有进入Pending状态的Job也不会被算进NodeProvisioner的期待Slave列表中。那么我们可以修改这里的间隔来加速调度。
  2. Jenkins的Slave生成的任务是由一个Jenkins各组件共享的线程池来执行的,这个线程池使用的是java.util.concurrent.ExecutorService的newCachedThreadPool,池内用容量为0的java.util.concurrent.SynchronousQueue来维系生产者消费者的关系,之所以用这个线程池是为了让生产者进程当没有分配到线程时阻塞在submit方法。但是由于这种线程池对突来的大量任务会做缓冲导致一些任务没有办法立即调度,优化可以使用一个预声明线程充足的有界队列替换掉当前线程池

Jenkins Master和Kubernetes插件之间的关系的是什么?###

大体上,Kubernetes插件只是实现了Jenkins Master里Cloud类的provision接口ComputerLauncher的launch接口,provision接口是Jenkins Master想要生成一个Slave的时候调用的,那么Kubernetes插件只奉命做事和Kubernetes APIserver通信按照Pod Template创建一个用作Slave的Pod进行工作,launch接口是用来让Jenkins Master的启动一个Slave的,但是由于Kubernetes里面容器实例的创建是异步的过程,所以插件里launch只是在做轮询Pod状态来等待Pod创建完毕结束launch的过程。Kubernetes的Scale效率远大于目前压测实例的创建效率,所以我们定位瓶颈也是从Jenkins Master和Kubernetes插件上开始。

Jenkins Kubernetes Slave 调度效率优化小记第2张


Jenkins Master参数优化###

快照间隔/调度间隔参数#####

按从消费者到生产者的顺序进行分析,首先我们把Jenkins Master计算集群负载的快照间隔hudson.model.LoadStatistics.clock从10秒缩短到了2秒,btw,Jenkins Master防守式地用时间戳快照间隔最小限定到了1秒,但是为了可能更快的进行调度。我们并且且将进行provision的间隔hudson.slaves.NodeProvisioner.recurrencePeriod从6秒缩短到了2秒,这里参数比较危险的是当provision间隔小于快照间隔,可能导致短时间内无限创建slave的bug。

冷启动初次调度等待参数#####

Jenkins服务启动后的第一次provision是由参数hudson.slaves.NodeProvisioner.initialDelay决定的,这个参数是为了确保让静态的Jenkins Slave和Master建立起来连接,由于我们使用的Kubernetes插件其实并不存在双向的通信,所以我们把初始的调度delay从100秒缩小到了20秒。

快照存储EMA(Exponential Moving Average)变化参数#####

hudson.model.LoadStatistics.decay用于EMA抑制负载的抖动,这个参数原本的意义是用于抑制评估master负载的抖动,并且允许给使用者人肉反应时间来终止一些畸形的Job。默认decay是0.9。比如上一次快照负载为1,那么下次入队列的快照评分就会是1 + (1-0.9)*当前负载,我们把快照decay设成了0.1,允许负载大幅度变化。从而每次provision的时候,Jenkins Master评估的负载就是在当前尽可能真实的负载之上评估的新实例个数。这个也是主要提升调度性能的参数之一。

EMA Threshold对浮点型负载进行整数对齐的参数#####
hudson.slaves.NodeProvisioner.MARGIN_DECAY
hudson.slaves.NodeProvisioner.MARGIN
hudson.slaves.NodeProvisioner.MARGIN0

如上图所示,把调整这里的参数使负载做整数对齐的时候尽量向上对齐,从而多provision一个slave,以此来提高效率。

其他#####

另外发现一处可能的BUG,提交给了社区。

https://github.com/jenkinsci/kubernetes-plugin/pull/248

免责声明:文章转载自《Jenkins Kubernetes Slave 调度效率优化小记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Appium之长按元素springmvc常用注解标签详解【转】下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Kubernetes Ingress 日志分析与监控的最佳实践

摘要:Ingress主要提供HTTP层(7层)路由功能,是目前K8s中HTTP/HTTPS服务的主流暴露方式。为简化广大用户对于Ingress日志分析与监控的门槛,阿里云容器服务和日志服务将Ingress日志打通,只需要应用一个yaml资源即可完成日志采集、分析、可视化等一整套Ingress日志方案的部署。 前言 目前Kubernetes(K8s)已经真正...

Jenkins内存溢出的处理方法

参考:http://openwares.net/java/jenkens_deploy_to_tomcat_error_of_outofmemoryerror.html上的说明,有如下解释: -Xms:初始堆内存大小 -Xmx:最大堆内存大,一般设置-Xms与-Xmx一样大小,根据应用类型和物理内存大小来决定二者的大小 -Xmn或者-XX:NewSize:...

jenkins之 pipeline 小尝试

最近,一个小需求,动态建立slave节点来执行自动化用例,原有jenkins 老方式不满足需求,就用到jenkins2的pipeline来实现,但在实现过程中,2个小坑记录下 1、jenkins不能读取file参数中的文件  在任务有file参数时,如下: 然后在pipeline只引用env.env_conf时,发现找不到上传的文件.....<_&...

Jenkins+maven+gitlab自动化部署之Jenkins部署(三)

 本章开始正式搭建Jenkins: 公司现在使用的jenkins版本是2.150.3,但是本次实验安装的版本我们选择最新的2.164.3(当然,当你阅读这篇文章时,此版本已经不是最新),jenkins有多种启动方式,这里就不一一介绍,本问采用yum方式部署。 一、配置yum源 [tchua@centos01 ~]$ sudo wget -O /etc/yu...

Jenkins配置Gogs webhook插件

前言 我们在前面使用Jenkins集合Gogs来进行持续集成的时候,选择的是Jenkins定时检测git仓库是否有更新来决定是否构建。也就是说,我们提交了代码Jenkins并不会马上知道,那么我们可以通过webhook来解决。Jenkins的插件中心已经有对gogs的支持,真的是非常赞。 https://plugins.jenkins.io/gogs-w...

Jenkins 五: 构建Ant项目

1. 点击“新建”,在“Item名称”栏输入要构建的项目名,比如“Ant_project”,选择“构建一个自由风格的软件项目”,点击“OK”按钮。 2. 找到“源码管理”-> “Subversion”. 在 “Repository URL”栏输入源码地址。 3. 找到“ 构建”。点击 “增加构建步骤”,选择”Invoke Ant”。 在“Ant Ve...