一、前言现在很多企业都在使用Jenkins进行持续集成,所有业务端都依赖Jenkins。vivoDevops也使用Jenkins进行持续构建。如何部署Jenkins服务?保证服务的高可用尤为重要。以下是Jenkins目前存在的一些问题。Jenkins本身是单一的,即只能有一个JenkinsMaster。虽然也可以在多台机器上部署多个JenkinsMaster,但是这些Master之间是没有联系的。他们都将任务交给下属的slaves去执行,没有任何交集。可能一个master下的slaver很忙,而另一个master下的slaver很闲,资源没有得到充分利用。当其中一个slave宕机时,slave上正在运行的job任务不会被重新分配,需要用户重新执行。并且从节点下线后管理员没有得到通知。当系统业务量比较大时,业务请求集中在JenkinsMaster上,会给Jenkins带来压力,甚至导致Jenkins服务不可用。job任务在JenkinsMaster上排队时,JenkinsMaster宕机后无法持久化排队任务。JenkinsWorkspace没有自动清理功能,会导致磁盘空间不足,任务无法执行。基于以上情况,vivoDevops优化构建了Jenkins部署架构,提供了一套Jenkins资源调度系统来管理Jenkins资源。2、在业界的实现目前业界也有一些针对Jenkins的高可用设计方法,但都不能完全解决上述问题。例如:2.1方案一Gearman+Jenkins这是OpenStack团队使用的方案。该解决方案使用gearman,这是一个任务分发框架。需要在每个Master上安装gearman插件,并配置连接gearman服务器。同时,必须在每个Master上建立相同的工作。之后运行任务的流程如下:gearmanworker运行在各个JenkinsMaster中,等待gearmanserver分发任务;gearman客户端向gearman服务器发送运行作业的请求;gearmanserver通知每个gearmanworker有任务要拉取,第一个空闲的worker会接受任务,如果所有worker都忙,则将其放入gearman的任务队列,在worker空闲时分发;gearmanworker空闲时会从任务队列中取出job执行,执行后将结果返回给gearmanserver;gearmanserver将结果返回给gearmanclient。优点:这样可以充分利用每个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一主一备模式,通常是让JenkinsA提供服务,使用SCMSync配置插件保存数据。JenkinsA修改配置后,会触发JenkinsB更新配置。一旦JenkinsA出现问题挂了,就切换到备机JenkinsB。优点:可以实现Jenkins的高可用。当master宕机时,会切换到备机。缺点:会有一批Jenkins备机浪费资源,切换master的时间过长,会导致Jenkins服务一段时间不可用。3.vivoJenkinsScheduler系统的目标针对目前业界的一些实现不能完全满足我们目前的需求,我们设计并实现了vivoJenkinsScheduler系统。该系统需要实现以下目标:提高整个施工服务的可靠性。保证jenkins集群的高可用,解决目前master-slave的单点问题,保证整个构建服务的可靠性。在发生灾难时缩短服务恢复时间。①提供精准的流控方式,在Jenkins构建请求量过大时可以进行流控和持久化操作,减少对当前系统的影响。②当系统压力降低时,释放流量控制可以快速分配执行累积的请求。有效地为每个子节点分配任务,保证资源的有效利用。可以保证在发生灾难时及时将任务切换到可用节点,同时可以快速通知管理员进行处理。它可以对数据进行可视化分析,并提供一系列有助于提高开发效率的视图,例如构建时间报告和构建量报告。4.vivoJenkinsScheduler的设计我们从两部分来设计系统。首先,我们没有使用原来的Jenkins部署方案,而是采用fullmaster的方式。其次,设计开发用于管理Jenkins集群的调度系统。5、底层Jenkins工具部署方案没有采用目前的单master构建方案,而是采用多master构建方案。从机不挂载在master下,任务由master直接处理。Master之间的关系、任务分配、离线、插件安装等都由调度系统管理。这样,由于vivoJenkinsScheduler系统是高可用的,解决了目前Jenkins的单点问题。6.系统架构图7.系统描述7.1API-Gateway主要提供系统的对外请求,网关系统,其功能包括:权限验证:验证用户向集群管理系统发送请求的权限。智能路由:接收所有外部请求,转发给后端外部服务器。限流:配合监控线程(当构建请求达到一定阈值时)进行限流操作。API日志统一收集:类似于aspect切面,记录接口进入和退出时的相关日志。数据处理:对请求的参数进行数据转换处理。7.2事件中心是整个系统通信调用的主要模块,由Spring的Event机制实现。主要核心事件如下:Jenkins注册事件(EVENT_REGIST_JENKINS):Jenkins启动后,通过自定义插件向系统发送注册请求,系统收到后会触发Jenkins管理模块注册Jenkins信息到调度系统。Jenkins停机事件(EVENT_DOWN_JENKINS):监控和管理轮询以检查Jenkins的状态。当发现Jenkins宕机时,会触发该事件。Jenkins管理模块会将Jenkins的信息状态设置为不可用状态,这样就无法将任务分配给本站jenkins。任务从分配事件(EVENT_JOB_REDO):当jenkins宕机时,如果jenkins上有未完成的任务,会被job监控模块触发,job管理不予处理,会重新执行on上未执行的job詹金斯分发。任务接受事件(EVENT_JOB_RECIVE):当作业管理模块收到创建请求时,会触发该事件,作业管理模块将其放入Redis执行队列中。任务执行事件(EVENT_JOB_EXECUTE):作业管理模块中的执行线程(每10s执行一次,任务会从Redis队列中弹出),任务弹出后触发事件,调度中心选择适当的詹金斯执行。7.3调度中心是整个系统的核心模块。它的主要作用是在执行job的时候选择合适的jenkins来处理任务。它包括两个核心算法:7.3.1Jenkins分组算法。多标签,比如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的平均构建时间,如果构建时间达到一定的配置阈值,优先选择空闲builder最多的jenkins执行,并指出jenkins的锁功能。不允许分配其他工作。如果我们给Jenkins打上标签,那么我们就可以通过标签将Jenkins作为一个维度进行分组,存储到Redis缓存中,方便后续选择Jenkins执行任务:7.3.2Jenkins选择算法当Jenkins被分组后,接收执行作业的信息,我们可以使用Jenkins选择算法快速选择合适的Jenkins来处理作业,如下图所示。其中,标签子线程,语言子线程……就是我们上面Jenkins分组的维度,有多少个维度,那么这里要处理多少个子线程。构建任务进入主线程,然后主线程会根据分组维度进行分组过滤,然后在每个组中获取合适的Jenkins,然后进行交集(此时可以执行构建任务的Jenkins会得到),在判断是否需要走可选策略后,最终得到Jenkins。7.4流控管理&队列管理调度系统中的任务接受是以队列的形式实现的。当系统请求量达到阈值时,系统不会进入Redis队列,将请求持久化到MySQL。如果后面有请求,作业管理模块会检查数据库MySQL中是否有请求。如果有请求,它会将请求放入Redis队列中。如果没有请求,它会将当前请求放入Redis队列中。具体流程如下:实现的消息队列时序图如下:7.5回调中心该模块主要监控任务的状态。当任务开始执行、中断执行、执行成功、执行失败时,通知业务并存储数据,用于保存施工记录,方便后续数据统计,完成数据可视化。八、实施效果目前系统已在生产环境上线运行,Jenkins任务已被调度系统调度执行,运行稳定有效。9、后续展望随着vivoJenkins调度系统功能的逐步完善,越来越多的Jenkins机器运行在虚拟机上。从资源利用率和业务发布效率来看,未来的业务发布形式将以容器为主。目前公司也在大力发展k8s的容器生态建设,所以希望后期能够将Jenkins工具进行容器化和池化,提高资源利用率和发布效率,同时为用户提供可靠的,简洁稳定的调度执行。
