jenkins基础 | 我的日常分享

jenkins基础

Jenkins基础

一、jenkins安装

1.1 安装java环境

1
2
3
4
5
6
# 查询jdk版本有哪些
yum search java | grep jdk
# 安装jdk11
yum install -y java-11-openjdk
# 查看是否安装成功
java -version

1.2 安装maven

1
2
3
4
5
6
7
# 下载maven
curl -O https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz
# 解压缩
tar -zvxf apache-maven-3.8.6-bin.tar.gz
cp apache-maven-3.8.6 /usr/local/maven -r
# 查看版本
/usr/local/maven/bin/mvn -version

注意:

image-20221129095709576

这里的maven的runtime是有可能是jre,不是jdk,有坑。

如果在maven构建时出现no compiler is privided in this environment.则需要安装jdk环境

1
yum install -y java-devel

image-20221129112434534

1.3 更改maven镜像源

1
2
# 找到标签<mirrors>更改为阿里云镜像源
vi /usr/local/maven/conf/setting.xml
1
2
3
4
5
6
7
8
 <mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>

1.4 安装Jenkins

[jenkins官网]https://www.jenkins.io/ 官网中说明很详细。

1
2
3
4
5
6
7
8
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install fontconfig java-11-openjdk
yum install jenkins
# 启动jenkins
systemctl start jenkins
# 查看输出日志 里面包含了初始化的管理员秘钥
systemctl status jenkins -l

访问 http://ip:8080/ 根据提示操作下一步,使用推荐的插件进行安装即可。ip为安装Jenkins机器的ip地址。

二、构建maven项目

默认安装的插件中没有Maven Integration plugin,新建item中没有构建一个maven项目这个选项。

2.1 安装Maven Integration plugin插件

image-20221129102523516

成功安装后,在新建item中就多出构建一个maven项目选项,如图。

image-20221129161147932

2.2 新建maven构建项目

新建item,任务名称为testProject01,选择构建一个maven项目

image-20221129161313551

2.2.1 基础配置

配置源码管理。

image-20221129161934089

注意:

  1. 提示Failed to connect to repository : Error performing git command: git ls-remote -h https://git.yuencode.cn/jiaxiaoyu/jenkins-springboot.git HEAD,则是没有git环境。

    image-20221129103904689

    1
    2
    # 使用yum命令安装git
    yum install -y git
  2. 提示Jenkins needs to know where your Maven is installed.Please do so from the tool configuration.则是没有配置maven路径。

    image-20221129104356188

    配置maven路径,Manage Jenkins ---> Global Tool Configuration ---> Maven, http://ip:8080/manage/configureTools/

    image-20221129104508450

配置好源码管理后,其它配置默认,保存,即可查看一下构建效果。点击构建。

image-20221129162449026

片刻后,在左下角的构建执行状态中可查看到当期正在构建的job,点击进去。

image-20221129162515928

进入当期项目页面,在左下角有正在构建的job,再次点击进入。

image-20221129162531800

进入此页面可查看控制台输出。

image-20221129162544774

构建完成后,可以查看到生成的jar路径:/var/lib/jenkins/workspace/testProject01/target/jenkins-springboot-0.0.1-SNAPSHOT.jar

1
2
3
4
5
6
7
8
9
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ jenkins-springboot ---
[INFO] Installing /var/lib/jenkins/workspace/testProject01/target/jenkins-springboot-0.0.1-SNAPSHOT.jar to /var/lib/jenkins/.m2/repository/cn/yuencode/jenkins-springboot/0.0.1-SNAPSHOT/jenkins-springboot-0.0.1-SNAPSHOT.jar
[INFO] Installing /var/lib/jenkins/workspace/testProject01/pom.xml to /var/lib/jenkins/.m2/repository/cn/yuencode/jenkins-springboot/0.0.1-SNAPSHOT/jenkins-springboot-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.586 s
[INFO] Finished at: 2022-11-29T16:25:34+08:00
[INFO] ------------------------------------------------------------------------

image-20221129163946254

手动运行试试

1
2
[root@localhost ~]# cd /var/lib/jenkins/workspace/testProject01/target/
[root@localhost target]# java -jar jenkins-springboot-0.0.1-SNAPSHOT.jar

访问http://192.168.96.130:9000/

image-20221129164228045

2.2.2 自动化发布到测试服务器并运行

安装publish over ssh插件

image-20221129135634099

安装成功后,添加要使用publish over ssh的服务器.

image-20221129140607374

image-20221129140914564

打开testProject01任务,修改配置。

image-20221129164738115

添加Post Steps,选择Send files or execute commands over SSH通过ssh发送文件或执行命令。

image-20221129164911947

添加如下配置:

image-20221129171303167

再次执行job,构建成功。

image-20221129171954669

查看进程

image-20221129172200376

访问http://192.168.96.130:9000/

image-20221129172015004

2.2.3 编写清理脚本

可以发现以上的配置存在问题,如果jenkins-springboot进程存在,再次执行job,springboot端口会冲突启动失败。

编写一个停止springboot应用的简单脚本stopApp.sh,存放在/root/jars目录中

stopApp.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# 获取传入参数
appname=$1
# 获取进程id
pid=`ps -ef | grep $appname | grep 'java -jar' | awk '{printf $2}'`
# 判断pid是否为空
if [ -z $pid ];
then
echo "$appname not found"
else
# 杀死进程
kill -9 $pid
echo "$appname is stoping"
check=`ps -ef | grep -w $pid | grep 'java -jar'`
if [ -z $check ];
then
echo "$appname $pid stop success"
else
echo "$appname stop failed"
fi
fi

添加可执行权限:

1
[root@localhost jars]# chmod +x stopApp.sh

测试:传入应用名

1
2
3
4

[root@localhost jars]# ./stopApp.sh jenkins-springboot
jenkins-springboot is stoping
jenkins-springboot 3939 stop success

添加一个Pre Steps,选择Send files or execute commands over SSH.在构建前执行脚本停止该应用。

image-20221129172955716

Send files or execute commands over SSH插件:

  • Remote Directory

    1. 全局Remote Directory:决定ssh传输文件的根路径。
    2. steps中的Remote Directory:决定ssh传输文件在根路径下的相对路径。即实际上文件传输路径为全局的Romote Directory与Steps中配置的Remote Directory相加。

    例如在全局中配置的Remote Directory:/testDir/aaa/bbb,在某个Steps中配置的Remote Directory:jars,那么文件将传输到/testDir/aaa/bbb/jars中。

    image-20221129170357659

注意:
全局Remote Directory:配置的路径必须存在,例如:/testDir/aaa/bbb必须事先存在,否则不会自动创建。
steps中Remote Directory:配置路径并不需要手动创建,不存在将会自动创建。

如果全局Remote Directory没有配置,则默认进入当前ssh用户的home目录。

  • Exec command

    输入的命令不能存在“卡顿”,nohup java -jar /root/jars/jenkins-springboot-*.jar &>jekins-springboot.log &nohup java -jar /root/jars/jenkins-springboot-*.jar &两个命令的区别。后者存在“卡顿”现象,

    image-20221129174119903

    当该命令执行后需要用户按一下回车键才行。

    image-20221129174209700

    如果配置这样的命令,很有可能导致超时失败。如下图

    1
    2
    3
    4
    5
    6
    7
    SSH: Connecting from host [localhost.localdomain]
    SSH: Connecting with configuration [jenkins-testserver] ...
    channel stopped
    SSH: Disconnecting configuration [jenkins-testserver] ...
    ERROR: Exception when publishing, exception message [Exec timed out or was interrupted after 120,002 ms]
    Build step 'Send files or execute commands over SSH' changed build result to UNSTABLE
    Finished: UNSTABLE
  • 超时机制:默认超时时间是120000ms,点击高级可以配置超时时间。

    image-20221129174824233

数据流重定向

数据流重定向就是将某个命令执行后应该要出现在屏幕上得数据传输到其他地方。

  • 标准输入(stdin):代码0,使用<或<<
  • 标准输出(stdout):代码为1,使用>或>>
  • 标准错误输出(stderr):代码为2,使用2>或2>>
1
2
3
nohup java -jar /root/xxx.jar >mylog.log 2>&1 &
# 或者
nohup java -jar /root/xxx.jar &>mylog.log &

2.2.4 git钩子自动构建项目

配置构建触发器触发远程构建选项,设置身份验证令牌,比如设置成123456,访问链接http://192.168.96.134:8080/job/testProject01/build?token=123456即可触发构建。

但是存在问题,该链接不支持匿名访问,必须登录用户访问此链接才行。

安装插件Build Authorization Token Root,即可使用匿名访问。

image-20221130073638293

安装Build Authorization Token Root插件

image-20221130073148122


插件Build Authorization Token Root文档

  • Usage

    用例是 Jenkins 是安全的,因此匿名用户缺乏整体读取权限。假设您想从脚本触发某些作业的构建。您可以选择经过充分验证的用户并使用该人的 API 令牌 POST 到job/NAME/build. 但这会将那个人的完全权限授予任何可以看到该脚本的人,这是很危险的。

    此问题的通常解决方法是在作业配置中定义构建授权令牌,并使用脚本 ping job/NAME/build?token=SECRET。不幸的是,Jenkins 会按层次结构检查 URI,并且只检查job/NAME/需要身份验证的程度。

    这个插件提供了一个备用的 URI 模式,它不受通常的整体或作业读取权限的约束。只需发出一个 Http GET 或 POST 到buildByToken/build?job=NAME&token=SECRET. 无论安全设置如何,匿名用户都可以访问此 URI,因此您只需要正确的令牌。

    支持文件夹。如果名为 的作业myJob位于名为 的文件夹myFolder中,NAME则为myFolder/myJob(没有交错job/字符串)。

    (也支持变体子 URIbuildWithParameterspolling,就像通常的delay查询参数一样。)

    当构建成功排队时,服务器会回复“201 Created”状态代码。当构建已被安排时,服务器回复“303 See Other”,Location标头指向计划的构建 URL。没有构建许可的客户READ不应遵循重定向,因为这将导致他们无权查看的页面。

    要为您的作业创建令牌,请转到作业配置,在构建触发器部分选择远程触发构建。您在此处设置的令牌是您将通过 url 传递的内容。

  • Examples

    使用令牌TacoTuesday触发RevolutionTest作业:

    1
    buildByToken/build?job=RevolutionTest&token=TacoTuesday

    使用令牌 TacoTuesday和参数Type提供的值Mexican触发 RevolutionTest作业:

    1
    buildByToken/buildWithParameters?job=RevolutionTest&token=TacoTuesday&Type=Mexican

插件安装完成后使用get或post方法访问http://192.168.96.134:8080/buildByToken/build?job=testProject01&token=123456,即可触发构建。

image-20221130074500037

2.3 几种构建触发器

  • 快照依赖构建

    当依赖的快照被构建时执行本job

  • 触发远程构建(例如,使用脚本)

    远程调用本job的restapi时执行本job

  • job依赖构建Build after other projects are built

    当依赖的job被构建时执行本job

    image-20221130075639348

  • 定时构建Build periodically

    使用cron表达式定时构建本job

  • 向github提交代码时触发Jenkins自动构建

    GitHub-Webhook触发时构建本job

  • 定期检查代码变更Poll SCM

    使用cron表达式定时检查代码变更,代码变更则构建本job

2.4 jenkins cron表达式

标准cron表达式http://crontab.guru/

jenkins cron表达式遵循标准cron表达式语法,但是略有不同。

点击?号可以查看具体语法文档说明。

image-20221130080424216

1

2.5 配置邮件通知

使用163邮箱。

登录163邮箱打开stmp服务,获取授权码。

1
TCXHFYWWYFIJLOHBK

image-20221130083537282

2.5.1 配置Jenkins Location

image-20221130084451640

2.5.2 配置Extended E-mail Notification

没有这个选项,需要安装插件,此选项功能可以自定义触发邮件发送条件。

image-20221130084603597

其中包含更多的配置可以点击?号查看说明。

例如:

  • 自定义邮件模板

    image-20221130085235371

2.5.3 配置邮件通知

该邮箱通知是系统级别的,系统出现问题会通过此发送邮件。

image-20221130084802822

发送测试邮件。

image-20221130084819218

image-20221130084847979

2.5.4 项目构建后操作添加邮件提示

image-20221130090739211

项目构建后发送邮件成功:

1
2
3
4
Email was triggered for: Success
Sending email for trigger: Success
Sending email to: jarryxy@qq.com
Finished: SUCCESS

image-20221130092348389

邮件发送异常处理

  • 报错jakarta.mail.AuthenticationFailedException: 535 Error: authentication failed

    image-20221130084108697

    原因在于没有在”系统管理(Manage Jenkins)”的”系统设置(Configure system)”中”Jenkins Location”进行系统管理员邮件地址(System Admin e-mail address)配置;或者配置错误。

    image-20221130084152853

    image-20221130084257175

  • 报错Failed messages: com.sun.mail.smtp.SMTPSendFailedException: 554 MI:SPB UserReject 0,smtp7,C8CowABnsSRz+OVYTTvPBA--.59938S2 1491466355,

    查看发现邮箱被冻结了,被人在新加坡登录发送广告邮件,点击进去解冻即可。

    image-20221130083829461

  • 没有收件人列表

    控制台输出

    1
    2
    An attempt to send an e-mail to empty list of recipients, ignored.
    Finished: SUCCESS

    解决方式:
    1、Default Recipients

    1. 通过Manage Jenkins进入Configure System
    2. 查看Default Recipients这一栏是否填写了收件人

2、Project Recipient List

  1. 进入具体的Job
  2. 查看Post-build Actions里有没有添加Editable Email Notification这个功能
  3. 不要勾选Disable Extended Email Publisher这个选项栏
  4. 查看Project Recipient List这一栏有没有填写收件人

3、 Recipient List

  1. 还是进入Editable Email Notification这一栏
  2. 点击进入右下角Advanced Settings…
  3. 查看Triggers这一栏有没有设置对应触发条件,比如Failure-Any和Success
  4. 默认的Developers不会发送给收件人,需要选择Recipient List

三、Jenkins集群配置并发构建

集群化构建可以有效提升构建效率,尤其是团队项目比较多的时候,可以并发在多台机器上执行构建。

打开Manage Nodes and CloudsAdd

image-20221201170854585

新建节点

image-20221201171036208

节点配置内容

  • 标签: 标签非常有用,如果我们需要执行在某个机器上构建,以及流水线操作,写脚本等等,也需要引用这个标签进行制定在哪个机器上执行构建job。

image-20221201172123888

image-20221201172246167

image-20221201172552003

添加完成后,可以查看本节点日志

image-20221201172955620

可以查看到Jenkins成功连接到节点后,将remoting.jar拷贝了过去,并启动运行了,所以节点机器不需要安装jenkins,只需要安装Java环境以及job构建需要的环境即可,例如git、maven等等。

image-20221201173115506

成功连接,已同步,可以查看到节点机器的信息。

image-20221201173434556

配置多节点后,项目的general会多出两项配置

image-20221201174432301

四、容器化构建

4.1 容器化构建的三种方式

image-20221202054731734

  1. 外挂目录,不用重新构建镜像,运行文件存储在宿主机上,映射到docker中运行,每次需要将jar传输到部署服务器并重新启动docker镜像。
  2. 打包镜像,将jar传输到部署服务器中,在部署服务器中打包jar到docker镜像中,每次需要进行重新打包运行。
  3. 打包镜像推送私服,在jenkins构建服务器中进行打包推送即可,适合云原生环境。

4.2 外挂目录方式

测试服务器安装docker

https://docs.docker.com/engine/install/centos/

1
2
3
$ sudo yum install -y yum-utils
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y

在测试服务器执行命令

1
2
3
4
5
6
7
# 拉取openjdk镜像
[root@localhost ~]# docker pull openjdk:11
REPOSITORY TAG IMAGE ID CREATED SIZE
openjdk 11 5505a9a39df1 5 months ago 659MB
# 运行镜像openjdk:11 将/root/jars/jenkins-springboot-0.0.1-SNAPSHOT.jar挂载
# 到容器/app.jar中,并执行java -jar app.jar,端口映射到外部9001
[root@localhost ~]# docker run -d -p 9001:9000 --name demo -v /root/jars/jenkins-springboot-0.0.1-SNAPSHOT.jar:/app.jar openjdk:11 java -jar app.jar

在jenkins中部署

pre steps中添加执行命令
1
docker stop demo && docker rm demo
post step添加如下配置

image-20221202094311073

4.3 打包镜像方式

源代码中添加docker/Dockerfile文件

image-20221202110545877

jenkins添加post steps,传输jar到测试服务器

image-20221202110801735

jenkins添加post steps,传输Dockerfile到测试服务器中,并添加Exec command

1
2
3
4
5
docker stop  jenkins-springboot
docker rm jenkins-springboot
docker rmi jenkins-springboot
docker build -t jenkins-springboot /root/jars/jenkins-springboot
docker run -d -p 9005:9000 --name jenkins-springboot jenkins-springboot

image-20221202110826252

五、流水线pipeline

流水线既能作为任务的本身,也能作为jenkinsfile。

使用流水线可以让我们的任务从ui手动操作,转换为代码化,像docker的dockerfile一样,从shell命令道配置文件,更适合大型项目,让我们团队其他开发者同时参与进来,同时也可以编辑开发jenkinswebui不能完成的更复杂的构建逻辑,作为开发者可读性也更好。

5.1 pipeline语法

5个必备的组成部分

1
2
3
4
5
pipline:整条流水线
agent:指定执行器
stages:所有阶段
stage:某一阶段,可以有多个
steps:阶段类的每一步骤,可执行命令

post,流水线完成后可执行的任务

  • always 无论流水线或者阶段的完成状态。
  • changed,只有当流水线或者阶段的状态与之前不同
  • failure,只有当流水线或者阶段状态为failure
  • success,只有当流水线或者阶段状态为success
  • unstable,只有当流水线或者阶段状态为unstable,例如,测试失败
  • aborted,只有当流水线或者阶段状态为aborted,例如,手动取消

agent,可以指定指定节点

label,指定运行job的节点标签

any,不指定,有jenkins分配

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pipeline {
agent any

stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}

post {

}
}

声明式流水线

好处:

  • 更像是在jenkins web ui中的操作
  • 可读性比较高
  • 可以使用blue ocean自动生成
  • 支持语法检查

坏处:

代码逻辑能力比脚本式流水线弱,不能完成特别复杂的任务

脚本式流水线,官方现在不推荐了 grovory 难调试吧

好处:

  • 更少的代码和弱规范要求
  • 更灵活的自定义代码操作
  • 不受约束,可以构建特别复杂的工作流和流水线

坏处

  • 读写对编程要求比较高
  • 比声明式流水线代码更复杂

5.2 blue ocean可视化界面

安装blue ocean插件

image-20221202112153239

blue ocean插件界面ui

image-20221202124652682

image-20221202124738104

image-20221202124807285

5.3 将4.3打包镜像方式改造成流水线

新建一个名称为jenkins-springboot-pipeline的pipeline任务

image-20221202111545507

填入流水线脚本

image-20221202120843681

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
pipeline {
agent any

tools {
maven "maven3"
}
stages {
stage('拉取代码') {
steps {
git credentialsId: 'bf33c09d-8f17-4875-8174-bcf8d578d1a8', url: 'https://git.yuencode.cn/jiaxiaoyu/jenkins-springboot.git'
}
}

stage('执行构建') {
steps {
sh 'mvn clean package'
}
}

stage('部署测试服务器') {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'jenkins-testserver', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'jars/jenkins-springboot-pipeline', remoteDirectorySDF: false, removePrefix: 'target', sourceFiles: '**/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker stop jenkins-springboot
docker rm jenkins-springboot
docker rmi jenkins-springboot
docker build -t jenkins-springboot /root/jars/jenkins-springboot
docker run -d -p 9005:9000 --name jenkins-springboot jenkins-springboot''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: 'jars/jenkins-springboot-pipeline', remoteDirectorySDF: false, removePrefix: 'docker', sourceFiles: '**/docker/Dockerfile')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
}

注意:

要使用mvn命令,需要在tools中配置maven [name],其中nameGlobal Toll Configuration中配置的Maven Name,

image-20221202121429967

tools {
    maven "maven3"
}
stage('执行构建') {
    steps {
        sh 'mvn clean package'
    }
}

5.4 片段生成器

点击脚本输入框下方流水线语法即可进入片段生成器

image-20221202120930391

生成git拉取代码

image-20221202113833081

文件传输同样可以使用片段生成器

image-20221202115423494

image-20221202115720609

5.5 使用Jenkinsfile创建多分支流水线的job

这里的多分支指的是不同分支的代码,不是指的逻辑上的分支判断语句。

image-20221203005645622

blue ocean中也可以创建流水线。

image-20221202125401583

image-20221202125707810

blue ocean似乎有bug,有时候通过其创建不成功,也可以在原生的地方创建,选择多分支流水线

image-20221203005945329

在git仓库中提交Jenkinsfile文件,通过控制不同分支上Jenkinsfile文件内容的不同,而实现多分支构建。

image-20221203003954815

可以看到在不同分支上执行的流水线代码是不一样的

master分支上

image-20221203004734010

test分支上

image-20221203004817117