2

vivo 自研Jenkins资源调度系统设计与实践

 1 year ago
source link: https://server.51cto.com/article/746069.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

vivo 自研Jenkins资源调度系统设计与实践

作者:Wu Qinghua 2023-02-09 08:08:01
本文从目前业界实现Jenkins的高可用的实现方案,分析各方案的优缺点,引入vivo目前使用的Jenkins高可用方案,以及目前Jenkins资源的调度方案的设计实践和目前的落地运行效果。
f56ad88090802d64c9e20554702eb58c407a7e.jpg

现在的企业很多都在用Jenkins做持续集成,各个业务端都依靠Jenkins,vivo Devops也是使用Jenkins来进行持续构建,部署Jenkins服务时如何保障服务的高可用变得尤为重要。

下面是目前Jenkins存在的一些问题

  1. Jenkins本身是单体的,即只能有一个Jenkins Master。虽然你也可以在多台机器上部署多个Jenkins Master,但这些Master之间没有联系,都是各自把任务交给手下的slaver去执行,没有任何交集。
    也许某个master下的slaver很忙,而另一个master下的slaver却很闲,资源得不到充分利用。
  2.  当其中一个slave宕机之后,该slave上的运行的job任务没有版本重新进行分配,需要用户重新执行。并且slave节点离线之后没有通知管理员。
  3.  当系统业务量比较大的时候业务请求集中在Jenkins Master上,会对Jenkins造成压力,甚至的造成Jenkins服务不可用。
  4.  当有job任务在jenkins Master上队列排队的时候,Jenkins Master宕机后,队列任务不可持久化。
  5. Jenkins Workspace没有自动清理功能,会导致磁盘空间不足,任务执行不了的情况。

基于以上情况,vivo Devops对Jenkins的部署架构进行优化搭建,并且配套了一套Jenkins资源调度系统用于管理Jenkins资源。

二、业界实现

目前业界也包含一些Jenkins 高可用的设计方式,但是并不能完全的满足解决上述问题,比如:

2.1 方案一  Gearman + Jenkins

这是OpenStack团队使用的方案。这个方案使用了gearman, gearman是个任务分发框架。

需要在每个Master上安装好gearman的插件,并配置好能连接到gearman server,同时在每个Master必须建立相同的job。

之后运行任务的流程如下:

  1. gearman worker运行在各个Jenkins Master中等待gearman server分发任务;
  2. gearman client向gearman server发出运行job的请求;
  3. gearman server通知各个gearman worker有任务拉,第一个闲着的worker会接受任务,如果所有的worker都忙,则放入gearman的任务队列,得worker空闲时再分配;
  4. gearman worker闲下来后会从任务队列里取job来执行,执行完之后,将结果发回给gearman server;
  5. gearman server将结果返回给 gearman client。

这样各个salver资源可以得到充分利用,某个master挂掉另外的master可以继续服务。

每个master的slave必须配置一致,否则会造成job调度错误,同时会造成一些资源的浪费。当一个master出现问题,该master的任务不会进行自动重新分配。

2.2 方案二 改造Jenkins的文件存储方式

目前Jenkins的配置文件都是直接在硬盘上以文件形式存储的,你在JENKINS_HOME的个文件夹下能看到各种.xml文件。有些公司在Jenkins上进行二次开发,将Jenkins的数据存储方式改为数据库存储,这样前端可以起多个Jenkins服务,后端连相同的数据库即可。数据库也有比较成熟的高可用方案。

可以达到Jenkins的高可用也就是某个master挂掉另外的master可以继续服务。

需要对Jenkins进行二次开发,使用数据库会降低读取资源效率下降。

2.3 方案三 最简单的Jenkins一主一备模式

平时让Jenkins A机器提供服务,并使用SCM Sync configuration plugin保存数据,JenkinsA机器修改配置后触发Jenkins B更新配置,一旦Jenkins A出现问题挂掉后,切换到备机Jenkins B上。

可以达到Jenkins的高可用,当master宕机后会进行切换到备机上。

会有一批Jenkins备机存在资源浪费,切换master时间过长,会导致有段时间Jenkins服务不可用。

三、vivo Jenkins Scheduler系统目标

由于目前业界的一些实现还不能完全的满足我们目前的需求,所以我们进行了vivo jenkins scheduler系统的设计与实现。该系统需要达到如下的目的:

  1. 提升整个构建服务可靠性时长。
    保证jenkins集群的高可用,解决目前master-slave的单点问题,保证整个构建服务的可靠性时长。
  2. 降低灾难时服务恢复时长。
    ①提供精准流控方式,在jenkins构建出现请求量过高的时候可以进行流控和持久化操作,减少对目前系统的冲击。
    ②当系统压力减少后,放开流控可以快速的对堆积的请求进行分配执行。
  3. 有效分配任务至各个子节点,保证资源的有效利用。
  4. 能保证灾难时的及时切换任务至可用节点上,同时能快速的通知管理员进行处理。
  5. 能进行数据的可视化分析,能提供一系列帮助改善开发效率的视图,比如构建时长报表、构建量报表等。

四、 vivo Jenkins Scheduler设计

该系统我们从两大部分进行了设计,首先,我们不采用原生的Jenkins部署方案,而是采用全master的方式。第二,设计并开发了一套用于管理Jenkins集群的调度系统。

五、底层 Jenkins 工具部署方案

不采用目前单master的搭建方案,采用多master的搭建方案,master下不进行挂载slave机器,任务直接有master进行处理,master之间的关系、任务分配、离线、插件安装等由调度系统进行管理。这样由于vivo Jenkins Scheduler系统为高可用的,解决了目前Jenkins的单点问题。

图片

六、系统架构图

图片

七、系统说明

7.1 API-Gateway

主要提供系统的外部请求,网关系统,功能包含:

  • 权限校验:校验用户发送集群管理系统的请求的权限。
  • 智能路由:接收外部一切请求,并转发到后端的外服上去。
  • 限流:与监控线程配合(当构建请求达到某个阈值时),进行限流操作。
  • API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志。
  • 数据处理:对请求的参数进行数据的转换处理。

7.2 事件中心

是整个系统通信调用的主要模块,采用的是Spring的Event机制实现,主要核心事件如下:

  1. Jenkins注册事件
    (EVENT_REGIST_JENKINS)
    Jenkins启动后,通过自定的插件会向系统发送注册请求时,系统接收到后会触发Jenkins管理模块将Jenkins的信息注册至调度系统中。
  2. Jenkins宕机事件 
    (EVENT_DOWN_JENKINS)    : 
    监控管理轮询检查Jenkins状态,当发现有Jenkins宕机的情况会触发该事件,Jenkins管理模块处理将Jenkins的信息状态设置为不可用状态,从而是任务不能分配至该台jenkins。
  3. 任务从分配事件  (EVENT_JOB_REDO) 
    当Jenkins宕机后,如果该台jenkins上存在未执行完的任务时候,由job监控模块触发,job管理莫管处理,会对该Jenkins上未执行的job进行重新分配。
  4. 任务接受事件  (EVENT_JOB_RECIVE) :
    当job管理模块接受到创建请求,会触发该事件,由job管理模块放入Redis执行队列。
  5. 任务执行事件  (EVENT_JOB_EXECUTE) : 
    job管理模块中的执行线程(10s执行一次,会从Redis队列中弹出任务),弹出任务后触发该事件,由调度中心选取合适的jenkins进行执行。

7.3 调度中心

是整个系统的核心模块,主要的功能是进行执行job时候能选取合适的jenkins进行处理任务,包含两个核心算法:

7.3.1 Jenkins分组算法

每台jenkins都可以使用标签的方式,打上多个标签,比如jenkins可以构建java程序,使用的构建工具可以是maven和gradle,这个时候我们就可以给其打上java、maven、gradle三个标签。

标签的维度主要有以下几个:

  • 标签配置: 判断构建配置是否配置了标签,根据标签选择对应标签的Jenkins,比如配置了(docker等)。
  • 构建语言: 根据构建配置的语言,比如Java、C++、Python、Go等。
  • 构建工具和版本: 比如Maven、gradle、Ant,Cmark、Blade等。
  • JDK版本:比如JDK7、JDK8等。
  • Go语言版本:比如1.15.x.、1.16.x等。
  • GCC版本:如6.x、4.x等。
  • Python版本:2.x、3.x等。
  • 是否存活:判断Jenkins是否存活,如果宕机直接过滤。
  • (可选策略)选择执行过该job的Jenkins,减少下载代码的过程:(第一次构建还是会比较慢,可以采用预执行的方式,在配置构建配置的时候,就预先执行一次,这样在用户执行的时候就使用该job执行过得workspace,减少代码下载的时间)。
  • (可选策略)根据job的构建的平均构建时长,如果构建时长达到某个配置阈值时,优先选择构建器空闲多的Jenkins进行执行,并指出Jenkins的锁定功能。其他的job不允许分配上来。

如果我们给Jenkins打上标签,那么我们就可以使用标签为维度将Jenkins进行分组,并且存入至Redis中缓存,方便后续选取Jenkins用来执行任务:

图片

7.3.2 Jenkins选取算法

当Jenkins分组好了后,我们接受到执行的job的信息就可以使用Jenkins选取算法进行快速的选取合适的Jenkins进行处理job,如下图所示。

其中label子线程、语言子线程……就是我们上面的Jenkins分组的维度,有多少维度,那么这里就会有多少子线程处理。

构建任务进入主线程,然后主线程会按照分组维度分组操作并进行过滤,然后获取到每个分组中合适的Jenkins,再进行取交集(这个时候就获取到可以执行该构建任务的Jenkins了),在判断是否需要经过可选策略,最终得到Jenkins。

图片

7.4 流控管理&队列管理

调度系统中的的任务接受采用的是队列的方式实现,当系统请求量达到阀后,系统将不会进入Redis队列,会将请求持久化至MySQL。后续如果有请求过来,job管理模块会检查数据库MySQL中是否有请求,如果有请求,会将请求放入Redis队列,如果没有请求就会将当前请求放入Redis队列,具体流程如下:

图片

其中基于Redis实现的消息队列的时序图如下:

图片

7.5 回调中心

该模块主要是监控任务的状态,当任务开始执行、中断执行、执行成功、执行失败的时候进行通知业务并存储数据,用于保存构建记录,方便后续数据的统计,用来完成数据的可视化。

八、实施效果

目前该系统已经投入生产环境运行,Jenkins任务已采用调度系统进行调度执行,运行稳定,运行效果。

图片
图片

九、后续展望

随着vivo Jenkins 调度系统的功能慢慢完善,Jenkins的机器也越来越多,目前还大多数运行在虚拟机上,从资源利用率和业务发布效率来看,未来的业务发布形态将会是以容器为主。目前公司也在大力发展k8s的容器生态建设,

所以我们希望将Jenkins工具后期进行容器化、池化,在提高资源利用率和发布效率的同时也可以为用户提供可靠的、简洁的、稳定调度执行。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK