网络知识 娱乐 Jenkins代理模式配置Maven工程

Jenkins代理模式配置Maven工程

{"data":{"title":"Jenkins代理模式配置Maven工程","abstract":"前言相信大家对Jenkins已经非常了解了,大多数项目都采用了这款开源工具来实现项目的CI/CD。对于小型项目,我们完全可以采用“融合部署”的模式,即将Jenkins和构建环境部署在同一台服务器上,来实现自动构建和发布,这时Jenkins的环境搭建也比较简单。","cover":"https://p3.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/c04eb60bdf194857b39880f0c25d2c29","articleType":"article","itemId":"7112632511481545257","groupId":"7112632511481545257","groupSource":2,"isOriginal":true,"banComment":false,"publishTime":"2022-06-24 11:34","source":"程序员柒叔","tag":"technique","mediaSite":null,"pathname":"/article/7112632511481545257/","loginUserInfo":null,"favorite":false,"relation":{"isFollowing":false,"isFollowed":false},"likeData":{"userLikeStatus":0,"count":0},"isSelf":false,"content":"

前言

相信大家对Jenkins已经非常了解了,大多数项目都采用了这款开源工具来实现项目的CI/CD。

对于小型项目,我们完全可以采用“融合部署”的模式,即将Jenkins和构建环境部署在同一台服务器上,来实现自动构建和发布,这时Jenkins的环境搭建也比较简单。但有些时候我们需要多个项目并行编译,或者需要适配多种编译环境,这时对于单主机的性能要求就比较高了。

为应对这种情况,通常会采用“代理模式”(也有叫主从模式的):将Jenkins独立部署,负责对多个项目的构建任务进行调度,而不参与(或极少参与)项目的构建发布;然后添加多个子节点,来负责具体的编译构建任务。这种模式的好处是:

  • 构建节点高可用。一个构建节点挂了,其他节点可以接替执行构建任务,保证系统正常运行;
  • 可以配置差异化的构建环境。每个节点可以针对不同语言开发的项目配置不同的构建环境,互不影响;
  • 构建任务可并行。当SCM同时触发了多个构建任务时,可以将这些任务分配到不同节点上执行,提升构建效率。

代理模式的环境搭建比较简单,这里不做讨论。当我们在使用代理模式时构建项目时会出现很多问题,本文主要讨论在这种情况下的一些实践经验和建议。


准备工作

1、环境准备

这一步的工作是必须的,也是“很有学问”的。

对于java项目,我们需要配置的就是jdk和maven。按照传统的思路,我们会这么做:

  1. 上传适配系统和应用的jdk和maven;
  2. 在~/.bash_profile或/etr/profile中配置jdk和maven的环境变量;
  3. 在任意路径下执行java -version和mvn -v验证环境配置

最终配置的结果类似下方截图:

Jenkins代理模式配置Maven工程

配置环境变量

但是你会惊奇的发现这样做对Jenkins来说并不没有用,你可能会遇到如下错误:

Jenkins代理模式配置Maven工程

Jenkins报错

相信大家到这里都会有点懵。啥情况?明明配置好了环境变量,在主机上运行也好使,怎么到Jenkins里就不好用呢?

这是因为Jenkins在运行时不会加载用户的环境变量,只会使用自己(在Jenkins里配置)的环境变量。如果没有在Jenkins中配置环境变量,默认会使用系统中(Linux为例)/usr/bin或/bin 目录下的指令

所以,针对上面的问题,有2种解决方案,任选其一即可:

1)在Jenkins的控制台上,对构建节点添加环境变量,在“系统管理->节点管理->选中目标节点->配置从节点”中,添加环境变量,如下图:

Jenkins代理模式配置Maven工程

节点属性配置

说明:

这是节点的个性化配置。

如果所有的构建节点环境配置一致,就可以在“全局配置”中统一配置。

2)也可以在构建节点上建立软连接,链接到我们的可执行程序上,如:

ln -s /home/maven/apache-maven-3.6.2/bin /usr/bin/mvnnnln -s /home/maven/apache-maven-3.6.2/bin /bin/mvn

这样,Jenkins就能找到mvn这个指令了。

java指令也是这样配置。


2、插件准备

在Jenkins中商店中按需安装相关插件,如svn、git、pipeline,等等。

如果你的构建节点和运行节点不在一个机器上,需要安装“Publish Over SSH”这个插件。插件的安装不在本文讨论。

在Jenkins和构建环境中做好上述配置之后,就可以进行下一步了。

Maven项目构建

1、构建一个Maven项目

对于Maven工程,我们会本能的选择“构建一个Maven项目”:

Jenkins代理模式配置Maven工程

选择项目形式


但是这个工程有一个问题,它依赖于Jenkins的全局配置。如果没有配置,现象如下:

Jenkins代理模式配置Maven工程

Jenkins报错


这时可以点击后面的“the tool configuration”进入全局配置界面,配置maven路径。

很多时候各节点的jdk和maven的路径配置不同,或某些节点根本就不需要这2个工具,那么又需要在每个节点上分别修改配置。这种情况下,使用“构建一个Maven项目”就不太合适了。

我们可以使用下面的2种方式。


2、构建一个自由风格的软件项目

这种模式比较简单,只要在“环境准备”步骤中都配置好,接下来就是一些shell指令的编排。

首先,在创建项目时选择“构建一个自由风格的软件项目”:

Jenkins代理模式配置Maven工程

​编辑

其次,在General中勾选“限制项目的运行节点”,填写构建节点的名称,如下:

Jenkins代理模式配置Maven工程


然后,在“源码管理”中选择代码库、在“构建触发器”中设置SCM周期,这里就不展示了。

接下来到核心操作步骤了,在“构建”中增加构建步骤,选“执行 shell”,按照你工程的实际编译指令,编写shell内容,如:

Jenkins代理模式配置Maven工程

执行shell时,默认是在当前工作目录下,在主机上路径为$(JENKINS_HOME)/workspace/工程目录/。如果你的pom文件不在工程的根目录下,你还需要cd到目标路径下。


这一步完成之后,就会在你 “工作目录/target”中生成jar或war包。

在部署应用时,可以部署到容器、k8s、或者独立运行。本文只讨论独立部署运行的情况。可以在“构建后操作”中使用“Publish Over SSH”这个插件,将jar包上传到运行节点(也可以是本机)的目标目录中,然后启动程序。参考如下:

Jenkins代理模式配置Maven工程

Publish Over SSH 插件


需要注意几点:

  • SSH Server:目标节点的登录信息可以在“节点管理”中提前配置好,也可以在SSH Server下面的“高级”中设置;
  • Source files:要上传到目标节点的文件,本例中是可执行jar文件;
  • Remove prefix:去掉目录前缀,这是根据Source files设置的。按照例子中的填写方式,放到目标路径后,rest-1.0.jar这个文件还是在target目录下。这一步的作用就是把target目录去掉;
  • Remote directory:要将源文件放到目标节点上的目标目录。注意:这里是相对路径!你需要提前在“系统配置”中,配置好ssh主机的路径,如下图,系统配置中Remote Directory配置的是 /home/appuser。那么在本例中,rest-1.0.jar 会被放到目标主机的 /home/appuser/test 目录下。
Jenkins代理模式配置Maven工程

系统配置-SSH Server


后续的程序启动就可以在“Exec Command”中完成了,比较简单。

至此,我们就完成了一个Maven项目的自动构建和独立发布。


3、流水线

我们还可以使用Pipeline来构建和运行项目。在创建项目时,选择“流水线”:

Jenkins代理模式配置Maven工程

选择项目形式


在项目中,“General”和“构建触发器”的配置方式跟前面都是一样的。

在后面的“流水线”这里,需要编写Groovy脚本来控制构建和发布的逻辑。我们可以在网上找一些通用的代码模板,也可以选择Jenkins自带的模板,为我们自动生成一些代码,观察代码结构:

Jenkins代理模式配置Maven工程

流水线脚本

看到pipeline里面,指定了agent节点、克隆代码、构建,等等。

不会Groovy怎么办?看到左下角的“流水线语法”了吗?点进去,会为我们自动生成流水线代码!例如,我想指定我的运行节点,就可以按照如下步骤点击、选择:

Jenkins代理模式配置Maven工程


从英文中不难理解每个步骤的含义,最后点击按钮就会为我们生成代码。把这个代码直接贴到Pipeline的适当位置上即可,如下:

pipeline {n //1.指定标签为 test 的节点 执行该构建任务n agent {n label 'test'n }n n //2.声明环境变量n environment {n MAVEN_HOME = "/home/appuser/lr/maven/apache-maven-3.6.2"n JAVA_HOME = "/home/appuser/lr/jdk1.8.0_11"n JRE_HOME = "${JAVA_HOME}/jre"n CLASSPATH = ".:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH"n JAVA_PATH = "${JAVA_HOME}/bin:${JRE_HOME}/bin"n PATH = "/usr/local/go/bin:$JAVA_HOME/bin:$PATH:$JAVA_HOME/jre/bin:$PATH:${MAVEN_HOME}/bin"n }nnn stages {n stage('Pull Code') {n steps {n // 3.编写拉取代码的指令n // sh "svn xxxxx"n // sh "git pull xxxx"n echo "start"n }n }n stage('Build') {n steps {n // 4.在这里添加编译构建指令n sh "mvn -Dmaven.test.failure.ignore=true clean package"n }n }n stage('Run') {n // 5.应用发布n // 这部分代码也是在流水线语法中自动生成的,在“片段生成器”中选择sshPublishern steps {n sshPublisher(publishers: [sshPublisherDesc(configName: '10.4.122.155', sshCredentials: [encryptedPassphrase: '{AQAAABAAAAAQUhudNn9S1kPGyV4eRRGNs649cFzWNnaNJKTG0C0/OGc=}', key: '', keyPath: '', username: 'appuser'], transfers: [sshTransfer(excludes: '', execCommand: 'nohup java -jar /home/appuser/test/rest-1.0.jar &', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'test', remoteDirectorySDF: false, removePrefix: 'target', sourceFiles: 'target/rest-1.0.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])n }n }n }n}n

在编写Pipeline时,以上5个步骤是最基本的,即:

  1. 指定任务运行节点
  2. 设置环境变量
  3. 拉取代码
  4. 编译构建
  5. 应用发布

有了“流水线语法”,不会Groovy也可以编写Pipeline!本例中的所有代码都是通过“流水线语法”自动生成的

当然,如果你想实现更多的高级功能,就需要深入研究Groovy了。


总结

本文介绍了在代理模式下,分别通过“构建一个自由风格的软件项目”、“构建一个Maven项目”以及“流水线”3种方式来构建Maven项目,以及每种方式的注意事项,总结如下:

  1. Jenkins在运行任务时,使用的自己的环境变量,而不是操作系统的环境变量。可以在Jenkins的系统设置中进行设置,也可以针对每个节点进行设置;
  2. Jenkins默认使用的是/usr/bin和/bin下的指令,不会读取主机用户的PATH;
  3. “构建一个Maven项目”,更适用于小型项目,单台服务器就能够完成调度和构建任务的情形;
  4. 不熟悉Groovy也可以构建流水线,使用“流水线语法”自动生成代码;


","imageList":["https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/cf19acefee594c738339c791ee99bd71?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/53967bbda56a48a5ad5e16fd0edddba3?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/c04eb60bdf194857b39880f0c25d2c29?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/37b26127196c407a8e428dc5a046373b?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/67fc340ce1fb4320b519841d413bf336?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/3a24127350e04e19826e7880ed047231?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/63a0056aa2714de6a43d7b491178bd59?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/b40d80d782bb41f18a622624f3de9492?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/503d90534b41437da0dd5f09cc845cd9?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/c66a5666b3a54518a00fef2e526472be?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/9d1a9d0dead941e0a7d6de39a50f5d66?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/d6704b0a5cd64476a16b98925a5b0782?from=pc","https://p9.toutiaoimg.com/origin/tos-cn-i-qvj2lq49k0/f2124a7b945e46489c2f50f0fac588df?from=pc"],"mediaInfo":{"userId":"MS4wLjABAAAAnEO1xjsWlzz28dBU361RDmpyUHUZTwmiNUPdlbyLCCVRVcpd5YAQLwpY5x6yb7EL","unsafeUserId":"1099975885353869","name":"程序员柒叔","avatarUrl":"https://p26.toutiaoimg.com/origin/user-avatar/c1287122839390069163833fd54314c8","description":"最好的学习方式就是传承","userVerified":1,"userAuthInfo":""},"seoTDK":{"title":"Jenkins代理模式配置Maven工程-今日头条","description":"前言相信大家对Jenkins已经非常了解了,大多数项目都采用了这款开源工具来实现项目的CI/CD。对于小型项目,我们完全可以采用“融合部署”的模","keywords":"Java,Linux,软件,Apache,Git","publishTimestamp":"1656041670","modifiedTimestamp":"1656050324"},"logId":"202206241419340101581201440796E631","sylpageConfig":{"card":{"id":""}},"identity":{"web_id":"7111199547455817229","user_is_login":false},"abtestInfo":{"rsp_type":5,"version_name":"4252807,4164637","parameters":{"feat_repost_type":{"new":true},"home_nav_conf":{"dcd_out":1},"local_filter":{"core_filter":{"filter_list":{"ms::TicaiFilter":true}}},"page_upgrade":{"new_profile":true,"video_double_column":true},"sati":{"enable_ad_prime":true,"enable_sorter_optimus":true,"prime_rule_rank_version":"toutiao_web","use_toutiao_web_feed":true,"format_max_consecutive_middle":2,"format_max_consecutive_nogroups":3,"enable_reduce_nogroup":true},"seraph":{"score_rule":{"default":{"replace":{"group_util":"_CTR - 1000*dislike"}},"new_user":{"replace":{"group_util":"_CTR - 1000*dislike"}}}},"sort":{"allowed_ticai":["forum_post","pgc_text","pgc_video"]},"video_detail_page_upgrade":{"new_page":true}},"env_flag":0},"localCityInfo":{"name":"北京","code":"110000","channelId":3202164529},"showResearch":false}}