[TOC]
0x00 前言简述
Jenkins 介绍
Q: 什么是Jenkins?
答: Jenkins 是一个开源持续集成的工具(
CI&CD
)由Java开发而成, 用于自动化各种任务,包括构建、测试和部署软件(自动化服务器
); Jenkins 支持各种运行方式,可通过系统包、Docker 或者 通过一个独立的Java程序;
官方介绍 : 全球领先的开源自动化服务器,Jenkins 提供了数以百计的插件来支持构建、部署和自动化任何项目
官方标语 : “Build great things at any scale”-“建造伟大的事情以任何规模”
Tips :个人理解 Jenkins 是一个调度平台,本身不需要处理任何事情,而是通过众多的插件来完成所有的工作;
Q: 为什么要用Jenkins?
答: Jenkins的前身是Hudson, 是基于Java开发的一种持续集成工具,用于监控秩序重复的工作, 它是可以将各个开源的软件进行集成的调度平台,例如(
Gitlab/SVN 、Maven、Sonarqube、Shell、钉钉通知、项目监控
)等;
Jenkins 发行线版本说明:
- TLS 长期支持版本: 每12周从常规版本流中选择,作为该时间段的稳定版本。 每隔 4 周,我们会发布稳定版本,其中包括错误和安全修复反向移植。
- 每周更新版本: 每周都会发布一个新版本,为用户和插件开发人员提供错误修复和功能。
Jenkins 特性
- 开源的java语言开发持续集成工具,支持CI,CD;
- 易于安装部署配置:可通过yum安装,或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理;
- 消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告;
- 分布式构建:支持Jenkins能够让多台计算机一起构建/测试;
- 文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等;
- 丰富的插件支持:支持扩展插件,你可以开发适合自己团队使用的工具,如git,svn,maven,docker
Jenkins 应用场景
- 1) 创建一个项目,手动构建,完成简单任务,比如拉取代码进行编译(持续集成)。
- 2) 编译失败通知用户
- 3) 参数化构建
- 4) 代码改动自动触发构建或者定时触发构建
- 5) 一个项目构建完成后自动调用另一个项目的构建,完成一连串任务
- 6) 并发构建
- 7) 集群化部署开发(CI/CD)
Jenkins Job 类型
- 1) Freestyle project : 自由风格项目,主要的项目类型
- 2) Maven project : maven项目专有,类似freestyle,更简单
- 3) Multiconfigration project : 多配置项目,适合大量不同配置(环境、平台等)构建
- 4) Pipeline : 流水线项目,适合使用pipeline 插件功能构建流水线任务,或者使用freestyle project不容易实现的负责任务
- 5) Multibranch pipeline : 多分支流水线项目,根据SCM仓库中的分支创建多个pipeline项目
0x01 安装配置
安装方式
安装参考: https://www.jenkins.io/zh/doc/book/installing/
- Windows(Jar 、War)、Linux(yum|rpm 、apt|dpkg)、Mac
- Docker
PS : Jenkins通常作为一个独立的应用程序在其自己的流程中运行, 内置Java servlet 容器/应用程序服务器(Jetty)。
系统要求
最低推荐配置:
- 256MB 可用内存
- 1GB 可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB)
小团队推荐的硬件配置:
- 1 GB+ 可用内存
- 50 GB+ 可用磁盘空间
软件配置: Java 8—无论是Java运行时环境(JRE)还是Java开发工具包(JDK)都可以
Tips : 安装最低配置:不少于256M内存,不低于1G磁盘,JDK版本>=8(openjdk也可以)。
PS : Jenkins 依赖于 Java 环境, 如果是在不使用Docker安装Jenkins时就需要安装配置Java环境;1
2
3
4# Jenkins 版本与 Java版本依赖关系
2.164 (2019-02) and newer: Java 8 or Java 11
2.54 (2017-04) and newer: Java 8
1.612 (2015-05) and newer: Java 7
Ubuntu
Jenkins的Debian Package Repository
,以自动化安装和升级。要使用此存储库,请先将键添加到系统:
Jenkins Debian Packages:https://pkg.jenkins.io/debian-stable/
官方安装:1
2
3
4
5
6
7
8# 添加 gpg key
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
# 在 /etc/apt/sources.list 中添加以下条目 deb https://pkg.jenkins.io/debian-stable binary/
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
# 更新您的本地包索引,然后最终安装Jenkins:
sudo apt-get update
sudo apt-get install jenkins
国内安装: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
31
32
33
34# Java 环境安装配置 jdk-8u211-linux-x64.tar.gz
# 下载地址: https://www.oracle.com/cn/java/technologies/javase-downloads.html
sudo mkdir /opt/app/ && cd $_
tar -zxvf jdk-8u211-linux-x64.tar.gz -C /usr/local/
# 环境变量设置(临时生效) set oracle jdk environment
ln -s /usr/local/jdk1.8.0_211/bin/java /usr/bin/java
export JAVA_HOME=/usr/local/jdk1.8.0_211 ## 这里要注意目录要换成自己解压的jdk 目录
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
# 环境安装测试
root@jenkins:/usr/local/jdk1.8.0_211# java -version
# java version "1.8.0_211"
# Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
# Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
# Jenkins 下载& 安装
sudo wget https://mirrors.aliyun.com/jenkins/debian-stable/jenkins_2.263.1_all.deb
sudo dpkg -i jenkins_2.263.1_all.deb
# 更新站点配置
sed -i "s#updates.jenkins.io#mirrors.tuna.tsinghua.edu.cn/jenkins/updates/#g" /var/lib/jenkins/hudson.model.UpdateCenter.xml
# 启动 Jenkins 并查看状态
systemctl restart jenkins
systemctl status jenkins
# ● jenkins.service - LSB: Start Jenkins at boot time
# Loaded: loaded (/etc/init.d/jenkins; generated)
# Active: active (exited) since Wed 2020-12-23 14:10:12 UTC; 6s ago
# Docs: man:systemd-sysv-generator(8)
# Process: 357567 ExecStart=/etc/init.d/jenkins start (code=exited, status=0/SUCCESS)
安装后设置向导:
参考地址: https://www.jenkins.io/zh/doc/book/installing/#setup-wizard
- (1) 解锁 Jenkins
当您第一次访问新的Jenkins实例时,系统会要求您使用自动生成的密码对其进行解锁。
浏览到 http://localhost:8080(或安装时为Jenkins配置的任何端口),并等待解锁 Jenkins 页面出现。
1 | # Jenkins控制台日志显示可以获取密码的位置(在Jenkins主目录中) |
- (2) 自定义jenkins插件
解锁 Jenkins之后,在 Customize Jenkins 页面内, 您可以安装任何数量的有用插件作为您初始步骤的一部分。
两个选项可以设置:- 安装推荐的插件 - 安装推荐的一组插件,这些插件基于最常见的用例.
- 选择插件来安装 - 选择安装的插件集。当你第一次访问插件选择页面时,默认选择建议的插件。(
新手首次搭建建议选择此项
)

WeiyiGeek.选择安装的插件
PS : 如果您不确定需要哪些插件,请选择安装建议的插件
。 您可以通过Jenkins中的Manage Jenkins > Manage Plugins
页面在稍后的时间点安装(或删除)其他Jenkins插件 。
- (3) 不安装任何插件进入
插件列表
点击右上角的x
关闭窗口,显示如下页面则跳过了管理员用户密码重设;

WeiyiGeek.初始化成功页面
PS : 一旦初始安装完成后,可通过插件管理器安装其他插件
- (4) 进入 Jenkins 控制台安装成功,然后第一个管理员用户;
点击 Dashboard -> admin -> Configure -> Password 进行管理员密码设置;
从这时起,Jenkins用户界面只能通过提供有效的用户名和密码凭证来访问。
Ubuntu 下 Jenkins 相关文件及其目录(目录结构)一览: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
31# 配置文件
/etc/default/jenkins
# /etc/sysconfig/jenkins # CentOS
# 家目录&插件目录&构建工作目录
/var/lib/jenkins/
/var/lib/jenkins/config.xml # jenkins root configuration
/var/lib/jenkins/userContent # 该目录下的文件将在http://server/userContent/下提供
/var/lib/jenkins/plugins # 插件
/var/lib/jenkins/logs # 存放jenkins相关的日志
/var/lib/jenkins/fingerprints # 存储指纹记录
/var/lib/jenkins/secrets # 密码秘钥所在目录
/var/lib/jenkins/workspace # 各任务的构建工作目录
/var/lib/jenkins/jobs # 浏览器上面创建的任务都会存放在这里
+- [JOBNAME] # 每个作业Job的子目录
+- config.xml # (job configuration file)
+- workspace # (working directory for the version control system)
+- latest # (symbolic link to the last successful build)
+- builds
+- [BUILD_ID] # (for each build)
+- build.xml # (build result summary)
+- log # (log file)
+- changelog.xml # (change log)
# 启动文件 {start|stop|status|restart|force-reload}
/etc/init.d/jenkins
# systemd 管理的serice
/run/systemd/generator.late/jenkins.service
/run/systemd/generator.late/graphical.target.wants/jenkins.service
/run/systemd/generator.late/multi-user.target.wants/jenkins.service
文件内容&目录结构详细说明
1.config.xml 核心配置文件: 包含了Jenkins的版本信息、权限认证规则、workspace目录定义、builds目录定义、视图信息等等。其他的 xml 文件是 Jekins 服务扩展功能的配置信息文件。
2.plugins 插件目录: 已经安装的Jenkins插件都可以在里面找到对应的文件。每一个插件基本是由一个目录和一个与目录同名的文件配对组成。
3.jobs 执行任务存储目录: 该目录是 Jenkins 管理的所有
构建任务的配置细节、构建后的产物和数据
。Jenkins 服务所有的 Job 都会在这个目录下,创建一个以 Job 名称命名的文件夹。
job 任务的文件夹中存储的文件有:1
2
3
4
5
6config.xml 任务的XML格式声明信息。
nextBuildNumber 文件记录下次构建时的 buildNumber
builds 目录存储此 Job 构建的历史。
~ $ ls /var/lib/jenkins/jobs/
HelloWorld Kubernetes-jenkins-slave pineline-use-node4.workspace 工作空间目录: 包含了这个构建作业的源代码, Jenkins存放项目的工作空间。进入这个workspace目录,里面就是你之前创建的项目的目录。在构建过程中Jenkins会根据项目中配置的远程代码仓库的地址去拉取源码到项目目录中并在这里完成打包。之前我们在打包的脚本中用到的
$WORKSPACE
表示的就是workspace下对应项目的目录。
- 5.tools 工具目录: Jenkins 服务设置安装 tools ,会安装在这个目录中。安装工具的方式是:【Manage Jenkins】 -> 【Global Tool Configuration】 页面。
6.updates 更新目录: 用来存放可用的插件更新。
7.users 用户信息目录: 存储用户的账号信息。
8.nodes 节点目录: Jenkins 在配置了主从或者工作节点之后会在这里有相应的信息。
9.userContent 用户生成的文件: 用于存储在 Jenkins 管理过程中生成的文件;比如使用
Convert To Pipeline 插件
可以将 JOB 转换成 Pipeline,生成的 Pipeline 的内容会以文件的形式存储在这个文件夹中。10.fingerprints 文件指纹目录:
文件指纹(fingerprints)
是一个简单的MD5校验和。Jenkins维护了一个md5sum数据库,用于文件指纹校验。对于每个md5sum,Jenkins记录了哪些项目的哪些构建使用了他。在每次构建运行和文件被采集指纹时这个数据库会更新。为了避免过多的磁盘使用,Jenkins不存储实际的文件。相反它只存储md5sum和它的使用记录。11.logs 日志目录: 用于存储 Jenkins 服务的日志,主要是事件日志和工作日志。
12.war 目录: 如果是以WAR包形式运行的Jenkins,该目录下存放的是解压后的WAR包。
13.Jenkins 服务另外的文件目录:
1
2
3
4
5secrets
init.groovy.d
workflow-libs
scriptler
config-history
Tips: jenkins存放数据不依靠数据库所以在移植时只需要拷贝整个程序主目录即可,需要注意的是jobs和plugins目录比较重要
Docker 安装
描述: 使用容器化的方式部署 Jenkins Master 节点,可以选择自行构建镜像,推荐使用 Jenkins 官方提供的镜像。
Jenkins 服务官方在 dockerhub 平台发布官方镜像https://hub.docker.com/u/jenkins
1.Jenkins Master 镜像基础使用
- Jenkins Web 服务监听的端口为 8080
- Jenkins 使用JNLP 连接 Agent 节点使用的端口为 5000
- Jenkins 在 /var/jenkins_home 目录中保存workspace中的数据,包括插件和配置信息
- Jenkins 服务默认使用jenkins 用户运行,uid为1000;请注意文件权限问题
2.Jenkins Master 使用和升级
使用 Jenkins 的镜像构建容器时,至少要将端口映射出去,将/var/jenkins_home 目录做持久化。1
2
3
4
5
6
7
8
9
10
11# 示例:用 jenkins:2.107.3 创建容器并运行。
docker volume create jenkins-data
docker run --name jenkins-production \
--detach \
-p 50000:50000 \
-p 8080:8080 \
-v jenkins-data:/var/jenkins_home \
jenkins/jenkins:2.275-alpine
# If run for the first time, just run the following to get the admin
# password once it has finished starting
docker exec jenkins-production bash -c 'cat $JENKINS_HOME/secrets/initialAdminPassword'
在需要对 Jenkins 服务升级时,只需要使用新的镜像替换即可;持久化存储和端口映射操作相同。
示例:将 Jenkins 服务升级到 2.121.31
2
3
4
5
6
7
8
9docker stop jenkins-production
docker rm jenkins-production
# just temporarily docker rename it instead if that makes you worried
docker run --name jenkins-production \
--detach \
-p 50000:50000 \
-p 8080:8080 \
-v jenkins-data:/var/jenkins_home \
jenkins/jenkins:2.277-alpine
3.Jenkins Master 节点配置扩展(了解即可)
3.1 设置Master 节点的执行者 executors 数量
描述: 使用groovy脚本指定并设置Jenkins Master 实例的执行程序数。默认情况下,它设置为2个执行者,但是您可以扩展映像并将其更改为所需的执行者数:1
2
3
4
5
6
7
8executors.groovy
import jenkins.model.*
Jenkins.instance.setNumExecutors(5)
# 和 Dockerfile
FROM jenkins/jenkins:lts
COPY executors.groovy /usr/share/jenkins/ref/init.groovy.d/executors.groovy3.2 传递 JVM 的启动参数
描述: 您可能需要自定义运行Jenkins的 JVM,通常是为了传递系统属性(props列表)或调整堆内存设置1
2# 使用JAVA_OPTS环境变量:
docker run --name myjenkins -p 8080:8080 -p 50000:50000 --env JAVA_OPTS=-Dhudson.footerURL=http://mycompany.com jenkins/jenkins:lts3.3 给 Jenkins 启动器传递参数
描述: 您传递给运行 Jenkins 镜像的 docker 的参数将传递给 jenkins 启动器 ,例如运行docker run jenkins/jenkins:lts --version
将显示Jenkins版本1
2
3
4
5
6
7
8
9
10
11
12
13
14# 通过定义Jenkins参数 JENKINS_OPTS
示例1.Dockerfile使用此选项来强制将HTTPS与映像中包含的证书一起使用。
FROM jenkins/jenkins:lts
COPY https.pem /var/lib/jenkins/cert
COPY https.key /var/lib/jenkins/pk
ENV JENKINS_OPTS --httpPort=-1 --httpsPort=8083 --httpsCertificate=/var/lib/jenkins/cert --httpsPrivateKey=/var/lib/jenkins/pk
EXPOSE 8083
# 通过定义Jenkins参数 JENKINS_SLAVE_AGENT_PORT
示例2.Dockerfile中定义来更改jenkins的默认从属代理端口。
FROM jenkins/jenkins:lts
ENV JENKINS_SLAVE_AGENT_PORT 50001
# 或作为docker的参数
docker run --name myjenkins -p 8080:8080 -p 50001:50001 --env JENKINS_SLAVE_AGENT_PORT=50001 jenkins/jenkins:ltsTips :此环境变量将用于设置将系统属性添加
jenkins.model.Jenkins.slaveAgentPort
到JAVA_OPTS的端口 。3.4 配置日志记录
描述: 可以通过属性文件和java.util.logging.config.fileJava
属性来配置Jenkins日志记录。例如:1
2
3
4
5
6
7
8
9
10
11mkdir data
cat > data/log.properties <<EOF
handlers=java.util.logging.ConsoleHandler
jenkins.level=FINEST
java.util.logging.ConsoleHandler.level=FINEST
EOF
docker run --name myjenkins -p 8080:8080 -p 50000:50000 \
--env JAVA_OPTS="-Djava.util.logging.config.file=/var/jenkins_home/log.properties"\
- v `pwd`/data:/var/jenkins_home jenkins/jenkins:lts3.5 调整Jenkins 浏览器访问的路径path
描述: 如果您需要在浏览器中访问 Jenkins 服务时要添加一个 path 路径,则需要添加环境变量JENKINS_OPTS="--prefix=/jenkins"
。
Tips : 容器中 Docker 客户端配置
1.构建 NodeJS 任务执行镜像的 Dockerfile 文件内容:
1
2
3FROM docker.io/node:alpine
run apk add --no-cache git docker-cli
RUN yarn config set registry "https://registry.npmmirror.com"2.配置 Docker 客户端连接远程的 Docker 服务端:使用一个环境变量就可以实现这个配置。
1
2
3env:
- name: DOCKER_HOST
value: tcp://docker.example.com:2375
Tips : 配置镜像仓库的认证信息,认证信息一般存储在 /root/.docker/config.json
文件中。这里可以模仿前面 Maven 服务的 settings.xml 文件的配置方式配置, 然后就可以实现了连接 Docker Server 端构建镜像,对镜像打 tag 的操作, 然后将制作好的镜像推送到远程的镜像仓库中,例如Harbor。
Kubernetes 安装
请参考后续的 <(2) 集群搭建Jenkins Master 节点>
章节的文章。
0x02 基础知识
Jenkins 环境变量
描述: 环境变量可以被看作是pipeline与Jenkins交互的媒介, 环境变量可以分为Jenkins内置变量
和自定义变量
以及自定义全局环境变量
。
比如,可以在 pipeline 中通过 BUILD_NUMBER 变量知道构建任务的当前构建次数。
1.内置变量
描述: 在pipeline执行时,Jenkins通过一个名为 env 的全局变量,将Jenkins内置环境变量暴露出来。1
2
3${env.BUILD_NUMBER} 方式一,推荐使用
$env.BUILD_NUMBER 方式二,
${BUILD_NUMBER} 方式三,不推荐使用
例如:在实际工作中经常用到的变量。1
2
3
4BUILD_URL:当前构建的页面URL。
BUILD_NUMBER:构建号,累加的数字。
BRANCH_NAME:多分支pipeline项目支持。
GIT_BRANCH:通过git拉取的源码构建的项目才会有此变量。
2.自定义环境变量
描述: 当 pipeline 变得复杂时,我们就会有定义自己的环境变量的需求。声明式 pipeline 提供了environment 指令,方便自定义变量。
另外 environment 指令可以在pipeline中定义,代表变量作用域为整个 pipeline;也可以在 stage 中定义,代表变量只在该阶段有效。
Tips : 如果在environment中定义的变量与env中的变量重名,那么被重名的变量的值会被覆盖掉。
3.自定义全局环境变量
描述: 如果我们需要定义一些全局的跨pipeline的自定义变量。
我们可以进入 Manage Jenkins→Configure System→Global properties
页,勾选“Environment variables”复选框
,单击“Add”按钮,在输入框中输入变量名和变量值即可,
Tips : 自定义全局环境变量会被加入 env 属性列表中,所以,使用自定义全局环境变量与使用Jenkins内置变量的方法无异。
Tips : Jenkins 内置变量参考 请看补充说明中的内置环境变量
Jenkins 参数构建类型
主要缺省参数类型如下几类:
- Boolean 参数
- Choice 参数 (常用)
- String 参数 (常用)
- File 参数
- 密码 参数
- 凭据 参数
- 其他 参数
- 运行时 参数
额外的我们需要安装Extended Choice Parameter 和 git Parameter,以便向 Choice 参数添加扩展功能 以及 使用Git参数来获取分支。
使用过程
在参数化构建过程 -> 构建参数添加 -> 构建参数的变量 ->通过 $paramater 或者 ${paramater}
的形式使用

WeiyiGeek.构建参数
Tips : 环境变量生效的顺序全局环境变量 < slave配置环境变量 < JOB参数 < JOB injected环境变量
官网地址: https://www.jenkins.io/
官方文档: https://www.jenkins.io/zh/doc/
Jenkins 并发构建
描述: 我们创建Job可以进行并发构建,每个并发构建使用单独的workspace,默认是<workspace path>@<num>

WeiyiGeek.并发构建
Tips : slave 也可以进行并发构建前提是需要Node and Label parameter plugin
插件,并且需要配置node类型参数;
Jenkins 自动化构建
常见的triggers几种:
- Build periodically : 设定类似cron周期性时间触发构建
- poll SCM : 设定类似 cron 周期性时间触发检查代码变化,只有代码变动时才触发构建
- Hooks : 用过SVN的都知道钩子
Github hooks / Gitlab hooks
- Events : Gerrit event

WeiyiGeek.triggers
build periodically
描述: H 代表 jenkins 自己分配时间不去指定客观时间, 注意一般都是Jenkins根据监控资源利用率算法分配的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# * * * * *
# 第一颗*表示分钟,取值0~59
# 第二颗*表示小时,取值0~23
# 第三颗*表示一个月的第几天,取值1~31
# 第四颗*表示第几月,取值1~12
# 第五颗*表示一周中的第几天,取值0~7,其中0和7代表的都是周日
1.每30分钟构建一次:H/30 * * * *
2.每2个小时构建一次 H H/2 * * *
3.每天早上8点构建一次: 0 8 * * *
4.每天的8点,12点,22点,一天构建3次 0 8,12,22 * * *
# 多个时间点,中间用逗号隔开
Poll SCM
描述: 他会定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来然后执行构建动作;
比如: 你可以如果我想每隔30分钟检查一次源码变化有变化就执行;1
H/30 * * * *
Jenkins 上下游构建
触发下游构建:
- 1) 其他项目构建后触发: “Build other projects” under “Post build actions” -> 输入项目名称
- 2) 利用 Parameterized Trigger 插件 参数化构建 -> 在构建后操作步骤中 ->
Trigger Parameterized build on other peoject
->Restrict matrix execuson to a subset

WeiyiGeek.上下游构建
Jenkins 调用API
描述: Jenkins 服务提供了很多类型的API;因为工作需要这里只记录一下执行job的API使用CURL调用的方式。
Jenkins API 介绍
1.Jenkins API 从级别上分类
1
2
3* 站点 API:创建Job、复制Job、Build 队列、重启Jenkins等
* Job API:修改Job、删除Job、获取 Build 信息、Build Job、禁用Job、启用Job
* Build Job: 根据 Build Number 获取Build 信息,获取Build 控制台的输出日志2.传输数据格式: POST 传输数据支持的格式有
XML,JSON,PYTHON
3.安全处理: 可以找到一些开发语言编写的API封装包,结合到自己的脚本中,提高开发效率。
1
2* CSRF 跨域攻击保护:可以在全局安全中设置。
* 用户验证设置:可以使用用户的密码,也可以为用户创建token。
CURL 调用 API 执行 Job 实例:1
2
3
4# Curl Api 调用
CURL -X POST ${JOB_URI}
--user ${user_name}:${user_password}|${user_token}
--data-urlencode json="{\"parameter\":${JSON_DATA},\"statusCode\":\"303\",\"redirectTo\":\".\"}"
参数解析:
- JOB_URL: 就是Job 的访问URL地址。在Job 页面中点击
”Build with Parameters”
就可以获取到地址。一般以”build?delay=0sec“结尾; 示例:http://192.168.1.1/job/HelloWorld/build?delay=0sec
- user_name,user_password,user_token 用户验证信息
- JSON_DATA:Job 运行时,需要传递的参数,由Json 结构封装;示例:
[{\"name\":\"branchName\",\"value\":\"origin/dev\"},{\"name\":\"projectName\",\"value\":\"helloworld\"}]
0x03 基础配置
视图管理
描述: 当Job创建数量达到一定时我们需要在Jenkins中建立视图(分类),可以帮助我们快速找到某个所需Job;
实际上Job的视图类似于我们电脑上的文件夹可以通过一些过滤规则,将已经创建好的Job过滤到视图之中,也可以在视图中直接创建我们的Job;
我们可以采用View
或者directory
文件两种方式进行管理:
- views - 视图方式
1
2views视图更加灵活,不改变job的路径
views有多种形式、层级、看板,流水线等多样化 - directory - 文件夹方式 (名称空间隔离)
1
2
3文件夹适合多个团队共用Jenkins
性能更好,执行速度更快
支持RBAC权限管理
两则异同说明: 文件夹创建一个可以嵌套存储的容器利用它可以进行分组,而视图仅仅是一个过滤器,其次文件夹则是一个独立的命名空间
,因此你可以有多个相同名称的的内容,只要它们在不同的文件夹里即可。
views - 视图方式
创建流程:
Step 1.我的视图 -> 点击所有旁边 + 号 -> 设置视图名称 -> 选择三种类型
列表视图/包括全局视图/我的视图
列表视图 : 显示简单列表。你可以从中选择任务来显示在某个视图中
包括全局视图 : Shows the content of a global view.
我的视图 : 该视图自动显示当前用户有权限访问的任务Step 2.此处设置列表视图为例 -> 选择任务列表 -> 增加或者删除指定显示列

WeiyiGeek.views
directory - 文件夹方式
创建流程:
- Step 1.创建Job -> 选择
文件夹
-> 输入任务名称directory-test
- Step 2.在
directory-test
文件夹下 -> 可以继续创建视图(+ )
-> 选择(列表视图/包括全局视图/我的视图
)

WeiyiGeek.directory
插件管理
(1) 插件安装加速
Q: 在安装插件时如何进行配置安装加速?
答: 选择国内清华大学的Jenkins插件更新源
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
配置位置: Dashboard > Plugin Manager > Advanced > Update Site

WeiyiGeek.插件安装加速
(2)插件安装的几种方式
- Step 1.采用插件更新源搜索进行在线安装,例如下面对Jenkins进行汉化插件的安装, 搜索
Localization: Chinese (Simplified)
插件安装即可;WeiyiGeek.Jenkins 汉化插件安装
当安装插件安装完成时候可以选择重启 Jenkins 或 跳转到首页, 此处我重启 Jenkins 如下图所示汉化成功;

WeiyiGeek.Jenkins 汉化界面
- Step 2.通过Web页面上传.hpi文件进行插件安装
清华大学 jenkins 插件下载: https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/
例如下面进行 git 插件下载 进行上传其git.hpi
文件进行插件安装,之后上传即可;

WeiyiGeek.Jenkins git 插件安装
- Step 3.导入之前服务器已安装的插件进行离线安装;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# (1) Jenkins 已安装的插件目录
/var/lib/jenkins/plugins$ ls
# apache-httpcomponents-client-4-api display-url-api jdk-tool localization-zh-cn script-security trilead-api
# apache-httpcomponents-client-4-api.jpi display-url-api.jpi jdk-tool.jpi localization-zh-cn.jpi script-security.jpi trilead-api.jpi
# command-launcher git jsch mailer ssh-credentials workflow-scm-step
# command-launcher.jpi git-client jsch.jpi mailer.jpi ssh-credentials.jpi workflow-scm-step.jpi
# credentials git-client.jpi localization-support scm-api structs workflow-step-api
# credentials.jpi git.jpi localization-support.jpi scm-api.jpi structs.jpi workflow-step-api.jpi
# (2) 打包插件目录并上传到另外一台同版本的Jenkins服务器(PS:不同版本间可能会出现插件不兼容的情况)
tar -zcvf jenkins_2.263.1_plugins.tar.gz /var/lib/jenkins/plugins
# (3) 解压插件目录并进行所属者组修改
tar -zxvf jenkins_2.263.1_plugins.tar.gz
chown -R jenkins:jenkins /var/lib/jenkins/plugins
# (4) 启动 Jenkins 服务
systemctl stop jenkins
systemctl start jenkins
# (5) 启动 日志 查看
tail -f /var/log/jenkins/jenkins.log
权限管理
描述: 由于jenkins
默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,我们使用Role-based Authorization Strategy
插件,安装请参考前面插件管理章节。
插件功能特点:
- 按角色分权限
- 按项目分权限
Step 1.插件安装后我们先启用该插件管理Jenkins权限 -> 面板 -> 全局安全配置(
Global Security
)-> 授权策略 -> 找到并选中Role-Based Strategy
-> 然后应用保存 。Step 2.管理Jenkins -> 安全 ->
Manage and Assign Roles
-> 可以进行角色权限管理与分配 -> 此处添加一个test角色并设置其权限 -> 应用 -> 保存;
·- Step 3.Assign Roles -> Global roles(按角色)、Item roles(按项目)、Node roles(按节点) -> 用户添加(同时您需要在Jenkins用户中新增一个该用户) -> 保存应用
- 添加用户和组。默认情况下用户/组名是区分大小写的,因此它需要与您在
Configure Global Security->Access Control->Security Realm
下的用户/组定义匹配。
- 添加用户和组。默认情况下用户/组名是区分大小写的,因此它需要与您在

WeiyiGeek.jenkins权限管理
构建工具管理
在 Jenkins 服务中运行 Pipeline 等任务过程中,需要依赖一些工具(环境需求);比如 JDK,MAVEN或者golang 或者 python 环境。
构建工具的安装方式有三种:
1) 自行安装工具: 即自行在服务器上安装配置,然后在 Jenkins 服务中配置好这些工具的安装信息就可以使用了。配置路径:
Manage Jenkins→Global Tool Configuration
2) Jenkins 自动安装工具: 利用 Jenkins 服务提供的【工具自动安装功能】,实现工具的快速配置。
3) tools 指令安装工具:帮助我们自动下载并安装所指定的构建工具,并将其加入 PATH 变量中。这样,我们就可以在sh步骤里直接使用了, 但在agent none的情况下不会生效。
Tips : tools指令默认支持3种工具:JDK、Maven、Gradle。通过安装插件,tools 指令还可以支持更多的工具。
0x04 基础使用
HelloWorld 自由风格软件项目
Q: Jenkins Free Style 基本使用?
目的: 构建一个自由风格的软件项目, 这是Jenkins的主要功能Jenkins将会结合任何SCM和任何构建系统来构建你的项目, 甚至可以构建软件以外的系统.
操作流程:
Step 1.项目创建
(1) 面板 -> 新建一个任务 -> 任务名称 freestyle-helloworld -> 保存
(2) Dashboard -> 项目名称 freestyle-helloworld -> General
1 | # 重要的配置项 |
(3) Dashboard -> 项目名称 freestyle-helloworld > 构建 > 执行 Shell 命令
1
2 echo "FreeStyle - HelloWorld"
touch hello-world.txt

WeiyiGeek.自由风格的软件项目
Step 2.工程 WeiyiGeek.工程构建与控制台输出freestyle-helloworld
构建与控制台输出查看;
PS : 如果是蓝色圆点表示构建成功, 如果是红色圆点表示构建失败!
Step 3.构建后的工作区存放目录1
2
3jenkins:/var/lib/jenkins/workspace/freestyle-helloworld$ ls
# hello-world.txt
jenkins:/var/lib/jenkins/workspace/freestyle-helloworld$ cat hello-world.txt
Gitlab 集成配置与实践
简单说明:
Q: Jenkins 为啥要集成Gitlab?
答:由于我们需要依托于Jenkins将Gitlab上的项目获取至本地,为后续网站的代码发布工作做好准备;
Q: Jenkins 如何集成Gitlab?
答: 由于Jenkins 只是一个调度平台,所以需要安装和Gitlab相关的插件即可完成集成;
Jenkins 与 Gitlab 集成思路
1.开发提交代码 至 Gitlab
2.Jenkins 安装 Gitlab 所需插件
1 | Credentials Plugin (2.3.14) - This plugin allows you to store credentials in Jenkins. |

WeiyiGeek.Gitlab关联插件
- 3.Jenkins 创建 FreeStyle 项目,然后配置Gitlab仓库对应的地址;
操作流程:
- Step 1.首先需要将我们所用的项目代码推送到Gitlab(此处假设您已安装Gitlab)之中;
(1) 管理中心 -> 群组 -> 新建群组 -> 完善信息 -> 创建群组
(2) 管理中心 -> 项目 -> 创建项目 -> 完善仓库信息 -> 创建项目
(3) 推送现有文件夹到Gitlab之中
1 | cd existing_folder |

WeiyiGeek.gitlab
- Step 2.此处假设您已经按照上面
Gitlab 集成配置
安装了相应的插件, 并且配置好gitlab域名访问的解析记录;
1 | # 此处由于没有自己搭建DNS,则将其写入到Jenkins 服务器的hosts文件中进行相应的IP与域名绑定 |
- Step 3.Jenkins 创建 FreeStyle 项目,然后配置Gitlab仓库对应的地址(
ssh 的方式
)
1 | # (1) 在Gitlab中添加当前机器ssh密钥(此处以Jenkins用户为例) |

WeiyiGeek.SSH Keys
- Step 4.Jenkins > FreeStyle 项目 > 源码管理 > Git > Repositories 设置 > Credentials 设置
PS : 如果是非Jenkins用户下公钥对Gitlab该项目有访问权限时,可以通过 Credentials 添加其认证的密钥即可;
1 | # (1) Weiyigeek 用户密钥 (此时假设Gitlab已经添加该公钥) |

WeiyiGeek.Weiyigeek 用户密钥
- Step 5.首先手动实现设置NFS共享存储以及 Kubernetes 部署 StatefulSet 资源清单,通过Nginx访问我们的blog;
基础配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# (1) NFS 服务器配置
root@nfs$ showmount -e
# /nfs/data4 *
/nfs/data4# ls -alh /nfs/
# drwxrwxrwx 2 weiyigeek weiyigeek 4.0K Nov 19 13:27 data4
/nfs/data4# mkdir /nfs/data4/tags/
/nfs/data4# ln -s /nfs/data4/tags/ /nfs/data4/web
/nfs/data4# chown -R nobody:weiyigeek /nfs/data4/
# (2) Node 1 && Node 2
sudo mkdir -pv /nfs/data4/
sudo chown -R weiyigeek:weiyigeek /nfs/data4/
sudo mount.nfs -r 10.10.107.202:/nfs/data4/ /nfs/data4/
k8s-node-4:/nfs/data4$ ls -alh # 权限查看
# total 12K
# drwxrwxrwx 3 weiyigeek weiyigeek 4.0K Dec 24 15:44 .
# drwxr-xr-x 3 root root 4.0K Dec 24 15:47 ..
# drwxr-xr-x 2 weiyigeek weiyigeek 4.0K Dec 24 15:44 tags
# lrwxrwxrwx 1 weiyigeek weiyigeek 16 Dec 24 15:44 web -> /nfs/data4/tags/
资源清单: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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65cat > jenkins-gitlab-ci.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
name: deploy-blog-svc
spec:
type: NodePort # Service 类型
selector:
app: blog-html # 【注意】与deployment资源控制器创建的Pod标签进行绑定;
release: stabel # Service 服务发现不能缺少Pod标签,有了Pod标签才能与之SVC对应
ports: # 映射端口
- name: http
port: 80 # cluster 访问端口
targetPort: 80 # Pod 容器内的服务端口
nodePort: 30088
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: deploy-blog-html
spec:
serviceName: "deploy-blog-svc"
replicas: 3 # 副本数
selector: # 选择器
matchLabels:
app: blog-html # 匹配的Pod标签非常重要
release: stabel
template:
metadata:
labels:
app: blog-html # 模板标签
release: stabel
spec:
volumes: # 关键点
- name: web
hostPath: # 采用hostPath卷
type: DirectoryOrCreate # 卷类型DirectoryOrCreate: 如果子节点上没有该目录便会进行创建
path: /nfs/data4/web # 各主机节点上已存在的目录此处是NFS共享
- name: timezone # 容器时区设置
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
containers:
- name: blog-html
image: harbor.weiyigeek.top/test/nginx:v3.0 # 拉取的镜像
imagePullPolicy: IfNotPresent
ports:
- name: http # 此端口在服务中的名称
containerPort: 80 # 容器暴露的端口
volumeMounts: # 挂载指定卷目录
- name: web
mountPath: /usr/share/nginx/html
- name: logs
mountPath: /var/log/nginx
- name: timezone
mountPath: /usr/share/zoneinfo/Asia/Shanghai
volumeClaimTemplates: # 卷的体积要求模板此处采用StorageClass存储类
- metadata: # 根据模板自动创建PV与PVC并且进行一一对应绑定;
name: logs
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: managed-nfs-storage # StorageClass存储类
resources:
requests:
storage: 1Gi
EOF
部署资源清单:1
2
3
4
5
6
7
8
9
10
11
12
13
14~/K8s/Day12$ kubectl apply -f jenkins-gitlab-ci.yaml
service/deploy-blog-svc unchanged
statefulset.apps/deploy-blog-html configured
~/K8s/Day12$ kubectl get services -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
deploy-blog-svc NodePort 10.104.74.36 <none> 80:30088/TCP 5m9s app=blog-html,release=stabel
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 49d <none>
~/K8s/Day12$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deploy-blog-html-0 1/1 Running 0 72s 10.244.0.193 Master
deploy-blog-html-1 1/1 Running 0 57s 10.244.1.182 k8s-node-4
deploy-blog-html-2 1/1 Running 0 49s 10.244.2.84 k8s-node-5
效果查看:1
2curl http://10.10.107.202:30088/host.html
# Hostname: deploy-blog-html-0 ,Image Version: 3.0, Nginx Version: 1.19.4
- Step 6.采用Tag方式发布和回退项目
Q: 为什么要让项目支持Tag版本方式上线?
答: 采用 Tag 的方式可以直观的知道我们部署的项目版本,同时也便于进行回退;
比如: 第一次上线v1.1第二次上线v1.2,如果此时上线的v1.2出现文件,那么我们可以快速回退至上一个版本v1.1;
使用Tag方式发布与回退思路:
1.开发如果需要发布新版本,必须将当前版本打上一个标签。
2.Jenkins需要让其脚本支持传参,比如用户传递v1.1则拉取项目的v1.1标签。
实践操作:
(1) 首先需要安装
Git Parameter
插件(增加了从项目中配置的git存储库中选择分支、标记或修订的能力。
),然后配置Jenkins参数化构建过程,让用户在构建时选择对应的Tag版本;
丢弃旧的构建 > 保持构建的最大个数 为 10 个
参数化构建过程 > Git 参数 > git_version (变量) -> 参数类型 Tags -> 默认值 (origin/master) -> 排序方式 (DESCENDING SMART) 倒序防止 Tags 顺序乱
;
选项参数 (选择) > deploy_option (变量) -> 选项 deploy|rollback
源码管理 > Git > Repository URL:git@gitlab.weiyigeek.top:ci-cd/blog.git > Credentials (密钥认证) -> 分支机构建设 (指定分支(为空时代表any)
)-> 引入 ${git_version} 变量
构建 > 执行shell > /bin/sh -x /tmp/script/blog-script.sh
应用 > 保存

WeiyiGeek.jenkins项目创建
(2) 部署和回退脚本以及自动化发布重复构建的问题处理编写
touch /tmp/script/blog-script.sh && chmod a+x $_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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# Description: Jenkins CI & Kubernetes & Gitlab -> Deploy or Rollback Blog HTML
DATE=$(date +%Y%m%d-%H%M%S)
TAG_PATH="/nfs/data4/tags"
WEB_PATH="/nfs/data4/web"
WEB_DIR="blog-${DATE}-${git_version}"
K8S_MATER="weiyigeek@10.10.107.202"
K8S_MATER_PORT="20211"
# 部署
deploy () {
# 1.打包工作目录中的项目
cd ${WORKSPACE}/ && \
tar -zcf /tmp/${WEB_DIR}.tar.gz ./*
# 2.上传打包的项目到master之中
scp -P ${K8S_MATER_PORT} /tmp/${WEB_DIR}.tar.gz weiyigeek@10.10.107.202:${TAG_PATH}
# 3.解压&软链接
ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "mkdir -p ${TAG_PATH}/${WEB_DIR} && \
tar -xf ${TAG_PATH}/${WEB_DIR}.tar.gz -C ${TAG_PATH}/${WEB_DIR} && \
rm -rf ${WEB_PATH} && \
ln -s ${TAG_PATH}/${WEB_DIR} ${WEB_PATH} && \
kubectl delete pod -l app=blog-html"
}
# 回退
rollback () {
Previous_Version=$(ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "find ${TAG_PATH} -maxdepth 1 -type d -name blog-*-${git_version}")
ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "rm -rf ${WEB_PATH} && \
ln -s ${Previous_Version} ${WEB_PATH} && \
kubectl delete pod -l app=blog-html"
}
# 部署 & 回退 入口(坑-==两边没有空格)
if [[ "${deploy_option}" = "deploy" ]]; then
# 坑 (防止字符串为空)
if [[ "v${GIT_COMMIT}" = "v${GIT_PREVIOUS_SUCCESSFUL_COMMIT}" ]];then
echo -e "您已经部署过 ${git_version} 版本"
exit 1
else
deploy
fi
elif [[ "${deploy_option}" = "rollback" ]];then
rollback
else
exit 127
fi
(3) Jenkins 服务器 与 Kubernetes Master 机器中的普通用户进行 ssh 公钥认证登录;
1 | # copy 公钥 到 对端主机 |
(4) 为我们的Blog打三个Tag并验证构建脚本
1 | $ cd ~/workspace/freestyle-blog |
(5) 进行项目构建 -> Build With Paramters 查看 部署的版本以及是部署还是回退 -> 如下图所示拉取的指定 Tags ;

WeiyiGeek.项目构建
(6) 项目构建部署验证 访问
http://10.10.107.202:30088/
博客地址
1 | Built Branches |

WeiyiGeek.项目构建部署验证
(6) 项目回退验证 > 请选择您要部署的RELEASE版本
v1.1
, 然后选择部署或是回退;

WeiyiGeek.项目回退验证
Maven 集成配置与实践
基本概述:
Q: 什么是Java项目?
答:简单来说就是使用Java编写的代码,我们将其称为Java项目;
Q: 为什么Java项目需要使用Maven编译?
答: 由于Java编写的Web服务代码是无法直接在服务器上运行,需要使用Maven工具进行打包;
简单理解: Java 源代码就像汽车的一堆散件,必须经过工厂的组装才能完成一辆完整的汽车,这里组装汽车可以理解是 Maven 编译过程;
Q: 在实现自动化构建Java项目时,先实现手动构建Java项目;
答: 因为想要实现自动化发布代码,就必须手动进行一次构建,既是熟悉过程又是优化我们的部署脚本;
大致流程: 源码 -> gitlab -> Maven 手动构建 -> 最后推送构建 -> 发布;
1 | # Maven 拉取 Jar 的几种途径 |
自动部署 Java 项目至 kubernetes 集群流程步骤:
- (1) Jenkins 安装 Maven Integration 插件,使Jenkins支持Maven项目的构建
- (2) Jenkins 配置 JDK 路径以及 Maven 路径
- (3) Jenkins 创建 Maven 项目然后进行构建
- (4) 编写自动化上线脚本推送至 kubernetes 集群
- (5) 优化部署脚本使其支持上线与回滚以及,相同版本重复构建
基础环境配置:
- Step 1. Jenkins 服务器中 Java 与 Maven 环境配置与 Maven 插件安装;
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# Java 环境
~$ ls /usr/local/jdk1.8.0_211/
~$ java -version
# java version "1.8.0_211"
# Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
# Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
# Maven 环境 (两种方式)
# ~$ sudo apt install maven # 方式1
~$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
~$ sudo tar -zxvf apache-maven-3.6.3-bin.tar.gz -C /usr/local
~$ ls /usr/local/apache-maven-3.6.3/
# bin boot conf lib LICENSE NOTICE README.txt
~$ sudo ln -s /usr/local/apache-maven-3.6.3/ /usr/local/maven # 非常值得学习(变版本却不变执行路径)
~$ /usr/local/maven/bin/mvn -v
# Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
# Maven home: /usr/local/maven
# Java version: 1.8.0_211, vendor: Oracle Corporation, runtime: /usr/local/jdk1.8.0_211/jre
# Default locale: en_US, platform encoding: UTF-8
# OS name: "linux", version: "5.4.0-46-generic", arch: "amd64", family: "unix"
~$ export PATH=/usr/local/maven/bin/:$PATH # 临时
~$ export PATH=${JAVA_HOME}/bin:/usr/local/maven/bin/:$PATH # 加入 /etc/Profile永久
~$ mvn -v
# Maven Integration 插件 安装
# PS : 提供了Jenkins和Maven的深度集成:根据快照在项目之间自动触发,各种Jenkins发布者的自动配置(Junit)。
# Jenkins 中 Maven 集成配置
> 面板 -> 全局工具配置 -> JDK 配置 -> 新增JDK -> 别名 jdk_env -> JAVA_HOME /usr/local/jdk1.8.0_211/
-> 新增Maven -> 别名 maven_env -> MAVEN_HOME /usr/local/jdk1.8.0_211/WeiyiGeek.Maven 集成配置
- Step 2.手动我们的Java的Maven项目, 测试Jenkins服务器上的Maven是否可以正常编译War包并运行在单机的Tomcat8 之中;
Maven 镜像配置(您也可选择阿里云的Maven仓库地址加快拉取速度):1
2
3
4
5
6
7
8
9
10
11
12
13<!-- # (1) 修改官方的Maven仓库地址为本地私服; -->
158 <mirrors>
159 <!-- Maven 私服地址配置 -->
160 <mirror>
161 <id>weiyigeek-maven</id>
162 <mirrorOf>central</mirrorOf>
163 <name>Private maven</name>
164 <url>http://maven.weiyigeek.top:8081/repository/maven-public/</url>
165 </mirror>
166 </mirrors>
<!-- # (2) Default: ${user.home}/.m2/repository 缓存目录 -->
53 <localRepository>/path/to/local/repo</localRepository>
Maven代码项目程序拉取:1
2
3
4
5$ git clone git@gitlab.weiyigeek.top:ci-cd/java-maven.git
# Cloning into 'java-maven'...
# The authenticity of host 'gitlab.weiyigeek.top (10.10.107.201)' can't be established.
$ ~/code/java-maven$ ls
pom.xml src target
构建与运行测试:1
2
3
4
5
6
7
8
9
10
11
12
13
14~/code/java-maven$ mvn clean package -Dmaven.test.skip=true # 跳过测试用例
# [INFO] Building war: /home/weiyigeek/code/java-maven/target/hello-world.war
# [INFO] WEB-INF/web.xml already added, skipping
# [INFO] ------------------------------------------------------------------------
# [INFO] BUILD SUCCESS
# [INFO] ------------------------------------------------------------------------
# [INFO] Total time: 7.225 s
# [INFO] Finished at: 2020-12-25T09:23:20Z
# [INFO] ------------------------------------------------------------------------
~/code/java-maven$ ls -alh /home/weiyigeek/code/java-maven/target/hello-world.war # 生成的war
-rw-r--r-- 1 weiyigeek weiyigeek 2.0M Dec 25 09:23 /home/weiyigeek/code/java-maven/target/hello-world.war
# 将生成的 hello-world.war 复制到本地的 Tomcat 的Wabapps目录之中他会自动解压

WeiyiGeek.Maven-hello-world
- Step 3.在 Kubernets 上 准备接受 Jenkins 推送过来的war包的项目环境;
基础配置: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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47# (1) NFS 服务器上配置 (PS:由于测试资源有限 则 nfs 与 k8s master 在同一台机器上)
root@nfs$ showmount -e
# /nfs/data4 *
/nfs/data4# ls -alh /nfs/
# drwxrwxrwx 2 weiyigeek weiyigeek 4.0K Nov 19 13:27 data4
/nfs/data4# mkdir /nfs/data4/{war,webapps}/
/nfs/data4# ln -s /nfs/data4/war/ROOT /nfs/data4/webapps/ROOT
/nfs/data4# chown -R weiyigeek:weiyigeek /nfs/data4/
# (2) Node 1 && Node 2 都要执行
sudo mkdir -pv /nfs/data4/
sudo chown -R weiyigeek:weiyigeek /nfs/data4/
sudo mount.nfs -r 10.10.107.202:/nfs/data4/ /nfs/data4/
# (3) master 节点拉取 tomcat 此处选择 8.5.61-jdk8-corretto 并上传到内部私有harbor之中
master$ docker pull tomcat:8.5.61-jdk8-corretto
# 8.5.61-jdk8-corretto: Pulling from library/tomcat
# ...
# Status: Downloaded newer image for tomcat:8.5.61-jdk8-corretto
# docker.io/library/tomcat:8.5.61-jdk8-corretto
master$ docker tag tomcat:8.5.61-jdk8-corretto harbor.weiyigeek.top/test/tomcat:8.5.61-jdk8-corretto
master$ docker push harbor.weiyigeek.top/test/tomcat:8.5.61-jdk8-corretto
# The push refers to repository [harbor.weiyigeek.top/test/tomcat]
# f13244e4918b: Pushed
# 536f15f78828: Pushed
# 1c98b6d16fad: Pushed
# fdef502bf282: Pushed
# cee8d35c645b: Pushed
# 8.5.61-jdk8-corretto: digest: sha256:110d7391739e868daf8c1bdd03fcb7ffe9eaf2b134768b9162e2cd47d58f7255 size: 1368
# (4) 节点拉取验证
k8s-node-4:~$ docker pull harbor.weiyigeek.top/test/tomcat:8.5.61-jdk8-corretto
k8s-node-5:~$ docker pull harbor.weiyigeek.top/test/tomcat:8.5.61-jdk8-corretto
# (5) 将 jenkins 中构建好的war包 上传到 Master 节点 的 /nfs/data4/war 目录之中
jenkins$ scp -P 20211 /var/lib/jenkins/workspace/Maven-HelloWorld/target/hello-world.war weiyigeek@10.10.107.202:/nfs/data4/war
# **************WARNING**************
# Authorized only. All activity will be monitored and reported.
# hello-world.war
# (6) 解压war并建立软链接
master$ /nfs/data4/war$ unzip hello-world.war -d hello-world-v1.0
# Archive: hello-world.war
master$ /nfs/data4/war$ ls
# hello-world-v1.0 hello-world.war
master$ /nfs/data4$ ln -s /nfs/data4/war/hello-world-v1.0/ /nfs/data4/webapps && ls /nfs/data4/webapps # 坑太多该目录不能存在
# index.jsp META-INF WEB-INF
资源清单: (同样此处采用了HostPath的Volumns卷(war项目)与StorageClass存储类(访问日志)
)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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65cat > jenkins-ci-gitlab-to-kubernetes.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
name: deploy-maven-svc
spec:
type: NodePort # Service 类型
selector:
app: java-maven # 【注意】与deployment资源控制器创建的Pod标签进行绑定;
release: stabel # Service 服务发现不能缺少Pod标签,有了Pod标签才能与之SVC对应
ports: # 映射端口
- name: http
port: 8080 # cluster 访问端口
targetPort: 8080 # Pod 容器内的服务端口
nodePort: 30089
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: deploy-java-maven
spec:
serviceName: "deploy-maven-svc"
replicas: 3 # 副本数
selector: # 选择器
matchLabels:
app: java-maven # 匹配的Pod标签非常重要
release: stabel
template:
metadata:
labels:
app: java-maven # 模板标签
release: stabel
spec:
volumes: # 关键点
- name: webapps # 卷名称
hostPath: # 采用hostPath卷
type: DirectoryOrCreate # 卷类型DirectoryOrCreate: 如果子节点上没有该目录便会进行创建
path: /nfs/data4/webapps # 各主机节点上已存在的目录此处是NFS共享
- name: timezone # 容器时区设置
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
containers:
- name: java-maven
image: harbor.weiyigeek.top/test/tomcat:8.5.61-jdk8-corretto # 拉取的镜像
imagePullPolicy: IfNotPresent
ports:
- name: http # 此端口在服务中的名称
containerPort: 8080 # 容器暴露的端口
volumeMounts: # 挂载指定卷目录
- name: webapps # Tomcat 应用目录
mountPath: /usr/local/tomcat/webapps/ROOT
- name: logs # Tomcat 日志目录
mountPath: /usr/local/tomcat/logs
- name: timezone # 镜像时区设置
mountPath: /usr/share/zoneinfo/Asia/Shanghai
volumeClaimTemplates: # 卷的体积要求模板此处采用StorageClass存储类主要针对于应用日志的存储;
- metadata: # 根据模板自动创建PV与PVC并且进行一一对应绑定;
name: logs
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: managed-nfs-storage # StorageClass存储类
resources:
requests:
storage: 1Gi
EOF
资源清单构建: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# (1) svc 与 stafefulset 资源创建
~/K8s/Day12$ kubectl apply -f jenkins-ci-gitlab-to-kubernetes.yaml
# service/deploy-maven-svc created
# statefulset.apps/deploy-java-maven created
# (2) 查看创建的资源
~/K8s/Day12$ kubectl get svc | grep "deploy-maven-svc" && kubectl get pod -l app=java-maven -o wide
# deploy-maven-svc NodePort 10.101.97.223 8080:30089/TCP 7m24s
# NAME READY STATUS RESTARTS AGE IP NODE
# deploy-java-maven-0 1/1 Running 0 10s 10.244.0.212 weiyigeek-ubuntu
# deploy-java-maven-1 1/1 Running 0 25s 10.244.1.199 k8s-node-4
# deploy-java-maven-2 1/1 Running 0 29s 10.244.2.102 k8s-node-5
# (3) 访问验证
master$ curl -s http://10.101.97.223:8080 | grep "<p>"
# <p> Server : Apache Tomcat/8.5.61 | 10.244.2.102 </p>
# <p> Client : 10.244.0.0 | 10.244.0.0</p>
# <p> Document_Root : /usr/local/tomcat/webapps/ROOT/ <br/><br/> URL : 10.101.97.223/index.jsp </p>
master$ curl -s http://10.101.97.223:8080 | grep "<p>"
# <p> Server : Apache Tomcat/8.5.61 | 10.244.0.212 </p>
# <p> Client : 10.244.0.1 | 10.244.0.1</p>
# <p> Document_Root : /usr/local/tomcat/webapps/ROOT/ <br/><br/> URL : 10.101.97.223/index.jsp </p>
master$ curl -s http://10.101.97.223:8080 | grep "<p>"
# <p> Server : Apache Tomcat/8.5.61 | 10.244.1.199 </p>
# <p> Client : 10.244.0.0 | 10.244.0.0</p>
# <p> Document_Root : /usr/local/tomcat/webapps/ROOT/ <br/><br/> URL : 10.101.97.223/index.jsp </p>
- Step 4.下面正餐开始了,在 Jenkins 控制台
点击新建任务 -> 输入任务名称(Maven-HelloWorld) -> 选择构建一个Maven项目
常规设置: 丢弃旧的构建 10 个、参数化构建过程 Git 参数 git_version | 选项参数 deploy_option (deploy|rollback|redeploy)
(设置与上面相同 PS 注意排序方式为智能排序)
关键点: Maven Build -> Goals and options : clean package -Dmaven.test.skip=true
构建后脚本设置: Post Steps -> 执行 Shell 命令 -> /bin/bash -x /tmp/script/maven-jenkins-ci-script.sh
-> 应用并保存
构建测试结果: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
31
32
33
34
35
36
37# 项目拉取
Running as SYSTEM
Building in workspace /var/lib/jenkins/workspace/Maven-HelloWorld
The recommended git tool is: NONE
using credential b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f
Cloning the remote Git repository
Cloning repository git@gitlab.weiyigeek.top:ci-cd/java-maven.git
<===[JENKINS REMOTING CAPACITY]===>channel started
Executing Maven: -B -f /var/lib/jenkins/workspace/Maven-HelloWorld/pom.xml clean package -Dmaven.test.skip=true
# 扫描项目并下载依赖
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.weiyigeek.main:hello-world >-------------------
[INFO] Building hello-world Maven Webapp 1.1-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO] Downloading from weiyigeek-maven: http://maven.weiyigeek.top:8081/repository/maven-public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
# 打包应用
[INFO] Packaging webapp
[INFO] Assembling webapp [hello-world] in [/var/lib/jenkins/workspace/Maven-HelloWorld/target/hello-world]
[INFO] Processing war project
[INFO] Copying webapp resources [/var/lib/jenkins/workspace/Maven-HelloWorld/src/main/webapp]
[INFO] Webapp assembled in [26 msecs]
[INFO] Building war: /var/lib/jenkins/workspace/Maven-HelloWorld/target/hello-world.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.756 s
[INFO] Finished at: 2020-12-25T13:55:45Z
[INFO] ------------------------------------------------------------------------
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving /var/lib/jenkins/workspace/Maven-HelloWorld/pom.xml to com.weiyigeek.main/hello-world/1.1-SNAPSHOT/hello-world-1.1-SNAPSHOT.pom
[JENKINS] Archiving /var/lib/jenkins/workspace/Maven-HelloWorld/target/hello-world.war to com.weiyigeek.main/hello-world/1.1-SNAPSHOT/hello-world-1.1-SNAPSHOT.war
channel stopped
Finished: SUCCESS
Step 5.Jenkins CI 部署Shell脚本编写,脚本需求部署、回退、可重复构建;
脚本与权限:su - "jenkins" -c "touch /tmp/script/maven-jenkins-ci-script.sh && chmod a+x /tmp/script/maven-jenkins-ci-script.sh"
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Description: Jenkins CI & Kubernetes & Gitlab -> Deploy or Rollback or Redeploy Java Maven Project
DATE=$(date +%Y%m%d-%H%M%S)
WAR_PATH="/nfs/data4/war"
WEBROOT_PATH="/nfs/data4/webapps"
WEB_DIR="${JOB_NAME}-${DATE}-${git_version}"
WAR_DIR="${WAR_PATH}/${WEB_DIR}"
WAR_NAME="${WEB_DIR}.war"
K8S_MATER="weiyigeek@10.10.107.202"
K8S_MATER_PORT="20211"
# 部署
deploy () {
# 1.上传Maven打包的war包到master之中
scp -P ${K8S_MATER_PORT} ${WORKSPACE}/target/*.war weiyigeek@10.10.107.202:${WAR_PATH}/${WAR_NAME}
# 2.解压&软链接
ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "unzip ${WAR_PATH}/${WAR_NAME} -d ${WAR_DIR} && \
rm -rf ${WEBROOT_PATH} && \
ln -s ${WAR_PATH}/${WEB_DIR} ${WEBROOT_PATH} && \
kubectl delete pod -l app=java-maven"
}
# 回退
rollback () {
History_Version=$(ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "find ${WAR_PATH} -maxdepth 1 -type d -name ${JOB_NAME}-*-${git_version}")
ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "rm -rf ${WEBROOT_PATH} && \
ln -s ${History_Version} ${WEBROOT_PATH} && \
kubectl delete pod -l app=java-maven"
}
# 重部署
redeploy () {
# 如果是以前部署过则删除以前部署的项目目录,否则重新部署;
if [[ "v${GIT_COMMIT}" = "v${GIT_PREVIOUS_SUCCESSFUL_COMMIT}" ]];then
echo -e "曾经部署过 ${git_version} 版本,现在正在重新部署!"
History_Version=$(ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "find ${WAR_PATH} -maxdepth 1 -type d -name ${JOB_NAME}-*-${git_version}")
ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "rm -rf ${History_Version}"
fi
# 物理如何都要重新部署
deploy
}
# 部署 & 回退 入口(坑-==两边没有空格)
if [[ "${deploy_option}" = "deploy" ]]; then
# 坑 (防止字符串为空)
if [[ "v${GIT_COMMIT}" = "v${GIT_PREVIOUS_SUCCESSFUL_COMMIT}" ]];then
echo -e "您已经部署过 ${git_version} 版本"
exit 1
else
deploy
fi
elif [[ "${deploy_option}" = "rollback" ]];then
rollback
elif [[ "${deploy_option}" = "redeploy" ]];then
redeploy
else
echo -e "无任何操作!停止执行脚本"
exit 127
fiStep 6.修改h1标签为我们的项目打几个Tag标签然后Push到仓库;

WeiyiGeek.show tags
- Step 7.验证我们的构建的Maven项目以及推送构建的war到kubernetes集群之中(激动人心的时刻即将到来);
PS: 查看任务控制台输出信息确定脚本部署没有任何问题,之后访问http://10.10.107.202:30089/
查看编译的war运行在kunbernets中部署Tomcat应用的结果;

WeiyiGeek.jenkins-ci-deploy
- Step 8.回滚测试 构建参数:
deploy_option->rollback , git_version -> v1.1
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
31
32
33
34
35# 构建推送反馈
[Maven-HelloWorld] $ /bin/sh -xe /tmp/jenkins6930799554885763742.sh
+ /bin/bash -x /tmp/script/maven-jenkins-ci-script.sh
++ date +%Y%m%d-%H%M%S
+ DATE=20201227-021208
+ WAR_PATH=/nfs/data4/war
+ WEBROOT_PATH=/nfs/data4/webapps
+ WEB_DIR=Maven-HelloWorld-20201227-021208-v1.1
+ WAR_DIR='/nfs/data4/war/Maven-HelloWorld-20201227-021208-v1.1'
+ WAR_NAME=Maven-HelloWorld-20201227-021208-v1.1.war
+ K8S_MATER=weiyigeek@10.10.107.202
+ K8S_MATER_PORT=20211
+ [[ rollback = \d\e\p\l\o\y ]]
+ [[ rollback = \r\o\l\l\b\a\c\k ]] # 进行回滚操作
+ rollback
++ ssh -p 20211 weiyigeek@10.10.107.202 'find /nfs/data4/war -maxdepth 1 -type d -name Maven-HelloWorld-*-v1.1'
**************WARNING**************
Authorized only. All activity will be monitored and reported.
+ History_Version=/nfs/data4/war/Maven-HelloWorld-20201227-020140-v1.1 # 历史版本
+ ssh -p 20211 weiyigeek@10.10.107.202 'rm -rf /nfs/data4/webapps && ln -s /nfs/data4/war/Maven-HelloWorld-20201227-020140-v1.1 /nfs/data4/webapps && kubectl delete pod -l app=java-maven'
**************WARNING**************
Authorized only. All activity will be monitored and reported.
pod "deploy-java-maven-0" deleted
pod "deploy-java-maven-1" deleted
pod "deploy-java-maven-2" deleted
Finished: SUCCESS
# 应用反馈
http://10.10.107.202:30089/
# Maven - Hello World - v1.1
# 访问时间: Sun Dec 27 2020 10:12:18 GMT+0800 (中国标准时间)
# Server : Apache Tomcat/8.5.61 | 10.244.1.203
# Client : 10.244.0.0 | 10.244.0.0
# Document_Root : /usr/local/tomcat/webapps/ROOT/
# URL : 10.10.107.202/index.jsp
- Step 9.重部署测试 构建参数:
deploy_option->redeploy , git_version -> v1.2
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51# (1) 我们先来看看 war 目录的v1.2版本的文件与目录名称
/nfs/data4/war$ ls -alh | grep "-v1.2"
drwxrwxr-x 4 weiyigeek weiyigeek 4.0K Dec 27 10:09 Maven-HelloWorld-20201227-020939-v1.2
-rw-r--r-- 1 weiyigeek weiyigeek 2.0M Dec 27 10:09 Maven-HelloWorld-20201227-020939-v1.2.war
# (2) 项目重部署控制台信息输出
[Maven-HelloWorld] $ /bin/sh -xe /tmp/jenkins8520069315177369772.sh
channel stopped
+ /bin/bash -x /tmp/script/maven-jenkins-ci-script.sh
++ date +%Y%m%d-%H%M%S
+ DATE=20201227-021934
+ WAR_PATH=/nfs/data4/war
+ WEBROOT_PATH=/nfs/data4/webapps
+ WEB_DIR=Maven-HelloWorld-20201227-021934-v1.2
+ WAR_DIR='/nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2'
+ WAR_NAME=Maven-HelloWorld-20201227-021934-v1.2.war
+ K8S_MATER=weiyigeek@10.10.107.202
+ K8S_MATER_PORT=20211
+ [[ redeploy = \d\e\p\l\o\y ]]
+ [[ redeploy = \r\o\l\l\b\a\c\k ]]
+ [[ redeploy = \r\e\d\e\p\l\o\y ]]
+ redeploy # 进入了重部署脚本选择
+ [[ ve8d88cf3e222b79259edcfb7ca48cee7b079ee08 = \v\e\8\d\8\8\c\f\3\e\2\2\2\b\7\9\2\5\9\e\d\c\f\b\7\c\a\4\8\c\e\e\7\b\0\7\9\e\e\0\8 ]]
+ echo -e '曾经部署过 v1.2 版本,现在正在重新部署!'
曾经部署过 v1.2 版本,现在正在重新部署!
++ ssh -p 20211 weiyigeek@10.10.107.202 'find /nfs/data4/war -maxdepth 1 -type d -name Maven-HelloWorld-*-v1.2'
+ History_Version=/nfs/data4/war/Maven-HelloWorld-20201227-020939-v1.2
+ ssh -p 20211 weiyigeek@10.10.107.202 'rm -rf /nfs/data4/war/Maven-HelloWorld-20201227-020939-v1.2' # 删除了原来v1.2版本的war解压目录
# 重新构建
+ deploy
+ scp -P 20211 /var/lib/jenkins/workspace/Maven-HelloWorld/target/hello-world.war weiyigeek@10.10.107.202:/nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2.war
# 解压上传的war 并创建软连接
+ ssh -p 20211 weiyigeek@10.10.107.202 'unzip /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2.war -d /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2 && rm -rf /nfs/data4/webapps && ln -s /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2 /nfs/data4/webapps && kubectl delete pod -l app=java-maven'
Archive: /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2.war
creating: /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2/META-INF/
....
inflating: /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2/META-INF/maven/com.weiyigeek.main/hello-world/pom.properties
pod "deploy-java-maven-0" deleted
pod "deploy-java-maven-1" deleted
pod "deploy-java-maven-2" deleted
Finished: SUCCESS
# (3) 应用反馈
Maven - Hello World - v1.2
访问时间: Sun Dec 27 2020 10:20:03 GMT+0800 (中国标准时间)
Server : Apache Tomcat/8.5.61 | 10.244.2.107
Client : 10.244.0.0 | 10.244.0.0
Document_Root : /usr/local/tomcat/webapps/ROOT/
URL : 10.10.107.202/index.jsp
PS : 至此 Maven 与 Jenkins 集成实践完成
补充介绍: 除了上面在项目的Pom.xml中设置内部Maven服务器,我们可以可以采样下面两种方式指定配置文件
- 方式1.通过 curl 在构建前下载 Git 版本控制的 Maven 自定义的 setting.xml 配置文件(在我后面K8s中构建时会看见)。
- 方式2.采用
Managed file(可以配置 Maven 的全局配置文件和用户配置文件)
和Maven Integration
插件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// Config File Provider 插件使用配置文件
configFileProvider([configFile(fileId:'maven-global-settings',variable:'MAVEN_GLOBAL_ENV')]) {
sh "mvn -s $MAVEN_GLOBAL_ENV clean install"
}
// Pipeline Maven Integration 插件使用配置文件
withMaven(
// Maven installation declared in the Jenkins "Global Tool Configuration"
maven: 'maven-3',
// Maven settings.xml file defined with the Jenkins Config File Provider Plugin
// We recommend to define Maven settings.xml globally at the folder level using
// navigating to the folder configuration in the section "Pipeline Maven Configuration / Override global Maven configuration"
// or globally to the entire master navigating to "Manage Jenkins / Global Tools Configuration"
mavenSettingsConfig: 'my-maven-settings') {
// Run the maven build
sh "mvn clean verify"
} // withMaven will discover the generated Maven artifacts, JUnit Surefire & FailSafe & FindBugs & SpotBugs reports...
SonarQube 集成配置与实践
描述: 在Jenkins持续集成中中可以在构建代码前对我们项目进行一个代码质量扫描检测, 此处我们引入SonarQube进行实现;
操作流程:
Step 0.在 SonarQube Web中进行认证 Token 生成:(手工设置)_添加项目 -> 项目标识 -> 创建一个令牌 (Jenkins) -> 得到Token;
1
2Jenkins: 755eeb453cb28f96aa9d4ea14334da7287c2e840
# 此令牌用于执行分析时认证时使用,如果这个令牌存在问题,可以随时在你的用户账号下取消这个令牌。Step 1.插件安装: 系统管理 -> 插件管理 ->
SonarQube Scanner for Jenkins
()

WeiyiGeek.SonarQube Scanner for Jenkins
- Step 2.在Jenkins系统管理->系统设置以及全局工具管理->上配置SonarQube相关配置(服务端地址,以及客户端工具地址);
1
2
3
4
5# (1) 服务端
Dashboard -> 配置 -> SonarQube servers -> Add SonarQube 设置名称和SonarQube地址 -> 添加Token凭据(类型:Secret Text) -> Jenklins-Connet-Sonarqube-Token
# (2) 客户端
Dashboard -> 全局工具配置 -> SonarQube Scanner -> 名称(sonarqube-scanner) -> 工具路径 (/usr/local/sonar)-> 保存应用

WeiyiGeek.Jenkins上SonarQube配置
Step 3.应用项目分析实战在分析项目中配置
Analysis Properties
->保存和应用-> 此时项目中会多一个SonarQube的图标;
PS : 下述图中有误应该是在Pre Steps阶段(Execute SonarQube Scanner,其次 Build 构建即可)
1
2
3
4
5
6
7
8
9# 构建前进行分析配置(名称、唯一标识、检测目录)
sonar.projectName=${JOB_NAME}
sonar.projectKey=Jenkis
sonar.source=.
# 已配置不需要了
# sonar.host.url=http://sonar.weiyigeek.top:9000 \
# sonar.login=755eeb453cb28f96aa9d4ea14334da7287c2e840WeiyiGeek.SonarQube Analysis Properties
Step 4.新建立一个V1.7Tag并上传到Gitlab之中,之后进行检测与构建操作->返回工程点击SonarQube 图标进行项目检测结果页面;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17WeiyiGeek@WeiyiGeek MINGW64 /e/EclipseProject/hello-world (master)
$ git add .
$ git commit -m "v1.7"
# [master 0f50b10] v1.7
# 1 file changed, 1 insertion(+), 1 deletion(-)
$ git tag -a "v1.7" -m "v1.7"
$ git push
# Enumerating objects: 11, done.
# Counting objects: 100% (11/11), done.
# .....
# To http://gitlab.weiyigeek.top/ci-cd/java-maven.git
# 3bfb942..0f50b10 master -> master
$ git push origin v1.7
# ...
# To http://gitlab.weiyigeek.top/ci-cd/java-maven.git
# * [new tag] v1.7 -> v1.7

WeiyiGeek.SonarQube项目检测结果
- Step 5.项目在K8s集群中部署结果
1
2
3
4
5
6
7# https://10.10.107.202:30089/
Maven - Hello World - v1.7
访问时间: Sun Jan 03 2021 13:20:34 GMT+0800 (中国标准时间)
Server : Apache Tomcat/8.5.61 | 10.244.2.111
Client : 10.244.0.0 | 10.244.0.0
Document_Root : /usr/local/tomcat/webapps/ROOT/
URL : 10.10.107.202/index.jsp
邮箱&钉钉&微信消息通知 集成配置与实践
描述: 在Jenkins中我们还有最重要的一步还没有完成, 即消息通知(让我们知道是构建成功还是、构建失败)等等, 常规的方式有邮箱通知、Shell自定义脚本通知,WebHook通知等;
通知插件插件安装:1
2DingTalk : 钉钉 Jenkins 插件 2.4.3 (https://github.com/jenkinsci/dingtalk-plugin)
Qy Wechat Notification Plugin : 这个插件是一个机器人,可以发布构建状态和发送消息给qy微信. 1.0.2 (https://www.jenkins.io/doc/pipeline/steps/qy-wechat-notification/)
(0) 邮箱通知实践配置
描述: 此处以腾讯企业邮箱为例进行配置,首先需要登陆将要被使用的邮箱,注意必须要使用微信绑定后才能正常生成客户端专用密码
,然后开启SMTP服务;1
2
3
4
5# 客户端设置方法
接收服务器:
imap.exmail.qq.com(使用SSL,端口号993)
发送服务器:
smtp.exmail.qq.com(使用SSL,端口号465)

WeiyiGeek.腾讯企业邮箱
Step 1.在 Dashboard -> 系统配置 -> Jenkins Location
进行配置系统管理员邮件地址,注意此处管理员邮箱地址必须与smtp服务发信地址一致否则将会报出501 mail from address must be same as authorization user
错误;
Step 2.设置发信邮箱相关配置,点击 Dashboard -> 系统配置 -> 邮件通知
填入 SMTP 发信服务器地址以及企业邮箱后缀,采用SSL协议并输入认证的账号与客户端专用密码,最后测试发信;

WeiyiGeek.发信邮箱相关配置
Step 3.构建项目通信发信测试,点击 Dashboard -> Maven-HelloWorld -> 构建设置 -> 启用E-mail Notification
1
2
3
4
5# 收信人:Recipients
# 什么场景发送信息:
- 构建失败给每一个人发送发送电子邮件 : Send e-mail for every unstable build
- 谁构建失败给谁发送邮件: Send separate e-mails to individuals who broke the build
- 为每个失败的模块发送电子邮件 : Send e-mail for each failed module

WeiyiGeek.项目通信发信测试
补充方式:
描述: 由于Jenkins自带的邮件功能比较鸡肋,因此这里推荐安装专门的邮件插件(Email Extension
)并介绍如何配置Jenkins自带的邮件功能作用。
插件安装: 系统管理→管理插件→可选插件选择Email Extension Plugin
插件进行安装
系统设置:
- 1) 通过系统管理→系统设置,进行邮件配置 -> Extended E-mail Notification -> 输入 SMTP Server 相关信息以及Authentication相关设置(
注意:密码一般是邮箱授权码
) - 2) 设置其编码格式以及默认内容类型,以及邮件模板配置在 Extended E-mail的 default content -;
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104<!-- ^\s*(?=\r?$)\n 正则替换空行 -->
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<td>(本邮件由程序自动下发,请勿回复!)</td>
</tr>
<tr>
<td>
<h2><font color="#FF0000">构建结果 - ${BUILD_STATUS}</font></h2>
</td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center" />
</td>
</tr>
<tr><a href="${PROJECT_URL}">${PROJECT_URL}</a>
<td>
<ul>
<li>项目名称:${PROJECT_NAME}</li>
<li>GIT路径:<a href="${GIT_URL}">${GIT_URL}</a></li>
<li>构建编号:${BUILD_NUMBER}</li>
<li>触发原因:${CAUSE}</li>
<li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
</ul>
</td>
</tr>
<tr>
<td>
<b><font color="#0B610B">变更信息:</font></b>
<hr size="2" width="100%" align="center" />
</td>
</tr>
<tr>
<td>
<ul>
<li>上次构建成功后变化 : ${CHANGES_SINCE_LAST_SUCCESS}</a></li>
</ul>
</td>
</tr>
<tr>
<td>
<ul>
<li>上次构建不稳定后变化 : ${CHANGES_SINCE_LAST_UNSTABLE}</a></li>
</ul>
</td>
</tr>
<tr>
<td>
<ul>
<li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
</ul>
</td>
</tr>
<tr>
<td>
<ul>
<li>变更集:${JELLY_SCRIPT,template="html"}</a></li>
</ul>
</td>
</tr>
<!--
<tr>
<td>
<b><font color="#0B610B">Failed Test Results</font></b>
<hr size="2" width="100%" align="center" />
</td>
</tr>
<tr>
<td>
<pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
<br />
</td>
</tr>
<tr>
<td>
<b><font color="#0B610B">构建日志 (最后 100行):</font></b>
<hr size="2" width="100%" align="center" />
</td>
</tr>-->
<!-- <tr>
<td>Test Logs (if test has ran): <a
href="${PROJECT_URL}ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip">${PROJECT_URL}/ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip</a>
<br />
<br />
</td>
</tr> -->
<!--
<tr>
<td>
<textarea cols="80" rows="30" readonly="readonly" style="font-family: Courier New">${BUILD_LOG, maxLines=100,escapeHtml=true}</textarea>
</td>
</tr>-->
<hr size="2" width="100%" align="center" />
</table>
</body>
</html> - 3) 设置
Default Triggers
触发机制,例如下面是失败时候和成功时候发送;

WeiyiGeek.设置
- 4) 在Job任务调用中选择构建后操作进行设置
Email Notification
进行设置通知

WeiyiGeek.Email-Notification
(1) 钉钉消息通知实践配置 WeiyiGeek.钉钉群聊机器人添加
Step 0.在钉钉中建立一个群聊并且创建一个群机器人生成一个Webhook地址,操作如下图所示:1
例如:https://oapi.dingtalk.com/robot/send?access_token=95f707645db08794166ed3aad3eaad363bb1475bf7c91635b7456a0a8c8893c6
Step 1.设置钉钉消息通知参数, 点击 Dashboard -> 系统配置 -> 钉钉
选择通知时机以及代理通信(当该主机无法正常连接网络时可采用此方法
) -> 点击新增(填入唯一的id、以及名称和webhook地址,注意如果在创建机器人时指定了关键字和加密字符串需要填写上
)->然后测试发信;

WeiyiGeek.钉钉消息通知参数
Step 2.在FreeStyle风格的项目是可以在通用设置卡点选钉钉消息通知的,而Maven的项目是没有该点选选项,因为该插件只支持FreeStyle和PIPELINE流水线
(这里有巨坑所以有的时候还是老版本的插件好用),注意网上博客中关于大多数此问题都是不适用的官方文档才是第一手;

WeiyiGeek.FreeStyle风格构建的钉钉通知
PS : 对于其它项目风格的项目在后面我们将使用流水线PIPEline进行实现钉钉的消息通知;
(2) 企业微信通知实践配置
- Step 1.设置企业微信通知全局参数,点击
Dashboard -> 系统配置 -> 企业微信通知配置
设置构建环境名称(会在信息中显示)以及默认Webhook地址(全局的)、通知用户的Uid(@ALL表示全部)

WeiyiGeek.企业微信全局参数
Step 2.在构建任务中设置相应的通知参数,点击
Dashboard -> Maven-HelloWorld(项目名称) -> 构建后的操作 -> 选择企业微信
1
2
3
4
5
6
7
8
9
10
11# PS:此处输入的Webhook优先级高于全局的企业微信Webhook这样做的好处是便于为每个任务分配不同的Webhook;
Webhook地址: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c222f3fc-f645-440a-ad24-0ce8d9626f11
情况通知:
仅失败才@
发送开始构建信息
仅失败才发送
仅成功才发送
仅构建中断才发送
仅不稳定构建才发送
通知UserID: @ALL
通知手机号码: 选填Step 3.对
Maven-HelloWorld
项目进行构建并查看控制台输出,消息推送;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 构建前发送
> git config core.sparsecheckout # timeout=10
> git checkout -f e8d88cf3e222b79259edcfb7ca48cee7b079ee08 # timeout=10
Commit message: "v1.2"
> git rev-list --no-walk e8d88cf3e222b79259edcfb7ca48cee7b079ee08 # timeout=10
推送通知 {"markdown":{"content":"Jenkins-Notify<font color=\"info\">【Maven-HelloWorld】<\/font>开始构建\n >构建参数:<font color=\"comment\">git_version=v1.2, deploy_option=rollback <\/font>\n >预计用时:<font color=\"comment\">0分钟<\/font>\n >[查看控制台](http://jenkins.weiyigeek.top:8080/job/Maven-HelloWorld/16/console)"},"msgtype":"markdown"}
通知结果 {"errcode":0,"errmsg":"ok"}
# 构建部署后发送
+ ssh -p 20211 weiyigeek@10.10.107.202 'rm -rf /nfs/data4/webapps && ln -s /nfs/data4/war/Maven-HelloWorld-20201227-021934-v1.2 /nfs/data4/webapps && kubectl delete pod -l app=java-maven'
**************WARNING**************
Authorized only. All activity will be monitored and reported.
pod "deploy-java-maven-0" deleted
pod "deploy-java-maven-1" deleted
pod "deploy-java-maven-2" deleted
推送通知{"markdown":{"content":"Jenkins-Notify<font color=\"info\">【Maven-HelloWorld】<\/font>构建<font color=\"info\">成功~<\/font>👌\n >构建用时:<font color=\"comment\">28 sec<\/font>\n >[查看控制台](http://jenkins.weiyigeek.top:8080/job/Maven-HelloWorld/16/console)"},"msgtype":"markdown"}
通知结果{"errcode":0,"errmsg":"ok"}
项目运行结果[SUCCESS]
Finished: SUCCESS

WeiyiGeek.企业微信通知实现效果
0x05 补充说明
(1) 内置环境变量
PS : Jenkins 默认的环境变量列表 http://jenkins.weiyigeek.top:8080/env-vars.html/
1 | BUILD_NUMBER |
测试环境变量: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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
echo BUILD_NUMBER: ${BUILD_NUMBER }
echo BUILD_ID: ${BUILD_ID}
echo BUILD_DISPLAY_NAME: $BUILD_DISPLAY_NAME:
echo JOB_NAME: $JOB_NAME
echo JOB_BASE_NAME: $JOB_BASE_NAME
echo BUILD_TAG: $BUILD_TAG
echo EXECUTOR_NUMBER: $EXECUTOR_NUMBER
echo NODE_NAME: $NODE_NAME
echo NODE_LABELS: $NODE_LABELS
echo WORKSPACE: $WORKSPACE
echo WORKSPACE_TMP: $WORKSPACE_TMP
echo JENKINS_HOME: $JENKINS_HOME
echo JENKINS_URL: $JENKINS_URL
echo BUILD_URL: $BUILD_URL
echo JOB_URL: $JOB_URL
echo GIT_COMMIT: $GIT_COMMIT
echo GIT_PREVIOUS_COMMIT: $GIT_PREVIOUS_COMMIT
echo GIT_PREVIOUS_SUCCESSFUL_COMMIT: $GIT_PREVIOUS_SUCCESSFUL_COMMIT
echo GIT_BRANCH: $GIT_BRANCH
echo GIT_LOCAL_BRANCH: $GIT_LOCAL_BRANCH
echo GIT_CHECKOUT_DIR: $GIT_CHECKOUT_DIR
echo GIT_URL: $GIT_URL
echo GIT_COMMITTER_NAME: $GIT_COMMITTER_NAME
echo GIT_AUTHOR_NAME: $GIT_AUTHOR_NAME
echo GIT_COMMITTER_EMAIL: $GIT_COMMITTER_EMAIL
echo GIT_AUTHOR_EMAIL: $GIT_AUTHOR_EMAIL
测试结果: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+ /bin/bash /tmp/script/env.sh
BUILD_NUMBER: 22
BUILD_ID: 22
BUILD_DISPLAY_NAME: #22:
JOB_NAME: Maven-HelloWorld
JOB_BASE_NAME: Maven-HelloWorld
BUILD_TAG: jenkins-Maven-HelloWorld-22
EXECUTOR_NUMBER: 0
NODE_NAME: master
NODE_LABELS: master
WORKSPACE: /var/lib/jenkins/workspace/Maven-HelloWorld
WORKSPACE_TMP: /var/lib/jenkins/workspace/Maven-HelloWorld@tmp
JENKINS_HOME: /var/lib/jenkins
JENKINS_URL: http://jenkins.weiyigeek.top:8080/
BUILD_URL: http://jenkins.weiyigeek.top:8080/job/Maven-HelloWorld/22/
JOB_URL: http://jenkins.weiyigeek.top:8080/job/Maven-HelloWorld/
GIT_COMMIT: 0f50b10b09c160a86972178d94ca1f0a704dd767
GIT_PREVIOUS_COMMIT: 0f50b10b09c160a86972178d94ca1f0a704dd767
GIT_PREVIOUS_SUCCESSFUL_COMMIT: 0f50b10b09c160a86972178d94ca1f0a704dd767
GIT_BRANCH: v1.7
GIT_URL: git@gitlab.weiyigeek.top:ci-cd/java-maven.git
GIT_AUTHOR_NAME:
GIT_AUTHOR_EMAIL:
GIT_COMMITTER_NAME:
GIT_COMMITTER_EMAIL:
GIT_LOCAL_BRANCH:
GIT_CHECKOUT_DIR:
Finished: SUCCESS
(2) Jenkins 管理员密码忘记重置
1.找到用户的路径1
2
3
4
5
6
7
8
9
10
11
12[root@jenkins-node1 ~]# cd /var/lib/jenkins/users/
[root@jenkins-node1 users]# tree
.
├── 552408925_8628634723176281851
│ └── config.xml
├── admin_8092868597319509744
│ └── config.xml
├── jenkins_3327043579358903316 #我使用的jenkins作为管理员(如果你是admin就进admin目录)
│ └── config.xml #修改config.xml
└── users.xml
3 directories, 4 files
2.修改jenkins用户目录下的config.xml,定位到<passwordHash>
那行删除,改为如下内容-1
2[root@jenkins-node1 users]# vim config.xml
<passwordHash>#jbcrypt:$2a$10$slYx6.2Xyss6w9LnuiwnNOReuvkcSkaI.Y.Z2AC6Sp7hdF7hhxlsK</passwordHash>
3.新密码为bgx.com 记得重启jenkins生效
(3) Jenkins 升级迁移
描述: 在使用 Jenkins 时候显示新版本的 Jenkins (2.272) 可以下载 (变更记录),正好可以实践一哈Jenkins的升级&迁移。
PS : 如果是是在生产环境中升级建议慎重,可能会导致插件和升级版本不兼容的情况;
操作流程: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
31
32
33
34# (1) 下载更新包
wget https://updates.jenkins.io/download/war/2.272/jenkins.war
# (2) 停止 Jenkins 服务
jenkins:/usr/share/jenkins# systemctl stop jenkins && ls
# jenkins.war
# (3) 备份上一个版本
jenkins:/usr/share/jenkins# mv jenkins.war jenkins.war.2.263.1.bak
jenkins:/usr/share/jenkins# cp /home/weiyigeek/jenkins.war jenkins.war
jenkins:/usr/share/jenkins# ls -alh
# -rw-r--r-- 1 root root 67M Dec 24 02:38 jenkins.war
# -rw-r--r-- 1 root root 65M Dec 2 13:56 jenkins.war.2.263.1.bak
# (4) 启动 Jenkins 服务
jenkins:/usr/share/jenkins# systemctl start jenkins
jenkins:/usr/share/jenkins# systemctl status jenkins
# ● jenkins.service - LSB: Start Jenkins at boot time
# Loaded: loaded (/etc/init.d/jenkins; generated)
# Active: active (exited) since Thu 2020-12-24 02:38:50 UTC; 4s ago
# Docs: man:systemd-sysv-generator(8)
# Process: 448375 ExecStart=/etc/init.d/jenkins start (code=exited, status=0/SUCCESS)
# Dec 24 02:38:48 gitlab systemd[1]: Starting LSB: Start Jenkins at boot time...
# Dec 24 02:38:48 gitlab jenkins[448375]: Correct java version found
# Dec 24 02:38:48 gitlab jenkins[448375]: * Starting Jenkins Automation Server jenkins
# Dec 24 02:38:48 gitlab su[448432]: (to jenkins) root on none
# Dec 24 02:38:48 gitlab su[448432]: pam_unix(su-l:session): session opened for user jenkins by (uid=0)
# Dec 24 02:38:49 gitlab su[448432]: pam_unix(su-l:session): session closed for user jenkins
# Dec 24 02:38:50 gitlab jenkins[448375]: ...done.
# Dec 24 02:38:50 gitlab systemd[1]: Started LSB: Start Jenkins at boot time.
# (5) 访问 Jenkins UI 界面验证升级版本
http://jenkins.weiyigeek.top:8080/about/

WeiyiGeek.Jenkins UI
0x06 入坑&出坑
问题1.jenkins depends on daemon; however Package daemon is not installed.
问题描述: 在Ubuntu 采用 dpkg 安装 jenkins_2.263.1_all.deb 时报错提示 daemon 包未安装
问题复原:1
2
3
4
5
6
7
8
9
10
11
12
13
14$ sudo dpkg -i jenkins_2.263.1_all.deb
Selecting previously unselected package jenkins.
(Reading database ... 115038 files and directories currently installed.)
Preparing to unpack jenkins_2.263.1_all.deb ...
Unpacking jenkins (2.263.1) ...
dpkg: dependency problems prevent configuration of jenkins:
jenkins depends on daemon; however:
Package daemon is not installed.
dpkg: error processing package jenkins (--install):
dependency problems - leaving unconfigured
Processing triggers for systemd (245.4-4ubuntu3.2) ...
Errors were encountered while processing:
jenkins
解决办法:1
sudo apt install -y daemon
问题2:Jenkins 启动时显示 ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin
问题复原:1
2
3
4
5
6
7$ systemctl status jenkins
Dec 23 14:02:57 gitlab systemd[1]: Starting LSB: Start Jenkins at boot time...
Dec 23 14:02:57 gitlab jenkins[356298]: ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin
Dec 23 14:02:57 gitlab jenkins[356298]: If you actually have java installed on the system make sure the executable is in the aforementioned path and that 'type -p ja>
Dec 23 14:02:57 gitlab systemd[1]: jenkins.service: Control process exited, code=exited, status=1/FAILURE
Dec 23 14:02:57 gitlab systemd[1]: jenkins.service: Failed with result 'exit-code'.
Dec 23 14:02:57 gitlab systemd[1]: Failed to start LSB: Start Jenkins at boot time.
问题原因: 未找寻到有效的Java执行环境;
解决流程:1
2
3
4
5
6
7
8①.先执行echo $PATH 看看环境变量运行结果如下:
/usr/maven/maven/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/java/jdk1.8/bin
如果连这都没有的话重新安装Java。
②.建立软连接:ln -s /usr/java/jdk1.8/bin/java /usr/bin/java(换成你自己的路径)
Please wait while Jenkins is getting ready to work (jenkins)
如果界面提示Jenkins正在启动,请稍后…或者提示
Please wait while Jenkins is getting ready to work…
问题3.安装Jenkins后或者安装插件时候一直在加载;
问题描述: 由于Jenkins官方插件下载地址没被墙但是网速很慢,下载时间也长;
解决方法:换清华的镜像进去之后下载插件即可 (http://updates.jenkins-ci.org/download/)
操作流程: 需要你进入jenkins的工作目录1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 打开 hudson.model.UpdateCenter.xml 把 http://updates.jenkins-ci.org/update-center.json 改成 http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
sed -i "s#updates.jenkins.io#mirrors.tuna.tsinghua.edu.cn/jenkins/updates#g" /var/lib/jenkins/hudson.model.UpdateCenter.xml
# 上面的命令就是将将安装目录下的 hudson.model.UpdateCenter.xml 中改成
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
<url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url>
</site>
</sites>
# (2) 将updates文件夹下的default.json 中所有 http://updates.jenkins-ci.org/download/替换为 https://mirrors.tuna.tsinghua.edu.cn/jenkins/ PS: 也可以在后台进行设置
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
# (3) 修改完成后重启 Jenkins 即可

WeiyiGeek.Jenkins Please wait
问题4: 未正确配置Jenkins基础URL等相关信息;
问题描述: Jenkins的根URL是空的,但是需要Jenkins的许多特性的正确操作,如电子邮件通知、PR状态更新和环境变量,如BUILD_URL。
请提供Jenkins配置中的准确值。1
2
3Jenkins root URL is empty but is required for the proper operation of many Jenkins features like email notifications, PR status update, and environment variables such as BUILD_URL.
Please provide an accurate value in Jenkins configuration.
解决办法: Dashboard -> 配置 -> Jenkins Location -> Jenkins 地址 & 邮箱
问题5.无法连接仓库:Command “git ls-remote -h – git@gitlab.weiyigeek.top:ci-cd/blog.git HEAD” returned status code 128:
问题复原:1
2
3
4stdout:
stderr: Host key verification failed.
fatal: Could not read from remote repository.
# Please make sure you have the correct access rights and the repository exists.
问题原因: 由于采用SSH协议进行代码的拉取和信息的查看,在利用公密钥首次链接时候未绑定其机器的公钥信息, 将会导致 Host key verification failed.
解决办法: 在连接的机器上先执行git -T git@gitlab.weiyigeek.top
保存其主机的公钥信息;1
2
3
4
5
6
7
8
9# 例如 首次连接Gitlab时候需要进行主机于公钥绑定
ssh -T git@gitlab.com
# 无法建立主机“gitlab.com(172.65.251.78)”的真实性。
The authenticity of host 'gitlab.com (172.65.251.78)' can\'t be established.
ECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
$ cat ~/.ssh/known_hosts
gitlab.com,172.65.251.78 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAABFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QOLXBpQ6KWjbjTDTdDkoohFzgbEYI=
问题6.Jenkins 内置邮件通知发信测试 Failed to send out e-mail javax.mail.AuthenticationFailedException: 535 Error:
错误信息:1
2
3
4
5
6
7Failed to send out e-mail
javax.mail.AuthenticationFailedException: 535 Error: ÇëʹÓÃÊÚȨÂëµÇ¼¡£ÏêÇéÇë¿´: http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256
at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:947)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:858)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:762)
at javax.mail.Service.connect(Service.java:364)
错误原因: 配置STMP的邮箱账号,输入的认证字符串是邮箱密码而并非生成的客户端密码, 在 腾讯企业邮箱、163邮箱都需要使用生成的客户端密码进行登录;
问题7.Jenkins 内置邮件通知发信测试 com.sun.mail.smtp.SMTPSenderFailedException: 501 mail from address must be same as authorization user
错误信息:1
2
3
4
5
6
7
8
9
10
11Failed to send out e-mail
com.sun.mail.smtp.SMTPSenderFailedException: 501 mail from address must be same as authorization user
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1817)
Caused: com.sun.mail.smtp.SMTPSendFailedException: 501 mail from address must be same as authorization user
;
nested exception is:
com.sun.mail.smtp.SMTPSenderFailedException: 501 mail from address must be same as authorization user
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2374)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1808)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1285)
at javax.mail.Transport.send0(Transport.java:231)
错误原因: 最后发现是jenkins url下面的系统管理员邮件地址没有填写或者与STMP发信邮箱不一致
解决办法: 填写系统管理员邮箱与STMP发信邮箱地址一致就可以了。
问题8.Jenkins 内置邮件通知发信测试com.sun.mail.smtp.SMTPAddressFailedException: 501 Bad address syntax
错误信息:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21ERROR: Invalid Addresses
javax.mail.SendFailedException: Invalid Addresses;
nested exception is:
com.sun.mail.smtp.SMTPAddressFailedException: 501 Bad address syntax
at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:2064)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1286)
at javax.mail.Transport.send0(Transport.java:231)
at javax.mail.Transport.send(Transport.java:100)
at hudson.tasks.MailSender.run(MailSender.java:130)
at hudson.tasks.MailSender.execute(MailSender.java:105)
at hudson.maven.MavenModuleSetBuild$MavenModuleSetBuildExecution.cleanUp(MavenModuleSetBuild.java:1093)
at hudson.model.Run.execute(Run.java:1954)
at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:543)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
Caused by: com.sun.mail.smtp.SMTPAddressFailedException: 501 Bad address syntax
at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1917)
... 10 more
Finished: FAILURE
`
错误原因: 输入的接收邮箱地址是无效的格式;