查看原文
其他

轻量化 Jenkins 最佳实践

2018-01-11 石雪峰 DevOps时代

2018年,DevOps 落地是关键词,再好的理念和方法实践都需要工具去完成落地,Jenkins 无疑是 DevOps 落地中的关键工具之一,如果轻装前行,且听国内首批Certified Jenkins Engineer是怎么做的?


作者简介

石雪峰,Certified DevOps Master,Certified Jenkins Engineer,DevOps时代社区核心成员,全开源端到端部署流水线主创成员,DevOpsDays大会金牌讲师。现任某大型互联网创业公司配置管理与工程效率总监,负责公司DevOps与持续交付体系与平台建设。曾任职于华为、尼康,从事持续交付推进及工具链平台建设工作,拥有多年持续交付落地实践经验。

本文整理自Jenkins User Conference China 演讲:石雪峰-《轻量化 Jenkins 高可用实践》(部分)

前言

今天分享主题主要分成三个部分:

第一部分,Jenkins跟持续交付;

第二部分,Jenkins轻量化思路;

第三部分,Jenkins高可用实践。

一、Jenkins 与持续交付

1.1、持续交付构建企业IT价值流

我相信大家都听说过2017DevOps状态报告,作为核心的结果指标,这一组数据也在各种场合下出场率很高,体现了DevOps对于企业业务的直接产出和贡献。

其实简单来说数据体现了两个方面的重要内容:第一点,DevOps可以帮助我们加快企业交付效率,第二点DevOps可以提升交付质量,最终做到快速高质量的持续交付。

当前DevOps是一个非常宽泛的概念集合和知识框架体系,其中持续交付是非常核心的工程实践,来打通软件交付的最后一公里,而流水线Pipelines就是承载持续交付工程实践集合的主要工具。

在今天Jenkins创始人KK的分享中,也提及了Jenkins的未来就是围绕Pipeline和Blueocean来构建可视化的端到端交付流水线,背后的思想就是在于CI向CD的延伸,落地持续交付,实践DevOps,从而帮助企业进行快速的价值交付和灵活应对飞速变化的市场环境。

1.2、流水线打破敏捷之墙

那么,为什么Pipeline可以承载如此重要的业务价值交付诉求,可以帮助大家打破传统的理念,Pipeline有哪些特别之处呢。

我们都知道,远在DevOps诞生之前,敏捷就已经活跃在整个软件行业中,很多时候团队都有改进的意愿,但这样的改进往往局限于各自领域内部,从全局视角来看,整个价值交付流是割裂的,不连续的。

而流水线的出现带来的最显著的改进就是,它可以实现整个持续交付的环节,打通每一个交付链条,从而实现完整的端到端价值交付,提升整个价值流动效率。所以之前有朋友总结流水线的特征,其中最重要的就是端到端。端到端可以让我们从需求一直到交付整个流程全部打通,避免以前各自为战的状态。

1.3、Jenkins驱动持续交付

这张图相信大家也见过很多次了,我们讲Jenkins驱动持续交付。Jenkins作为一个平台,并不是要替代所有原本的工作,它只是提供了一个平台化的能力,帮助大家把散落在各个环节的工具接入进来,实现端到端的交付,让所有人工作在一个界面,关注同一条价值流动。

Jenkins就是持续交付的枢纽,相当于是整个持续交付链条的核心,所有环节都跟Jenkins交付,这也是为什么现在Jenkins的CI/CD对于企业来说越来越重要。

1.4 、CI/CD平台对于企业至关重要

Jenkins这种核心平台的稳定性是我们现在格外关注的一点,假设有朝一日我们的CI/CD做得足够好,但是Jenkins平台挂掉了,后果不堪设想。

之前由于一些不可抗力因素,我们公司的Jenkins受限无法访问,导致的结果是超过两天的时间来修复,这段时间所有软件开发团队都无法实现价值交付,这对于一个成熟的企业来说,是难以估量的损失。

我相信随着各个企业逐渐发展扩大,Jenkins所代表的CI/CD平台起到的作用也会越发重要。所以我们应该花一些心思在平台的可用性上,这也是为什么越来越多的人开始关注Jenkins高可用的问题。

二、Jenkins轻量化思路

2.1、使用jenkins的常见问题

接下来就是我今天所要谈的重点,刚才解释了为什么Jenkins所代表的CI/CD如此之重要,但现实里Jenkins还是会出现这样那样的问题,让人很是担忧,这些问题包括很多方面,比如服务的性能、可用性、拓展性、安全。

我相信大家脑中对Jenkins的问题还有很多,我们不妨回过头来看一看,这些问题根源到底是什么?在哪里?

2.2、我们是如何使用jenkins的

我先帮大家理一理过往我们是如何使用Jenkins的,因为我自己用Jenkins也挺长时间了,算是重度用户群体。在最开始我们不知道Jenkins的时候,大家都在用一些类似的自动化工具或者脚本工具。直到有一天有人告诉我,有一个工具叫做Jenkins,它是研发的管家,可以帮助我们实现自动化任务调度,统一管理任务执行情况。

所以Jenkins最开始引入团队的时候可能更多的相当于自动化工具平台,当然在这一点上Jenkins是比较称职的,也的确减轻了很多手动工作。我相信到现在很多人还是把Jenkins作为自动化调度平台使用。

随着Jenkins逐渐为人所知,我们突然发现Jenkins有一个非常强大的特点在于它有很多插件,如果有人号称没用过Jenkins插件,那应该是一件比较奇怪的事情。

在今年的Jenkins World大会上也提到,现在Jenkins的插件已经超过1600个。如此庞大的插件能力大大拓展了Jenkins的能力,减少我们平常琐碎的工作,很多任务只需要简单配置即可完成。

在这样的背景下我们开始疯狂的搜插件,想要实现一些功能的时候我们就会不自觉的去查查有没有相应的插件能替我们做这些事情。

问题是插件在很多时候并没有完整的满足使用者的需求,有的时候可能需要两三个插件一起使用才能覆盖我们的完整需求。

这就是为什么Jenkins上面的插件会越来越多。同时因为很多插件是个人爱好者维护、开发的,而Jenkins内核也在不断的更新发展,这就导致很多插件处于长期无人维护的状态,甚至跟最新的Jenkins版本都无法适配,当我们继续使用这样一些插件的时候显然会出现一些问题。

随着插件越来越多,Jenkins的功能也越来越强大,我们会依赖于Jenkins做更多的事情,这是理所应当的。自然而然团队也会有更多的人开始使用Jenkins,从而导致Jenkins上的用户也变得越来越多,Jenkins管理的节点也越来越多。这就是我们使用Jenkins日常的路径。

2.3、Jenkins系统固有问题

所以我们期望Jenkins无所不能,我们希望Jenkins变得更强大,我们希望Jenkins帮我们承担更多的工作,我们希望Jenkins集成更多的能力。似乎我们从来没有考虑过Jenkins的感受,那么回过头来让我们关注Jenkins自身,看看Jenkins自身包含哪些潜在的问题?

  • 第一,Jenkins是一个单体应用,没错,Jenkins是一个典型的JAVA单体应用,而且到现在为止依然是一个单体应用。在当今微服务思想满天飞的背景下,单从这一点来看其实Jenkins还有很多改进的空间。

  • 第二,Jenkins采用的是本地文件存储。我不知道大家有没有看过Jenkins目录结构,所有的内容都是通过文件保存的。这会带来什么问题呢?一是会带来非常大的IO压力,因为系统会一直读写磁盘上的文件。另外对高可用,对同步备份带来了一些瓶颈和问题。传统上我们使用数据库的时候有非常多成熟的方案帮助我们去做数据分层或者动态负载均衡,多节点等等。因为Jenkins目前使用的是基于本地文件的存储方式,所以这些优势对Jenkins难以起到作用。

  • 第三,大量碎片文件。在Jenkins上保存了很多的数据,尤其是像日志、归档产物等都是保存在Jenkins的Master节点上的,即便Jenkins采用了分布式的架构设计,实际上任务执行的结果还是会回传到master上,所以分布式并不能解决这个问题,这也是为什么如果我们不做适当的清理的话,Jenkins上的数据会持续累计,越来越多,产生大量的文件。之前我们的生产服务器就有一个案例,Jenkins没有任何征兆的就挂掉了,而且重启后依然会挂掉,分析这个问题的时候我们发现,是一个用户任务的脚本存在缺陷,所以导致了无限循环,输出日志超过几十G,直接就把master给拖挂了,所以如果没有保护机制,master就相对于在所有任务面前裸奔,随便一个用户任务就足以搞垮整台服务器,这是非常恐怖的一件事情。

  • 第四,Jenkins启动很慢。你们有没有想过Jenkins在启动的时候都做什么?关于这个事情我昨天特意咨询了一下Sam。他告诉我,简单来说Jenkins在每次启动的时候会做以下几件事:1,加载Jenkins主要的配置,也就是Jenkins的系统配置;2,会加载所有插件,插件越多,加载的内容也就越多,导致Jenkins性能越来越慢。不仅是插件,还有所有的任务配置,如果Jenkins无限扩大,性能会越来越有问题。这些都是Jenkins系统的固有问题,导致在大规模企业应用的时候会出现性能瓶颈。

2.4、重新审视Jenkins架构

我之前也把这个问题抛给了Jenkins的创始人KK,他告诉我一个非常好的消息,也就是Jenkins的架构优化会作为2018年非常重要的里程碑,我们也非常期待Jenkins的架构演进,从官方解决以上提到的各种固有问题。总之现在Jenkins社区也越来越关注Jenkins的性能问题,因为大家都知道Jenkins是企业的核心服务。

我们可以期待明年的版本升级,虽然时间已经非常临近了,但是依然要给Jenkins社区点赞。其实我们也明白,想去改变一个历史悠久的单体应用架构,这是需要花费大量的精力和决心的。

放这张图我想表达的意思是,不要让Jenkins陷入重围,Jenkins可以作为我们软件交付的管家,可以帮助我们做很多事情,但是你不要让它承载更多的功能,这样会导致Jenkins不堪重负。谁也不希望Jenkins摆在这个位置,虽然很酷。

我们不希望Jenkins承载更多的东西,这也是为什么我提出轻量化Jenkins的概念,初衷在于给Jenkins减负。

接下来我们看一看Jenkins的系统架构。我花了很长时间也没有找到官方的系统架构图,所以没办法自己动手画了一个。

Jenkins系统架构包括什么?

  • 第一Jenkins是一个分布式的系统,在右上角就是Jenkins的Master,Jenkins的Master包括了Jenkins Core,Jenkins Core提供了很多核心能力。

  • 第二个是队列能力,我之前也花时间研究了一下队列的实现机制,Jenkins在任务调度的时候倾向于使用之前成功执行任务的节点,这背后的原理在于,希望帮助我们节省很多的缓存和环境准备时间,但由于并非是按照实时资源负载进行调度,导致的结果就是各种节点闲的闲死,忙得忙死。

  • 第三块就是Build,自动化构建是Jenkins最初提供出来的能力,这个不用多说,大家每天都在打交道。插件系统刚才也提到过,对于插件Jenkins提供了Update center来集中管理更新维护插件,用于扩展Jenkins的功能图谱,值得注意的是,所有的插件也是保存在Master上的,这个不是分布式的。

左下角是外部系统,跟Jenkins本身并没有直接的关系,但是因为Jenkins插件的存在帮助我们简单的集成外部系统,打通彼此的信息和能力,这也是上午乐神在发布流水线2.0产品的亮点功能之一,就是实现无缝的系统调用和集成。

2.5、Jenkins的核心能力

我们再来看一下Jenkins的核心能力是什么?这其中有哪些是不可替代的,或者替代成本非常高的内容。

  • 第一个就是Jenkins Core,Jenkins Core就是Jenkins最核心的内容,我们常说的Jenkins 1.X,2.X版本,其实说的就是Jenkins Core的版本号,这里面包含了Jenkins的核心架构,服务等。

  • 第二点是插件,就如同刚才介绍的那样,每件事情都有两面性,我们受益于插件的同时,也受困于插件,如何平衡选择恰到好处的插件,既不会导致系统负担过大,也能很好的优化日常工作效率,这应该是一个长期的话题。

  • 第三点是队列和资源调度。实际上这是Jenkins提供的一个非常重要的核心能力,包括队列等待机制和任务调度等,虽然目前的调度算法不是特别智能令人满意,但依然可以满足基本的使用要求。

  • 第四点就是Jenkins2.0所带来的Pipeline和Blueocean。这是Jenkins未来的发展方向,也是驱动Jenkins持续交付的源动力和最佳实践的载体,很高兴这次邀请到了CloudBees的Sam过来和我们面对面交流,在他的分享中提及了很多Pipeline的内部实现机理和优化建议,我个人也受益匪浅。

2.6、轻量化解决之道

那么轻量化的概念到底是什么意思呢?我认为其核心思想在于少即是多,即保留Jenkins的核心能力的基础上,将更多的冗余任务代理给外部服务,保证Jenkins自身的清爽和高效对整个企业的CI/CD系统而言至关重要。

所以我们要分担Jenkins身上的压力,不让他陷入重围,让这个管家更好的为我们服务,同时也给他找一些帮手。

那么在实践Jenkins轻量化解决之道的过程中,我总结了一些套路和体系,其中以下八点内容希望可以帮助大家解决一些实际生产工作中Jenkins的性能问题,同时扩展大家的思路,共同探索Jenkins应用的最佳实践。

2.6.1、最佳实践一、分布式架构。

这点其实没什么太多好说的,因为Jenkins原生就支持分布式架构,只不过在平常交流的过程中,我发现很多团队都习惯把任务调度在master节点上,结果就是Jenkins master既当爹又当妈,在任务规模不大的时候其实还好,但是随着规模的扩大,这样做毫无疑问会给Jenkins带来诸多问题。

当然有时候也不怪大家,毕竟Jenkins默认的行为就是使用master节点,当我们新建任务不指定工作节点的时候,Jenkins会自动替我们寻找可用的节点,这里面当然就包含master。但是作为最佳实践而言,保持master的独立性,将所有消耗系统资源的任务调度到slave节点执行,这是毫无疑问的。

在企业级Jenkins使用过程中,master节点应该只承担任务管理和调度工作,管理员可以在系统层面禁用master节点的工作线程池,或者修改系统默认节点配置,从而避免由于误操作等导致的任务堆积,充分发挥分布式系统的扩展能力。

2.6.2、最佳实践二、动态节点挂载。

所谓动态节点,就是只有在需要的时候才生成这个节点,任务完成后自动销毁,平时是不存在的。相比于传统的通过建立长连接的方式管理节点,这种方式减少了Jenkins用来维持连接,保持节点间联系没有意外断掉的成本,按需创建,所见即所得。

为什么要动态的挂载节点?一方面是刚才提到的动态资源,另外一方面持久化节点会存在一些问题,比如测试需要一些特殊的设备,这些设备往往放在他们自己的实验室里面,当这些设备的IP地址发生变化的时候Jenkins Master是无法感知并修复这个问题的,所以通过动态节点,一定程度上可以减少僵死节点进程,清理无用节点连接,最终还是关注Jenkins的性能表现。

2.6.3、最佳实践三,资源调度代理。

在上次818DevOpsDays大会上,我分享过这个话题,很高兴在今天上午主会场的分享中,很多嘉宾包括硅谷来的同学都在讲通过容器调度平台动态的生成节点。在这点上我们跟世界处在同一条起跑线上,我们是在做同样一件事情,去摸索同一个解决之道。

我刚才提到资源调度是Jenkins的一个核心能力,但是他并不完美,因为种种因素,所以我们需要找到一种更高效的方法。

事实上对于每一个任务而言,他所需要的资源数量都是不一样的,但是对于Jenkins是以任务为单元进行调度,Jenkins并不知道这个任务到底要消耗多少资源,只能硬性的指定一个可用的节点。如果一个节点的资源消耗已经非常大,但是仍然有可用的任务进程池的话,Jenkins依然会把任务调度到同样一台机器上,这就导致了资源冲突,从而引发性能问题。

而容器调度平台天生就支持资源的精细化管理和基于复杂算法的调度能力,甚至可以按照一定的指标来动态的扩容缩容,要实现这个能力是相当复杂的,所以不妨把这个能力提供给Jenkins,而Jenkins只需要关心任务调度即可。

这样的话我们就可以受益于现有的非常优秀的容器调度平台,使用它们的算法将所有资源池化。当我们把所有的服务器都接入容器调度平台后,我眼中只剩下一些CPU,一些内存或者一些计算资源。这也是我们帮Jenkins减负的重要途径,通过资源调度平台把资源调度完全剥离出去。

2.6.4、最佳实践四点,任务按需触发。

最早我们在使用Jenkins的时候,通常是通过手动或者定时的方式触发任务,因为Jenkins的定时任务采用了linux通用的cron语法,所以大家写起来没有任何压力。这样做的结果就是很多任务都在定时的跑,即便代码或者配置没有任何变化,也会执行完整的任务流程,这就给服务器资源带来了冗余浪费,如果想减缓这样的问题,往往需要我们在脚本里面执行各种判断,如果没有任何变化则直接退出不执行,但即便如此,任务还是会按时触发起来。

另外一种方式是poll SCM,这个方式跟定期调度没有太多区别。但是它天生会帮我们检查代码有没有变更,如果没有变更任务是不会执行的。大家注意这个地方使用的是“poll”这个单词,这个单词本身有选举投票的意思,也就是按需执行的含义。

到现在我相信很多同学已经把持续集成平台跟SCM平台做了集成。也就是通过配置过滤不需要的分支,不需要的提交,只有满足了一定条件任务才会触发。这就意味着这种任务更加准确和有效,比之前的无限循环更加合理。其实在同样的资源下,做更多有意义的事情,这本身也是一种减负。

不仅如此,我们在提到持续集成的时候,最显著的一个特征就是每次提交都要触发一次完整的流水线,如何去做呢?就是通过Webhook的方式,在流水线2.0的最佳实践里面已经实现了这种方式,也欢迎大家参考。

2.6.5、最佳实践五,合理的使用插件。

关于如何挑选插件:

  • 第一个原则,Jenkins企业版有一个非常重要的功能,就是帮助企业版用户来验证每一个插件是否匹配,功能完好,以及是否有潜在漏洞等,这是Jenkins企业版的卖点之一,对于我们来这就是一个很好的参考。另外在安装Jenkins的时候,官方安装向导里面也提供了推荐的插件集合,这个列表可以在GitHub上找到,总之第一点就是看一看Jenkins企业版在用的东西,跟随官方版本总不会出太大的问题。

  • 第二个原则我个人认为插件这个东西够用就好,之前很多同学都有一些强迫症,看到插件有更新了,一定要批量更新。但原本非常稳定的插件或者稳定的功能因为插件没有经过完好的测试,导致原本能用的东西一升级就挂掉了,到那个时候只能恨自己手贱了。如果说一个插件能满足现有的需求,没有明显的瓶颈点,或者Jenkins官方没有提出相关安全漏洞,我建议大家可以继续使用,而不是频繁的升级,另外每次升级的时候要关注一下到底改了什么,改的东西跟你有没有关系,比如插件提供了AWS的支持,但实际上用的阿里云,这就没有必要跟随版本升级了。

刚才Sam也提到,很多时候插件不一定比原生命令好用,实际上正好相反,插件做的事情无外乎帮我们包了一层,提供友好的用户界面。核心的工作如果用简单的脚本可以完成,为什么加载一个插件,为什么要在Jenkins启动的时候再做一些额外的负担呢。

还有就是大家有没有做过一个尝试?把一个运行中的Jenkins实例的插件目录全部干掉,猜测下会发生什么?什么也不会发生,因为Jenkins在运行的时候已经把所有插件都加载到内存里边,所以即便把目录直接干掉,对他来说没有任何影响,下次重启的时候才会报错。这也是一个非常大的理由,为什么我们要合理的使用插件,如果原生的命令可以满足这些功能,建议大家用原生的命令实现,这也是所谓少即是多的概念。

2.6.6、最佳实践六,任务动态的生成。

大家可以猜猜这是哪家企业的Jenkins?我觉得Sam应该非常熟悉,因为这是Jenkins官方的Jenkins。我们来看一看Jenkins官方自己是怎么用Jenkins的,很明显的一点就是所有官方维护的任务已经完全Pipeline化了,这是一个非常明显的信号,是时候开始拥抱Pipeline了。

第二个,我们这边用的比较少一些,这个小黑书的图表,代表了GitHub的Multibranch Job,不知道有多少人用过这个功能。核心理念在于所有的任务都是动态生成的,因为Multibranch Job会扫描版本库中每一条代码分支,并自动创建Jenkins任务,你没有必要去手动创建,一切都是动态生成的。而且当你改变代码库,新建一个分支,减少一个分支,它也会自动更新,主要就是用到了Jenkinsfile,也就是流水线即代码的能力,剩余的就交给Multibranch Job来实现就好了。

而且Sam也提到了一个非常强大的黑科技,不仅一个代码库可以支持多个Multibranch Job,实际上多个Multibranch Job可以共用同一个代码库,这里面就用到marker的功能。所以作为一个Jenkins管理员,我最纠结的就是有一个任务很久没执行过了,到底要不要删除或归档。当我去问开发人员或者项目经理的时候,他们的回答的是可能用,说了跟没说一样。那么如果我们都用Multibranch Job的方式就不存在这种情况了。

2.6.7、最佳实践七,Master水平扩展。

上午KK给大家提供了一个关于PayPal的案例,我没记错他们公司使用了2500个Jenkins Master。很多业界最佳实践也在推荐多Jenkins Master,而不是使用一个Jenkins Master。为什么会有这样的结果,其核心的理念又是什么呢?实际上当Jenkins Master的水平扩展做的足够好,我们有后台机制保证服务的连续性,其实对于用户来说,他们并不关心后台实现到底是一个master还是多个master,他们关心的是任务本身和过程中的数据。当我们可以水平扩展master,那么单体性能的问题就不再那么尖锐了,所以多个Jenkins Master可能也是我们未来的发展趋势。

2.6.8、最佳实践八, 外部系统集成。

这幅图是XebiaLabs提供的DevOps元素周期表,里面罗列了非常非常多工具,多到认不过来。Jenkins也在其中,就是28号元素。

其实我想表达的是,Jenkins替我们做了很多工作,但却没有办法覆盖元素周期表里边所有的事情。我个人理解对Jenkins正确的使用姿势,更多的还是要把各种各样的工具和系统插接上来,而不是用Jenkins直接替代所有的工具,让Jenkins做所有的事情。

我们可能要关注如何把这些系统跟Jenkins做无缝集成,这也是我们未来比较大的一个挑战。

以上是石雪峰老师的《轻量化 Jenkins 高可用实践》的上半部分,明天会发布下半部分,关于Jenkins 高可用的实践方法


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存