作者:vivo 互联网服务器团队- Wu Qinghua

本文从目前业界实现Jenkins的高可用的实现计划,剖析各计划的优缺点,引入vivo目前应用的Jenkins高可用计划,以及目前Jenkins资源的调度计划的设计实际和目前的落地运行成果。

一、前言

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

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

  1. Jenkins自身是单体的,即只能有一个Jenkins Master。尽管你也能够在多台机器上部署多个Jenkins Master,但这些Master之间没有分割,都是各自把工作交给手下的slave去执行,没有任何交加。兴许某个master下的slave很忙,而另一个master下的slave却很闲,资源得不到充分利用。
  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工具前期进行容器化、池化,在进步资源利用率和公布效率的同时也能够为用户提供牢靠的、简洁的、稳固调度执行。