转载

手把手教你Jenkins开发进阶,加速DevOps落地

目录:

Maven

DirectoryStructure

Extensions

PageElements

Howto debug

UnitTest

Questions

今天主要想跟大家分享Jenkins插件的开发;以及关于开源的内容,个人觉得开源这件事情挺有意思。

手把手教你Jenkins开发进阶,加速DevOps落地

这个老头大家都很熟悉了,长的变形金刚的样子,我估计官方的意思他身上的装备也就是插件。如果你安装一个干净的Jenkins,可能基本上都干不了。

我们知道Jenkins可以做很多的事情,比如说我想编译一个程序,但是又不清楚,需要装哪些插件,怎么办呢?你可以去 https://plugins.jenkins.io/ 搜索,比如搜索JAVA,然后会看到很多插件,可以从中选择一个。那么多插件,该选哪一个呢?我有个建议,可以看它的下载数,以及研发出来的时间、是否稳定,以及版本的迭代过程。如果版本迭代的快,说明这个社区比较活跃,遇到问题可能会有人帮你。有时候,插件的发起人可能不再维护。如果你看到最近一次的提交记录是三年前,就要慎重考虑一下。

手把手教你Jenkins开发进阶,加速DevOps落地

Maven

这是我下面介绍的内容:首先是Maven,然后是目录结构。Jenkins本身没有什么实用的功能,基本上都是留出扩展点来做。比如,代码的拉取。你装一个干净的Jenkins,是无法拉取代码的,所以要支持的话,就需要安装插件。因此,要开发一个插件,例如优化任务队列,有的机器很忙,有的很闲,你可以借助扩展点,自定义队列中的任务排序规则。比如,想要实现任务的插队。后面会介绍怎么找扩展点,以及对应的参考实现类。

手把手教你Jenkins开发进阶,加速DevOps落地

还有页面元素,这要看插件的情况。需要页面的地方不多,但有一些肯定要有页面,比如说构建配置,需要一些参数。你得知道怎么写这个页面,Jenkins出现都超过十年了,用的框架技术比较古老,资料相对匮乏。

写代码通常很快,而调试比较慢,尤其是遇到很诡异的问题时。还有单元测试,如果希望修复某个开源插件的漏洞,单元测试一定是必要的;而如果是Jenkins核心工程的话,要求更加严格。需要上线、发版时,跑一遍单元测试会比较放心,会少一些低级错误。

之所以可以做到在单元测试上要求比较严格,是由于Jenkins允许对页面进行UI测试,当实现一个扩展点,基本上把手工测试的东西全覆盖。

一点Jenkins插件都没有接触过的同学也没有关系。创建一个工程,不需要知道应该先干什么,后干什么,只要知道骨架即可。很多工程,都有特定的目录结构,和一些配置文件。而骨架,就是把一些模板性的东西直接生成出来。通过执行Jenkins的Maven骨架命令,会列出五个选项。

这是他的目录结构,包括Java代码、页面、单元测试等等。

这个是pom文件,关键是打包的方式,是hpi这也是插件文件的后缀名,然后可以选一个版本。

手把手教你Jenkins开发进阶,加速DevOps落地

Jenkins 四大扩展点

Jenkins有很多扩展点,我这里列了四个。点击下面的链接,可以看到托管在Jenkins上所有插件的扩展点列出来,点击某个扩展点,能看到有哪些类实现了这个扩展点。

第一个是Builder,如果实现这个扩展点,Freestyle类型的Job中构建区域下拉框就会多出一个选项来。

Recorder是构建后的一个扩展点,部署、测试都属于构建后的。Builder可以添加多个,而Recorder用于记录信息,例如:成品归档,或者Git发布。

这个是页面,Stapler。它的文档比较少,所以我建议一个做法,就是看Jenkins源码里面是怎么写的,就是这个目录。如果写过JSP的话,应该会比较好上手,就是一个标签,包起来就行了。其他的比如说经常看到的保存、应用按纽。

Jenkins Debug 调试

再来看一下如何调试Jenkins插件。一些简单的问题,通过查看日志也许能猜到问题所在。然而,遇到复杂的问题,可能就需要用到Java断点调试的功能了。

插件功能完成后,有几种方法可以看到效果:在Jenkins的插件管理页面离线安装、在插件工程根目录中执行mvn命令。离线安装的方式,不建议在开发调试过过程中使用,因为效率比较低——每次修改都需要重新打包、安装、重启。而通过执行命令的方式,则可以实现所见即所得的效果,不需要频繁地启动。

如果遇到一些问题需要在特定环境中才能复现,就需要用到Java Remote Debug 的功能。这种方式可以让你的开发机连接到其它环境上的Jenkins,并允许断点调试,和本地开发一样的效果。

Jenkins 单元测试

Jenkins对单元测试有很强大的支持,可以在单元测试中对UI或者接口进行测试。当你启动Jenkins单元测试后,它会自动启动一个最小的Jenkins服务。另外,我想说的是,单元测试并不是鸡肋,也不会耽误你做开发的时间。单元测试可以在很大程度上保障程序发布时避免很多低级问题。

如何选择Jenkins版本?

上面就是我今天要分享的主要内容,另外,为了能让大家尽可能有更多的收获,我还准备了一些问题供大家思考。

第一个问题是如何选择Jenkins的版本。有这么几个场景,一个是咱们今天的主题,插件的开发。比如说现在新起一个插件,是基于哪个Jenkins的版本呢?如果不需要很多特性的话,建议选较低的版本,这样插件的兼容性会好一些。而如果你想要测试插件在多个Jenkins版本上的稳定性的话,也是不需要修改pom.xml文件的,只需要在执行时指定profile即可。

还有一个场景,当你要部署一个Jenkins来做持续集成,该怎么选择版本呢?我在这里给大家普及一下Jenkins的版本发布规则:分两类版本,一个是每周发一次版本,还有一个长期支持的版本(一个季度发布一次)。最好选长期支持的版本,也就是LTS的版本。

如何寻求帮助?按我自身的经验来说,不太推荐通过微信、QQ等及时聊天工具。主要的问题是,你如果通过这样方式提问,真正能帮你解决的那个人不一定在线,就算在线也不见得能及时看到你的提问(也就没有了及时聊天的优势了);而且,很多人上班都比较忙,想要帮助你也没有时间。所以还是推荐发在论坛里寻找答案。

Jenkins API

然后是Jenkins API。据我了解,很多人会把Jenkins当作一个调度引擎来使用,这样就需要一个client来和Jenkins进行交互。官方的Java client更新很慢,大家如果使用Java作为开发语言的话,可以考虑 https://github.com/LinuxSuRen/jenkins-client-java 这个客户端。

容器与Jenkins集成

关于 Docker 和Jenkins集成的方式,有这么几种:交给容器编排(例如: Kubernetes )来动态管理、由Jenkins直接和Docker交互来管理、启动一个静态的Docker容器去连接Jenkins。让K8S来管理Jenkins代理的方式好处很明显,可以很大程度上利用物理机资源,缺点就是复杂度很高。而启动一个静态的Jenkins代理,其实和Jenkins经典的使用方式区别很大。

而Jenkins X正好弥补了Jenkins和 Kubernetes 交互复杂的问题。如果使用Jenkins X,你不用关心Jenkins和Kubernetes如何交互、配置等问题,只要有一个可用的集群就好,或者你没有一个集群的话,它也能帮你创建一个本地的集群环境。

在本月底的DOIS大会上,灵雀云有workshop,欢迎大家去参加,需要带上笔记本,现场会向大家演示如何安装和使用,以及更细节的使用方法。

最下面是文档的官网( https://jenkins-x.io/zh/ ),目前主要由我来做翻译。由于Jenkins X的迭代很快,还会有很多新的特性加进来,所以非常欢迎大家,或者是呼吁,一起加入翻译小组。

Jenkins X的文档基于HUGO静态网站生成器来做的。Hugo基于Golang开发。文章格式为Markdown,所以,了解Markdown的语法也是必要的。安装完Hugo,执行hugo server命令,就会启动一个监听端口;你对文件的修改,都可以在网页上实时看到效果。

另外,我贡献了一个用户构建Hugo站点的Jenkins插件( https://github.com/jenkinsci/hugo-plugin )。

Q&A 精选

Q1:我的问题是,Jenkins现在很多插件都会使用Pipeline这种方式,普通的插件,会不会没落下去,或者说我们在选择插件的时候,会不会更多地选择一般的插件?

A1:这个问题很好。要开发一个插件,其它Job能实现的功能现在流水线都能实现了。另外,Jenkins提供的一个注解,可以很轻松地把一个自由风格的构建任务添加流水线(DSL)的支持。所以你要自己写的话没有这个疑问。第三方的话,大的趋势对流水线都有支持。所以不管用别人还是用自己的,这个问题都不是太严重。

Q2:Jenkins有可以调用的API吗?

A2:对任务的创建、修改、删除、查询等操作Jenkins都是有API的。其实做一个产品的话,如果让用户很明显地看到Jenkins的痕迹的话,可能会显的粗糙和不太专业。另外,据我了解很多团队会把Jenkins,当作一个后端的调度引擎来用,所以你可能无法直接看到Jenkins。

Q3:像Jenkins中的任务数量到成百上千时,启动很慢。有没有解决办法?

A3:因为Jenkins出现的比较早,一开始可能没有考虑过这样的问题,所以是没有这样的一个扩展点的。社区里已经有过这样的PR,但是可能还没通过,理由就是会把Jenkins核心也会修改了,需要先经过讨论再定具体的解决方案。

这样的话,做这个工作比较困难,因为本身没有拓展点。但是,既然有人提过PR了,这个事还是可以做的。你可以去参考一个那个PR里的修改内容。

Q4:前一段时间我们用了一个multi-branch插件,分支的名称怎么才能拿到,这个需要自己调API还是通过环境变量可以取到?

A4:我觉得这个插件,应该会提供环境变量的。其实关于分支这一块,官方会给提供这样的分支信息,你随便创建一个流水线,它最下面会有一个“流水线语法”,点击进去,就能看到全局的环境变量,还有一个代码生成器。

Q5:我有两个问题,一个是性能上的问题,一个是运维的问题。每次构建的时候,就是工作目录,都会保留历史构建,导致下次打包的时候,新的Java加不进来。第二个问题是性能。我们使用Jenkins的jar,远程地发命令,大概有了20、30个批量的处理,这个整个耗时差不多一小时,所以想问一下,可不可以通过golang客户端,或者优化缩短这个时间?

A5:第一个问题,有一些jar,依赖加不进来,如果快照版本的话,可能不是Jenkins的问题。Maven有一个参数可以强制更新快照版本。而Release版本,是不允许部署两次的,应该不会出问题。

第二个问题,虽然golang效率很高,但因为走的都是HTTP协议,所这个跟语言关系不大。另外,我建议详细地分析一下,到底耗时在什么地方。比如说我遇到一个场景,把每一个阶段的都建成一个流水线,然后拿一个流水线来调度,所以导致流水线特别多。但如果用一个流水线把所有的阶段和步骤串起来,可以少很多的构建任务,这样Jenkins的压力就降低了。另外,multi-branch也是一个很好的选择,可以很大程度上复用流水线。所以,可以试着换个角度来优化。

原文  http://dockone.io/article/6013
正文到此结束
Loading...