目录
前言
本文章主要是自己对jenkins的一些理解和搭建过程中遇到的一些坑,毕竟现网上很多jenkins包括节点相关和docker构建时候的一些坑没有提到,官网的文档写的也不够详尽,摸索出来的一些经验聊以分享,有出入的地方望指正。最终还是希望大家多看官方文档:JenkinsJenkins 是一个开源自动化服务器https://www.jenkins.io/zh/
一、jenkins是什么?有什么用?为什么要用它?
1、jenkins是什么?
最开始学习时,看了很多相关视频,中心词无非就这几个:java编写、开源、CI&CD。引用官网原介绍:
Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。
Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
CI&CD
这里只解释下CI&CD,CI既是持续集成,以往我们集成的场景是多位开发人员负责不同功能模块,在合并日就导致工作繁琐耗时,当两个甚至多个开发人员改动同一个模块时,还需要对其手动合并。CI则可以帮助开发人员更加频繁的将代码合并到共享分支上,一旦开发人员对应用做出了更改合并,系统会自动构建并运行自动化测试来验证这些更改,如果发现冲突,CI就会自动修复这些错误。
CD有两个含义:一是持续交付。完成CI的持续集成后,持续交付可自动将已验证的代码发布。持续交付的目标就是拥有一个可以随时部署到生产环境的代码库;二是持续部署。持续集成和持续交付之后就是持续部署。持续交付自动将稳定的版本发布到代码库,持续部署就可以自动将应用发布到生产环境。换言之,开发人员写好了代码,发布到公共分支上,经过自动化测试,几分钟后即可在生产环境生效(当然生产环境还是测试环境是可控的)。
2、jenkins有什么用?为什么要用它?
jenkins有什么用?换句话来说的话就是jenkins的优缺点,下面我讲些个人理解的一些优缺点。
jenkins优点:
简化部署流程,增加工作效率。传统开发部署流程需要去多个服务器重复相同操作,对于开发、运维人员而已非常不友好;而jenkins部署,对于开发人只需要写好代码,不需要自己进行源码编译、打包等工作,直接将代码分支提交到git仓库即可;运维人员减少人工干预的错误率,同时解放运维人员繁杂的上传代码、手动备份、更新;测试人员可以通过jenkins直接部署测试。
持续集成项目,全程部署留痕。传统开发部署过程中,时常出现项目重启时间过长,客户体验差,甚至会杀错进程的情况,而jenkins部署,将构建过程全部自动化,只需要点击一个按钮,或者进入一个url即可自动编译、分发、部署和测试;并且有从搭建至今的部署记录和上传信息内容,方便回滚等操作。
jenkins弊端:
内部配置复杂,网上攻略较少。jenkins自动构建项目虽然使用起来方便,但是内部项目配置较为复杂,要对linux、docker、shell、ssh、windows批处理等技术有一定的基础,门槛较高。并且相对而言是个新技术,以至于出现很多错误网上没有详尽的攻略。
总之,jenkins则是解放我们开发的双手,不再被打包、部署等这些固定又无法逃避的事情所困扰,也不用记那些kill或者是stop的命令,只需要点击或者别的触发器构建项目即可自动化构建。
二、jenkins的搭建
jenkins有许多方式搭建,在官网中有多种下载方式:Docker、Ubuntu、CentOS、Windows...这怎么下区别真不太大(除了docker下载,有许多坑,等会再说),最后都是在jenkins工作台上工作。这边我还是以Docker安装来说明,CentOS和Windows的以后有机会再搞。
我是在linux服务器上搭建docker服务器,docker里搭建jenkins容器。这边linux的docker搭建就不细讲了。
1、安装jenkins
docker run -u root -p 8080:8080 -p 50000:50000 -v jenkins-data:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v /home/idea:/home/idea jenkinsci/blueocean
光这一条语句就有很多坑,第一大坑:-u root。直接docker run 该jenkins会出现无限多权限问题,比如:项目啥的都配置好了,但是最终要通过jenkins的maven打包项目并运行项目,但是当你到了jenkins就会发现你干啥都没有权限,你用docker部署的jenkins会自动给你的jenkins服务器设置密码,又不知道默认密码,就无线死锁。第二大坑:-v挂载。若不挂载很难操作jenkins里面的项目,等于你要从jenkins里面透到docker服务器再透到linux服务器处理文件。
访问的url为你启动Jenkins服务器的ip加端口的形式访问,端口为第一个-p的8080,可以设置为自己想要的端口,如:192.168.0.1:8080
启动中,会出现一个密钥,登录jenkins服务器,输入,把该设置的设置即可,填入用户时记得用户名密码,这是以后登录Jenkins的账号。(注:docker和普通下载的jenkins在下载插件处不一样,第一次启动时Jenkins会让你下载一些基础插件或者不下载,docker可以直接按默认的下载插件,普通下载的jenkins就选不下载,默认在外网下载,基本都会报错,需要在里面重新配置,选择国内镜像!由于这部分太过简单就不贴图了)
2、基础配置
①系统配置
这里没什么配置的,如果需要ssh连接别的服务器,则在“系统配置”内配置ssh相关信息即可,如果没有ssh连接配置,则去“插件管理”下载ssh相关插件。
配置ssh连接。这个网上一大把教程,就不细说了,大概思路就是要么就账号密码连接,要么就密钥公钥连接。这个ssh连接可以通过ssh把相关文件移动到ssh服务器上,甚至可以做相关执行命令操作,由于本项目没用,就不做演示。
②全局工具配置
配置jdk:jenkins由于是用java编写的,所以他是自带了jdk的,JAVA_HOME都是固定的,可以在“状态信息”--“系统信息”里查看。
配置maven:如果不想在jenkins里下载maven,可以勾选自动安装。这里就能体现docker里装jenkins的第一大坑了,如果想安装自己下载的maven就需要把maven包通过docker传输到jenkins服务器上,在进行解压和配置操作。这里省事直接自动安装。
同理,如果出现没有的情况,在“插件管理”处下载插件。
③插件管理:可以更换国内的镜像源地址,下载插件会稍微快点
Jenkins更换国内清华大学镜像
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
在 高级 -- 升级站点 处更换URL,再补充上面的上传插件,使用该功能的场景是,可选插件里面没有自己想要的插件,可以去Jenkins Plugins,进行插件下载,下载本地后在网站上选择文件上传。推荐个必下的插件:汉化Jenkins插件
下载完插件后需要重启Jenkins才能生效。
④凭据:
点击红框,添加凭证。凭证的作用就是Jenkins连接第三方的全局的账号管理。比如:记录连接git的账号,连接ssh的账号等账号。
基本做完这些已经可以开始玩jenkins。
三、Jenkins任务
点击“新建任务”,可以看到如下页面,下面主要讲两个任务部署。一个是maven项目,一个是流水线项目。
1、maven项目
maven项目建议从这里开始玩起,上手相对比较轻松。
进来配置,可以通过最上面的9个模块进行配置,下面一个一个进行分析,有些冷门的功能也可以通过最右边的问号查看详情。
①General
描述:对该构建任务的一个描述,可不填;
GitHub项目:里面配置相应的项目URL和显示名称,可不填;
This build requires lockable resources:此构建需要可锁定的资源,可不填;
Throttle builds:节流构建,通过设置时间段内允许并发的次数来实现构建的控制,可不填;
丢弃旧的构建:设置构建历史的保存策略,根据个人爱好填写,可不填;
保持构建的天数:根据天数来保存构建记录
保持构建的最大个数:最大的构建记录数
发布包保留天数:我们发布的jar、war包保存的天数
发布包最大保留#个构建:发布了几个jar、war包,保存构建的数量
参数化构建过程:动态配置参数,配置后可以在构建项目的之前填相应的参数,比如:在构建项目之前可以填对应的分支,这里举个例子,这里我选的“字符参数”,名称为“gitBatch”,默认值为“dev”,一会我们走完整个流程,看看构建的效果,可不填。
关闭构建:让项目无法构建,可不填;
在必要的时候并发构建:此项目的多个构建可能会并行执行,可不填;
②源码管理
Git:也就是代码从哪里拉,可以写github、gitee、gitlab的仓库地址;
Repository URL:Git 仓库,必填;
Credentials:证书,就是连接git仓库的账号密码,如果没有任何提示,则说明连接成功,必填。
Branches to build:指定分支,要发布什么分支就填什么分支,如果要动态配置,比如上面的gitBatch,由“*/master”换成“*/${gitBatch}”,开始就可以动态配置分支,必填。
源码库浏览器:默认自动就好,必填;
③构建触发器
触发器既是通过除点击启动外的方式构建项目。
Build whenever a SNAPSHOT dependency is built:每当构建 SNAPSHOT 依赖项时构建,如果选中,Jenkins 将解析此项目的 POM,并查看其任何快照依赖项是否也构建在此 Jenkins 上。如果是这样,Jenkins 将设置构建依赖关系,以便每当构建依赖作业并创建新的 SNAPSHOT jar 时,Jenkins 将安排此项目的构建。可不填;
触发远程构建 (例如,使用脚本):勾选后输入随意的身份验证令牌,就可以通过URL远程触发构建:JENKINS_URL /job/maven-test/build?token= TOKEN_NAME。可不填;
其他工程构建后触发:顾名思义其他工程构建后就构建该项目,也可以选择上个项目是否成功等构建状态来选择是否触发。可不填;
定时构建:可以定时构建,如每天、每周、每月等定时构建,可不填;
轮询 SCM:是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
④构建环境
Delete workspace before build starts:在构建开始之前删除工作区,可不填;
Use secret text(s) or file(s):允许获取各种凭证并在shell构建步骤中使用他们,可不填;
Provide Configuration files:提供配置文件,使全局配置的文件在本地工作区能使用,可不填;
Send files or execute commands over SSH before the build starts:在构建开始之前通过 SSH 发送文件或执行命令,可不填;
Send files or execute commands over SSH after the build runs:构建运行后通过 SSH 发送文件或执行命令,如果在构建前步骤中构建失败,则构建后步骤将不会运行,可不填;
Abort the build if it's stuck:如果构建被卡住,则中止构建
Add timestamps to the Console Output:向控制台输出添加时间戳
Execute shell script on remote host using ssh:使用 ssh 在远程主机上执行 shell 脚本,要在全局配置页面定义SSH,可不填;
Inspect build log for publipei Gradle build scans:检查已发布的 Gradle 构建扫描的构建日志,可不填;
⑤Pre Steps
准备步骤。也就是在Build之前,需要执行的操作,这个大部分情况不用,但是后面Windows节点构建项目时候会大有用处,可不填。
⑥Build
到了这里就开始构建了,整体还是和mavne一样的思路:clean install。
Maven Version:这里是在“全局工具配置”处配置了多个maven就会让你选择,用哪个maven进行build,随便选,必填;
Root POM:根POM,如果工作区在第一个模块的根目录之外有某个位置有*pom.xml,就需要指定详细路径下的pom.xml文件。正常的就默认的pom.xml,必填;
Goals and options:目标和选项,指定要执行的目标,此字段还可以接受 Maven 的任何其他命令行选项,例如我写的:"clean install -Dmaven.test.skip=true",clean install就是要执行的目标, -Dmaven.test.skip=true就是maven的其他命令,意思就是不执行测试用例,也不编译测试用例类,因为maven在编译打包的时候,maven会执行JUnit测试用例,跳过测试即可加上面命令。(这里拓展下“-DskipTests”和“-Dmaven.test.skip=true”的区别,前者是指不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下;后者则就是不执行测试用例,也不编译测试用例类),必填;
⑦Post Steps
发布步骤。一般在这个时候执行运行jar包的命令,看自己的系统选择相应的构建后的步骤。
最上面的三个单选框,就是中文直译的意思,分别为:仅在构建成功时运行、仅在构建成功或不稳定时运行、无论构建结果如何运行。一般选择第一个:Run only if build succeeds(仅在构建成功时运行)。
下面的下拉框,根据自己系统选择相应的执行命令,如果你在linux上执行,就选择执行shell,之后写上对应的shell脚本即可,若是windows,则选择“执行windows批处理命令”,对应的就要对shell脚本或者批处理命令有一定的基础知识(这里先将shell脚本怎么写,后面讲windows节点的时候再讲批处理命令怎么写)。
shell脚本:发布步骤的思路就是:将之前正在跑项目kill掉,删除旧项目,再将默认打包的jar包cp到docker挂载的目录下,再去挂载的目录去运行jar包,备份老项目。
DATE=$(date +%Y%m%d)
export JAVA_HOME PATH CLASSPATH
JAVA_HOME=/opt/java/openjdk
PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$CLASSPATH
DIR=/home/idea
JARFILE=Jenkins-test-1.0-SNAPSHOT.jar
if [ ! -d $DIR/jenkinstest ];then
mkdir -p $DIR/jenkinstest
fi
cd $DIR/jenkinstest
ps -ef | grep $JARFILE | grep -v grep | awk '{print $2}' | xargs kill -9
mv -f /var/jenkins_home/workspace/maven-test/target/$JARFILE .
java -jar $JARFILE > out.log &
if [ $? = 0 ];then
sleep 30
tail -n 50 out.log
fi
cd jenkinstest/
ls -lt|awk 'NR>5{print $NF}'|xargs rm -rf
每句分析下:if那一条语句意思是,查看挂载目录有没有该项目目录,如果没有就创建;
cd 到该挂载目录的项目目录
ps查找该jar文件的进程,将其kill
把Jenkins的maven打包的jar包mv到当前的项目目录
运行该项目目录下的jar包并生成log文件
⑧构建设置
E-mail Notification:是否需要邮件通知,勾选就会发送通知到注册的邮箱账户上。
⑨构建后操作
构建成功后的操作。基本不用操作,如果有需要自行百度。
这样整个maven项目就构建完成了,第一次运行会比较慢。
2、流水线项目
流水线项目最大的特点就是用Jenkinsfile和Dockerfile去控制整个项目的流转运行
可见流水线只有4个步骤,再次印证很多操作把他丢到 Jenkinsfile和Dockerfile去控制。
①General
参数化构建过程:将拉取代码库的URL、构建的分支等信息在这里参数化定义,一会在脚本处可以动态配置项目。配置详情参见Maven项目构建。
②构建触发器
配置详情参见Maven项目构建,与Maven项目构建一致,可不填;
③高级项目选项
显示名称:Jenkins web GUI中显示项目的可选显示名称,没设置就会显示默认的,故也可以不填;
④流水线
定义:pipeline script就直接将脚本命令写在页面上,或者选择下面的,则会从项目中找Jenkinsfile脚本文件,所以可以将脚本直接写在页面上,也可以写在项目的Jenkinsfile文件内。
脚本:
node {
stage('git checkout') {
git branch: '${git分支}', #用上面参数构建的参数
credentialsId: '${连接git仓库的用户}', #填凭证处的唯一标识ID
url: '${gitURL}' #用上面参数构建的参数
}
stage('maven package') { #maven打包项目
withMaven(
maven: 'maven:3.6.3', #使用的maven版本
mavenSettingsConfig: 'aliyun-settings', #在Managed files里面配置镜像
jdk: 'jdk-8u221' #jdk版本
) {
sh 'mvn -B -DskipTests clean package' #执行clean和package命令
}
}
stage('docker build') { #docker 构建项目
sh 'docker stop ${项目名}|| true && docker rm ${项目名} || true' #停止之前的项目
sh 'docker build -t ${镜像的名称}:${镜像的Tag名} ${Dockerfile所在目录}' #构建镜像
sh 'docker run -itd -p ${docker端口}:${jenkins端口} -v ${Jenkins挂载目录}:${docker挂载目录} --name ${为容器指定的名称} ${给镜像起的名称}' #启动镜像
}
stage('docker clean') { #将之前的垃圾clean掉
sh 'echo y|docker image prune'
sh 'echo y|docker volume prune'
}
}
项目里的Dockerfile:Dockerfile 是一个用来构建镜像的文本文件。
# Docker image for springboot file run
# VERSION 0.0.1
# 使用java8镜像
FROM java:8
# VOLUME指定了临时文件目录为/tmp
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
# VOLUME [ "/logs" ]
ADD target/项目名.jar 项目名.jar
# 运行jar包
RUN bash -c "touch /项目名.jar"
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT [ "nohup", "java", "-jar", "${项目名}.jar", "--server.port=${端口号}", ">${log名}.log", "2>&1", "&"]
这样我们流水线的项目就构建完了,启动时填入相应参数即可。
四、Jenkins节点
Jenkins节点的作用就是分布式构建,
分布式构建能够让同一套代码在不同的环境中(linux、Windows)编译、测试等,而且Jenkins构建的代码和产物最后自动拷贝到主节点。
明日更新节点详情...