文章目录
前言
阅读本文前请注意最后编辑时间,文章内容可能与目前最新的技术发展情况相去甚远。欢迎各位评论与私信,指出错误或是进行交流等。
背景
传统的软件开发在系统上线的时候需要手动进行,这个过程可能相对繁琐和容易出错,发布过程如下:
- 代码构建:开发人员在本地环境中编写代码,并手动进行代码编译、打包等操作,生成可执行的软件包或者部署文件,比如jar包或者war包。
- 手动集成和测试:开发人员需要手动将代码变更集成到主干代码库中,并在集成后手动运行测试来确保代码的质量和稳定性。
- 手动部署:一旦代码通过了测试,开发人员可能需要手动将软件部署到目标环境中,比如测试环境、预发布环境或者生产环境。
- 手动备份:发布前,开发人员需要手动备份历史版本,如果出现问题,可能需要回滚到之前的稳定版本。
这种手动的发布过程存在以下问题:
- 容易出错:人为操作容易出现错误,比如遗漏某个步骤或者配置错误,导致发布失败或者软件出现问题。
- 耗时耗力:手动操作需要花费大量的时间和人力资源,尤其是在大型项目或者频繁发布的情况下。
- 不可追溯:手动操作缺乏可追溯性,难以记录和回顾发布过程中的细节和问题,影响后续的改进和优化。
随着持续集成和持续交付的理念的兴起,Jenkins (GitLab CI/CD 、 GitHub Actions)等持续集成工具的出现填补了这一空白,帮助团队实现了自动化的集成、构建、测试和部署,提高了发布的效率和质量。
CI/CD
CI/CD 是持续集成(Continuous Integration,CI)、持续交付(Continuous Delivery,CD)与 持续部署(Continuous Deployment,CD)的简称,注意CD对应了两个名词。
CI/CD是实现敏捷开发和Devops理念的一种方法,具体而言,CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试,到交付和部署)。这些关联的事务通常被统称为CI/CD 管道(Pipeline),由开发(RD)、测试(QA)、运维(OP)团队以敏捷方式协同支持。
- 持续集成(Continuous integration):每次代码变更后,自动构建和测试。
- 持续交付(Continuous delivery):在 CI 的基础上,自动化部署到预生产环境,确保代码随时可发布。
- 持续部署(Continuous deployment):在 CD 的基础上,进一步自动化部署到生产环境,实现无缝发布。
Jenkins简介
Jenkins是一个基于Java开发的开源软件项目。提供一个开放易用的软件平台,使软件项目可以自动化地进行构建、测试和部署。
官方文档(很详细):https://www.jenkins.io/zh/
Jenkins特性
- 易安装。有多种安装方式,可以在线安装,也可以下载安装包安装,也可以运行war包。
- 集成了Email等工具,可以在集成或部署时通知工作人员。
- 可扩展性:Jenkins具有丰富的插件生态系统,提供了各种各样的插件,涵盖了几乎所有领域,包括版本控制、构建工具、部署工具、通知等。这使得Jenkins能够满足不同团队的需求,并支持各种不同的工作流程。
- 易用性:Jenkins提供了直观的用户界面,使得用户可以轻松地设置和管理各种构建任务和工作流程。它还支持基于Web的配置,使得用户可以通过浏览器轻松地访问和管理Jenkins实例。
- 分布式构建:Jenkins支持在多台计算机上执行构建任务,这样可以更快地完成大型项目的构建过程。它还支持在不同操作系统和环境中运行构建任务。
- 日志和报告:Jenkins会生成详细的构建日志和报告,包括每个构建的输出、测试结果、代码覆盖率等信息,帮助团队跟踪和分析构建过程中的问题。
安装
注意:本文在linux系统上,以Java项目为例,会用到 jdk、maven、git、docker等工具。其他开发语言项目仅作参考
从 Jenkins 的入门指南 中可以了解到
可以 通过java -version
命令来检查是否已经安装了 Java,如果有打印出 Java 的版本信息则表示已经安装过了。
如何在 Linux 上安装 Java,具体步骤可参考博客:https://blog.csdn.net/xhmico/article/details/123083940(或者自行查阅其他资料)
准备介绍 Jenkins 在 Linux 上构建 Java 项目,可先安装一下 maven,可参考博客:https://blog.csdn.net/xhmico/article/details/136450882
(或者自行查阅其他资料)
进入 Jenkins 的 官方下载页面
LTS 是长期支持的版本,是稳定的版本
在下载安装包之前要先确定应该下载哪个版本的 Jenkins,Jenkins 的版本依赖于 Java 的版本,可在 Jenkins-Java Support Policy 中进行查看
如果你下载的 Jenkins 版本与本地 Java 不支持,那么 Jenkins 是无法安装成功的,比如服务器上 JDK 的版本是 1.8.0_311,也就是 Java 8,那么只能安装 2.346.1 或者该版本之前的,在 Past Releases 上可以查看到历史版本
页面如下 :
下载合适版本的 jenkins.war 文件


下载完成之后就把该 war 包上传至服务器
上传成功之后就可以直接用 java -jar 命令启动起来,可以通过 httpPort 来指定端口号
cpp
java -jar jenkins.war --httpPort=8080

首次启动会比较慢,因为需要初始化和存放一些文件到 .jenkins 的目录下

在启动过程中会打印出 管理员账户密码
这个时候就可以去游览器上访问下 ip:port,ip 是服务器的 ip 地址,port 是启动 jenkins 的端口,比如:192.163.10.12:8080 ,如果你用的是 云服务器,可别忘了在云服务器上开放该端口号
在浏览器上展示页面如下,就可以进行初始化了
将 管理员账户密码 复制到对应的地方,点击 继续

这里建议点击 选择插件来安装,在点击 无 ,不安装任何插件,再点击 安装,因为我们没有配置镜像,安装插件是从外网下载
过来的,会比较慢,并且下载的插件可能会出现不兼容等状况,导致失败率很高。

进入到创建管理员页面,填写账户信息后 保存并完成
进入以下页面配置 jenkins 的 url ,一般使用默认的就行了,保存并完成

初始化完成
可以点击 开始使用 Jenkins 直接登录进入 Jenkins
Jenkins工作流程(仅供参考)

程序员在先把代码利用git提交到版本仓库(其中分支合并一般是由leader进行手动集成操作),然后通过Jenkins将Java项目通过maven去构建(生成jar包),随后部署到服务器上,测试人员可通过浏览器访问该项目进行手工测试(或者在服务器上运行脚本来测试)。

在部署之前进行同样的操作,但可以使用docker将jar包和环境build成一个镜像(或者使用挂载jar包的方式)运行容器进行部署,方便开发环境、预生产环境、测试环境的统一。假如服务器上有多个项目在运行,使用docker也能安全的将他们隔离开来。(关于docker的安装与使用可参考另外一篇博客)
安装maven和其他插件
已有一个示例项目放在了代码仓库中
如果要让Jenkins通过maven进行构建项目,需要在Jenkins中安装插件。点击Manage Jenkins->Manage Plugins
输入 Maven Integration,勾选并点击下方的 Install without restart按钮。同理,还需安装 publish over ssh 插件。(后续会用到)
此外,那么同学们还可以再安装一个中文插件:如下图,输入chinese就可以看到。
新建任务
装好插件后,返回首页。开始新建第一个任务(Job)
新建一个任务,任务名称自行决定。点击下方的构建一个maven项目(如果不是Java项目,或者不使用maven可选择freestyle project)
随后进入项目配置页面,Jenkins为项目提供了大量的配置选项,并且这些配置选项还可以通过插件进一步扩展。
General:对项目进行介绍,填写介绍信息。
任务源码管理

在任务配置中的源码管理这一部分,项目是使用git进行管理的,所以选择git,随后在第一行填入要拉取的仓库地址。Credentials是git凭证,如果项目是私有的,Jenkins使用git拉取项目需要进行身份验证,需要点击添加按钮,添加用户名和密码来进行身份验证。或者通过SSH密钥的方式进行验证。关于SSH密钥的生成方式请自行查阅资料,可参考文章:https://blog.csdn.net/lzc2644481789/article/details/124888223

这里填写要拉取仓库中的哪一个分支
配置maven
将任务拉到Buid这一部分,看到有提示。意思是指 Jenkins不知道maven安装在哪,我们系统中是安装了maven。并在Jenkins中安装了maven的插件,但插件是帮我们调用maven的,还得先配置一下maven的路径才能使用。点击the tool configuration,或者回到首页->Manage Jenkins->Global Tool Configuration
NAME这一行自行起个名字,MAVEN_HOME中填写maven的安装路径。点击保存
maven配置完毕后,回到任务配置项Build中,第一行的Root POM是根据git项目的根目录进行查找的,需要根据项目文件结构进行修改。
如图,项目文件结构为demo文件夹和README,pom.xml文件在demo文件夹中。
配置git(非必需)
参考前面的maven 配置,如果发现Jenkins无法调用git,也需要让我们进行Global Tool Configuration设置,那么可按照下图进行设置。
尝试手动构建jar包

回到首页面板,点击任务的build(绿色箭头)按钮,手动的对该任务进行执行构建任务。

我们可以看到该任务正在构建中,点击该任务名称,可以查看详细信息。
点击控制台输出,可以查看在构建过程中的详细信息。
上图只截取了一部分,总结一下所有的信息是,Jenkins先调用了git拉取了项目代码到 /root/.jenkins/workspace/first/demo-1。
随后调用maven对pom.xml进行解析,下载了依赖包后进行构建。构建了一系列文件,其中
jar包存放在 /root/.jenkins/workspace/first/demo-1/target/demo-1-0.0.1-SNAPSHOT.jar
cpp
# 在Jenkins服务器上
# 测试构建的jar包能否运行
# Jenkins占用了8080端口 所以换一个端口
java -jar demo-1-0.0.1-SNAPSHOT.jar --server.port=8088
可能遇到的错误

cpp
yum install -y java-devel

使用maven构建时,maven如果没有配置镜像源的话,会从官方处拉取,网络速度慢最终导致构建失败。请各位自行搜索maven配置国内镜像源文章。
发布到远程服务器
假如需要将该应用运行在远程的服务器上,那么就需要将构建完成的jar包发送过去,并执行运行jar包的命令。远程服务器上只需要额外安装java环境即可,用于运行jar包。
发送jar包和命令需要使用 publish over ssh 插件进行运作。
回到任务的配置页面,Post Steps部分,选择 Send files or execute commands over SSH。(通过SSH发送文件和执行命令,发生在构建完成后)

在选完之后,就需要让我们对远程服务器进行配置。
回到首页,Manage Jenkins-> Configure System -> Publish over SSH
点击高级,输入用户密码或者设置SSH密钥、配置端口等信息。点击Test Configuration 测试能否连接到远程服务器

随后回到任务配置页面,选择配置好的服务器。
填写,要传输的源文件路径。传输到远程服务器的具体位置,并去掉了路径前缀,并执行 nohub java -jar /root/xxoo/demo*.jar >mylog.log 2>&1
命令。
点击保存,回到首页进行构建,Jenkins会进行 拉取git代码 利用maven构建 将jar传输到远程服务器上 通过命令运行jar包 的操作。
前置清理工作
如果后续再进行构建的时候,远程服务器上已经有一个jar包在运行了,那么将新构建的jar包传输过去,则无法运行起来。
因此,我们需要做一些前置清理工作。

回到任务配置页面,在Pre Steps部分选择 Send files or execute commands over SSH,在构建之前发送文件或执行命令。

由于前置清理工作的命令较多,因此将这些命令全部都写在 远程服务器上的 x.sh 脚本中 并传入参数 demo,该脚本如下
cpp
#!/bin/bash
# 删除历史文件
rm -rf xxoo
# 获取传入参数 jar包的名字
# echo "arg:$1"
# 获取正在运行jar包的pid
pid=`ps -ef | grep $1 | grep 'java -jar' | awk '{printf $2}'`
# 如果pid为空 则提示 否则 杀死进程
if [ -z $pid ];
then
echo "$appname not start"
else
kill -9 $pid
echo "$appname stopping"
# 检查一下 是否真的杀死了进程
check=`ps -ef | grep -w $pid | grep java`
if [ -z $check];
then
echo "$appname stop"
else
echo "$appname stop fail"
fi
构建触发器
前面介绍的jar包的构建都是手动点击的,并不符合自动构建的想法。因此,需要设置触发器来进行自动构建。
git钩子
回到任务配置页面,Jenkins提供了多种触发器,这里主要介绍两种方式。
勾选触发远程构建,在设置了一个身份验证令牌后,远程调用URL则可触发该项目构建。
URL:http://192.168.44.101:8080/job/first/build?token=123123
http://192.168.44.101:8080 这是Jenkins服务的URL
first是任务名
token是设置的身份验证令牌
随后我们安装插件 Build Authorization Token Root
在git仓库中设置Webhooks勾子
填入该URL,然后选择合适的事件。例如合并请求事件
,这样在git仓库中合并分支后会调用勾子 访问填入的URL,该URL会触发Jenkins的构建动作,拉取git仓库的变化并进行构建。
定时触发器
勾选Poll SCM,填入参数,参数仿照Jenkins提供的corn表达式书写即可。设置完成之后,Jenkins会按照参数设定,定时的去检查git仓库中的分支是否有更新,如果发现有更新则会进行构建任务。
容器部署方式
前文我们是将项目(jar包)放到服务器上,并在服务器上安装了对应的构建环境或者运行环境来部署的。接下来介绍容器部署的方式
挂载jar包目录方式
准备了一台linux服务器,已经安装好了docker并拉取了官方jdk的镜像。
Jenkins中其他配置不变,仍然是从git拉取代码,并构建。但在构建之前,我们需要将服务器上的旧文件删除,并且停止已经在运行的容器。
cpp
# 在任务配置的Pre Steps中填写命令
rm -rf *
docker stop demo
随后进行构建,构建完成后将文件传输到服务器上,然后启动容器。
cpp
# 在任务配置的Post Steps中运行shell 脚本
# shell脚本可以放在项目里面一起传输过去,或者提前放在服务器上。
# shell脚本内容如下(仅供参考)
# if [[ "$(docker inspect [容器名] 2> /dev/null | grep '"Name": "/[容器名]"')" != "" ]];
if [[ "$(docker inspect [demo] 2> /dev/null | grep '"Name": "/[demo]"')" != "" ]];
then
# 如果容器存在则启动
docker start demo
else
docker run -d -p 8080:8080 --name demo -v /root/jarfile/demo-1-0.0.1-SNAPSHOT.jar:/demo.jar openjdk:11 java -jar demo.jar
# 如果容器不存在 生成名为demo的容器 挂载jar包目录 利用openjdk:11镜像创建 创建后并运行命令 java -jar demo.jar
fi
将jar包build成镜像方式
准备了一台linux服务器,已经安装好了docker。
Jenkins中其他配置不变,仍然是从git拉取代码,并构建。但在构建之前,我们需要将服务器上的旧文件删除,停止并删除正在运行的容器,删除docker旧镜像。
cpp
# 在任务配置的Pre Steps中填写命令
rm -rf *
docker stop demo
docker rm demo
docker rmi demo
构建镜像需要dockerfile,可以将其放在项目里面,利用git去管理。dockerfile内容如下:
cpp
FROM openjdk:11
EXPOSE 8080
WORKDIR /root
ADD jarfile/demo*.jar /root/app.jar
ENTRYPOINT["java","-jar","/root/app.jar"]
除了jar包,记得将dockerfile文件也传输到服务器上
随后再加入命令,创建docker镜像,并生成容器。
cpp
docker build demo-image .
docker run -d -p 8080:8080 --name demo demo-image
Jenkins并发构建简介(仅供参考)
集群化构建可以有效提升构建效率,尤其是团队项目比较多或是子项目比较多的时候,可以并发在多台机器上执行构建。
Jenkins首页->Manage Jenkins->Manage Nodes and Clouds

这是目前运行Jenkins服务的节点,也就是一台运行Jenkins的服务器。
点击左侧的新建节点,自行输入节点名称,点击创建后进行节点配置。

远程工作目录:在该节点的哪个目录下进行构建任务
标签:节点标签名 用于区分节点

连接远程节点的方式,利用SSH方式 用户名和密码访问的方式,当然也可以配置SSH密钥。(仅供参考)同样的,再新建一个节点jenkins-03

回到Job配置页面,General部分,勾选,保存。随后 手动构建几次 进行测试
提醒:次节点需要完整的构建环境 安装maven、jdk、git,Jenkins只有在主节点上安装并运行即可
如图,在不同节点上 均有任务在进行构建。
pipeline
流水线(pipeline)
流水线既能作为任务的本身,也能作为jenkinsfile
使用流水线可以让我们的任务配置从ui手动操作,转换为代码,像docker的dockerfile一样。这样更适合大型项目,可以让团队其他开发者同时参与进来,同时也可以编辑开发Jenkinswebui不能完成的更复杂的构建逻辑,作为开发者可读性也更好。
完整语法
5个必备的组成部分
pipeline:整条流水线
agent:指定执行器
stages:所有阶段
stage:某一阶段,可有多个
steps:阶段内的每一步,可执行命令
案例:用pipeline进行自动化构建(仅供参考)
创建一个pipeline任务
General,构建触发器部分与freestyle project、maven项目类似。
主要是流水线部分,书写jenkinsfile。(也可以将jenkinsfile放在代码仓库中,由git来管理)
基础的hello world
cpp
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
// 这里的hello2 是我加的,就是说明,这是stages下的第二个任务 ,就是在pipeline中加单行注释 用 // 就行
stage('Hello2') {
steps {
echo 'Hello World'
}
}
}
}
保存测试一下(保存以后点立即构建)
我们来看一下日志
我们的项目要经历几个步骤,1、从git中拉取;2、maven打包;3前置清理工作 4、docker生成镜像并运行
点击下方蓝色的 流水线语法 ,可以使用Jenkins的代码生成器帮我们书写Jenkinsfile(推荐)。
在代码生成器中,我们可以选择已安装的插件(如图git插件),并和之前采用相同的方式填写配置信息,最后点击生成流水线脚本。
cpp
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
git credentialsId: '93f024b8-6456-4c98-a131-9a5ee9f42027', url: 'https://gitee.com/i-dont-recognize-you/school-page.git'
echo '拉取成功'
}
}
}
}
引入maven
需要在全局工具配置里面配置maven
利用maven进行构建
前置清理工作。使用片段生成器,选择 Publisher over SSH插件,进行配置,生成对应的流水线脚本,用于执行命令。
注意:第一次构建的时候 会失败 因为一开始没有这个容器。(此处偷了个懒,shell脚本应该写的更完整,仅供参考)
cpp
rm -rf *
docker stop demo
docker rm demo
docker rmi demo

再使用片段生成器,选择 Publisher over SSH插件,进行配置,生成对应的流水线脚本,用于传输构建好的jar包 生成容器 运行jar包。
创建多分支Job(仅供参考)
在上面提到的Blue Ocean插件,我们可以安装并使用该插件进行多分支的pipeline构建。
场景:
一个项目 在git仓库中有多个分支,我们需要对不同的分支使用Jenkins进行构建、部署。
在Jenkins的Blue Ocean中 创建流水线,选择git代码仓库,并配置。
点击创建流水线

对流水线进行配置,设置jenkinsfile的路径。(我们将jenkinsfile放在项目代码中,由git来管理)
两个分支配备不同的jenkinsfile,随后进行构建。查看结果,可以看到对该项目的两个分支都进行了构建
参考目录
https://www.bilibili.com/video/BV17i4y1d7SS
https://www.bilibili.com/video/BV1G24qeHEwV
https://www.bilibili.com/video/BV18wXrYMEhq
https://www.bilibili.com/video/BV11B4y1W7eH
https://www.bilibili.com/video/BV11awpeTEDT
https://www.bilibili.com/video/BV1jJtWexEuT
https://www.bilibili.com/video/BV1bS4y1471A
https://www.bilibili.com/video/BV14Y4y1j7s4
https://www.bilibili.com/video/BV1ds4y1k7QM
https://www.bilibili.com/video/BV1pF411Y7tq
https://blog.csdn.net/xhmico/article/details/136535498
https://blog.csdn.net/qq_41889508/article/details/137428625
https://blog.csdn.net/m0_63004677/article/details/139350534
https://blog.csdn.net/lzc2644481789/article/details/124888223