Jenkins目前在单台Vm虚机上基于docker容器化支配,当Jenkins用了一段韶光往后,创造每天的Jenkins 构建次数日益剧增,逐渐涌现了Jenkins访问速率慢,卡顿,乃至直接终止做事相应的情形。由于底层是基于Vm,那么申请了一些物理资源,暂时办理了问题。
随后,随着几个项目组的构建需求频繁增长,每天Jenkins的构建次数会超过500次,此时显然原有支配构造已经不足支撑了。Jenkins做事各种卡去世,无相应白屏频频发生。不过涌现这个问题,也是猜想之内,但是便是相对棘手了些。
由于现有做事器资源相对有限,直接开几台高配置Vm,可能会比较大略粗暴地办理问题,但成本相对较大,也不利于资源利用。由于Jenkins事情日韶光也分忙时闲时。

1. 痛点梳理
构建任务高峰期,Jenkins做事频发不可用状态做事虚机资源有限,不能随意调用空闲资源Jenkins 做事器宕机后须要人工手动重启2. 思路剖析
A. 传统Master-Slave模式
增加3台虚机,在现有Jenkins做事上创建多个Slave,绑定新增的这几台虚机上,通过Master-Slave的形式来考试测验办理问题
上风
通过增加新的vm来办理问题,问题理论上可以得到办理韶光的技能壁垒较低,韶光较短劣势
须要新申请虚机资源,对付资源调度分配上会有一定风险3台Slave在Jenkins构建闲时也会占用资源,导致资源摧残浪费蹂躏每个Slave的职能会根据业务需求随时调度,Slave的环境配置后期掩护本钱较高当Jenkins构建任务较多,Slave分配不均的时候,也会存在排队征象B. 基于K8s动态Slave模式
基于K8s集群,Jenkins Master 接到构建任务后会动态在集群中的一个事情节点上拉起一个Jenkins Slave Pod来干活儿,活儿干完后可及时开释Pod。
上风
基于云原生现有K8s集群来办理问题,充分的利用现有资源,无需再申请新虚机Slave可在构建任务来之时动态创建,事情结束后自动销毁,开释资源可通过K8s原生来管理Jenkins的调度策略,防止Slave调度分配不屈均通过云原生Chart来管理Jenkins配置,后期比较利于掩护、扩展Jenkins 小概率意外宕机场景,通过K8s的机制可以自愈劣势
增加了系统繁芜度有一定技能壁垒实现须要韶光通过团队共识,果断采取基于K8s动态Slave模式,以云原生的思路办理问题,这样不但可以办理Jenkins的做事资源紧缺征象,还能充分的利用K8s集群中的事情节点资源,云原生的形式也利于后期扩展和掩护。操持先采取一个小型K8s集群(1m3n)来考试测验办理问题。
三、Jenkins事情事理简述1. 启动加载
Jenkins 启动时,会读取本地持久化目录数据,加载到内存。启动后,我们对Jenkins的上层用户操作,实际上都是对内存中数据状态的修正,Jenkins会异步刷盘,数据持久化。这样设计可应对大规模客户端操作要求,运行起来会更加节约I/O,性能更快。
2. 主从事情通信机制
https://github.com/jenkinsci/remoting
基于Remoting通信框架,通过TCP (JNLP protocols) 实现长连接序列化传输,master来向其对应注册的slave发送指令,slave异步处理后返回。
MasterSlave参考资料https://cloud.tencent.com/developer/article/1773184?from=article.detail.1773183
四、Dynamic Slave 事情事理1. 观点定义
基于K8s集群,Jenkins Master 接到构建任务后会动态拉起一个Jenkins Slave Pod来干活儿,活儿干完后可及时开释Pod。
2. 设计上风
动态伸缩合理的利用资源,每次运行 Job 时,会自动创建一个 Jenkins Slave,Job 完成后,Slave 自动注销并删除容器,资源自动开释,而且 Kubernetes 会根据每个资源的利用情形,动态分配 Slave 到空闲的节点上创建,降落涌现因某节点资源利用率高,还排队等待在该节点的情形。
做事高可用当 Jenkins Master 涌现故障时,Kubernetes 会自动创建一个新的 Jenkins Master 容器,并且将 Volume 分配给新创建的容器,担保数据不丢失,从而达到集群做事高可用。
扩展性好当 Kubernetes 集群的资源严重不敷而导致 Job 排队等待时,可以很随意马虎地添加一个 Kubernetes Node 到集群中,从而实现扩展。
五、Docker in Docker1. 设计思路
我们都知道,基于k8s拉起的做事,实际上都因此Pod形式存在的,而Pod是个容器组,终极做事实际因此Pod内的Container来支撑运行的。那么针对Slave的运用处景,Container该当如何设计?
为了不入侵宿主机Node上的docker做事,还要在Node上的Pod中利用docker做事,那么目前最佳的思路是要引入Docker in Docker技能来完成。
2. Docker in Docker
本篇文章暂不讲Dind模式的观点,后续篇幅我会补充我对Dind模式是如何理解的。那么我们先来看下标准的Dind利用办法,也便是Slave的内部设计
A. 容器职能
上图中,我们看到,Slave内部引入了3个容器,分别是JNLP,docker daemon和 docker build ,先来先容下这3个容器的职能
JNLP container卖力与Jenkins Master建立TCP通信,吸收l来自Master发送过来的所有构建指令
Docker Daemon containerdocker的事情事理大略说是通过C/S模式进行的,而docker daemon便是server端。
docker做事启动时,本地环境的client会和server端建立一个tcp连接,默认端口号是2375(如果利用TLS的话,则为2376),当我们运行一个docker指令时,这条指令会被发送到docker daemon,然后再返回干系信息。
Docker Build container这里才是我们真正用到的build server,我们构建项目用到的各种环境(java、go、php …)都可以把环境的根本信息放到这里面来,然后docker build 来构建。
B. Dind设计上风
Pod网络可以直策应用pod网络,通过pod的 ip可以直接访问到内部容器暴露的做事端口。
做事可用性由于是docker daemon,那么容器内部会建立一个守护进程,经由实际测试,用原来比较丑陋的『 kill 1』的命令,是无法终止它的,那么就天然担保了docker做事的可用性。
Pod清理办法Pod的清理交给k8s管理,如果特定场景下须要自清理,那么emptyDir是个不错的选择。
资源调度和利用情形Cpu和内存申请交给Pod, 可通过k8s机制来管理container的内存和cpu利用。
六、总结经由一番折腾,上线后完备Cover住目前项目组的构建场景,构建速率明显加快,同时最大化资源利用。总体来讲,基于K8s之上的Jenkins动态Slave的架构体验还是不错的,后续有韶光我会连续更新本帖,把实现过程中的一些详细操作呈现给大家。当然,如果您有问题,也请在评论区给我留言。