本文大纲概览:
- CI/CD 概念与工作流程 详解
- Jenkins安装、启动、初始化配置
- 使用Jenkins部署github上的 xzll-im 微服务项目
- freestyle方式
- push代码后自动部署
- pipeline方式部署
- pipeline + push 方式
本文实操过程中,相关工具版本信息如下:
- centos版本: CentOS Linux release 7.9.2009 (Core)
- jdk: jdk-11.0.22
- maven: 3.8.8
- git: 1.8.3.1
- jenkins 2.252
- docker: 26.1.4
- docker-compose: v2.27.2
- 其它项目中使用到的中间件版本请见
docekr-compose.yml
中的镜像版本,戳这里
什么是 持续集成(CI)& 持续交付(CD)?
大白话: 对于CI/CD的理解,可能每个人都不一样(一千个人有一千个哈姆雷特!😂),我理解他其实就是一种更加自动化的工作模式,使得开发、测试、运维之间的沟通成本降低,从之前的手动编译、打包、构建、测试到现在的自动化、流程化去执行这些步骤,从而更加快速,及时发现问题,最终实现:加快软件迭代周期,提高交付速度与质量 的目的!。
CI(持续集成) 介绍
CI全称: (Continuous Intergration)
持续集成的重点在于 构建编译
及 测试
(这里更多的
指通过脚本和自动化项目来进行的自动化测试
),开发人员每天要提交很多次代码到分支,在分支合并到主干前,需要通过编译和测试识别出问题。持续集成的流程就是通过自动化的构建(主要是构建编译、自动化测试)来验证,从而尽早地发现集成错误。
CI(持续集成)的工作流程
- CI初始化:包括但不限于(CI服务的安装&启动,脚本、任务定义与配置,webhook设置,凭证设置,系统配置,插件等等)
- 开发人员从代码库中获取最新代码(pull)。
- 开发人员在本地进行开发和测试。
- 开发人员将代码提交(commit & push)到代码仓库(github、 gitlib)
- 通过回调方式通知CI服务器,ci服务器自动拉取最新代码并触发构建任务。
- 构建(build)-> 自动化测试(test)-> 反馈结果(result)
- 将自动化测试的结果反馈给开发人员(钉钉邮件短信等方式),如果测试失败,开发人员会及时修复代码并重新提交
- 构建和测试成功后,代码可以部署到进一步的测试环境或生产环境中
集成工具
集成工具有很多种(我所接触的主要还是jenkins
和gitlib
),包括但不限于以下: * Jenkins (常见):一个开源的自动化服务器,支持复杂的构建、测试和部署流水线。 * GitLab CI/CD (常见):GitLab 内置的 CI/CD 工具,支持从代码提交到生产部署的全流程自动化。 * CircleCI:一个基于云的持续集成和持续交付平台,支持多种编程语言和构建环境。 * Travis CI:一个基于云的持续集成服务,特别适用于 GitHub 项目。 * Spinnaker:一个开源的持续交付平台,支持多云环境的自动化部署
持续集成的好处
- 提高代码质量:通过频繁的自动化测试和代码质量检查,可以早期发现并修复错误。
- 加快交付速度:自动化构建和测试减少了手动操作的时间,可以提高开发速度从而加快交付。
- 提高团队协作效率:开发人员可以更快地得到反馈,后期与测试人员协作更加顺畅。
总之概括起来就是一句话:
省去人工操作,push后自动构建、测试(这里指自动化测试)、反馈,从而尽早的在开发环境发现代码问题并修复CI 流程图
下边是持续集成(CI) 的流程图:
知道了CI , 那么CD又是指啥呢?接着看
CD(持续交付&持续部署) 介绍
CD 有两个意思 1. 一是 持续交付(Continuous Delivery) 2. 另一个是持续部署(Continuous Deployment)
说一句:其实做到持续交付就已经很不错了,持续部署听听就行了,别当真!为什么这么说? 往下看。
何为持续交付?
持续交付指的是将产品尽可能快的发布上线的过程。持续交付是在持续集成基础上的扩展,也就是说在成功通过dev环境的自动化部署与测试之后,为了尽快上线我们还需要自动化发布
fat或者uat环境(如果需要的话),整个流程实现后,根据实际需要,可以人工控制是否发布prod
环境。一般在公司都是开发环境(dev)、测试环境(fat)、预发布环境(uat)和正式生产环境(prod),如果代码在预发布环境测试通过,那么就可通过 手动方式 部署生产环境,从而尽可能的实现产品快速迭代上线。
持续交付的几个关键因素: - 自动化构建和测试: 与持续集成(CI)类似,持续交付(CD)依赖于自动化的构建和测试,以确保每次代码更改都能被快速验证。 - 自动化部署: 持续交付要求自动化部署流程,这意味着每次代码更改都可以自动部署到不同的环境中(如开发、测试、预生产)。 - 环境一致性: 确保所有环境(从开发到生产)的一致性,以减少部署问题。 - 持续反馈: 提供持续反馈,确保开发团队及时了解相应服务在不同环境中的状态和问题。 - 手动发布控制: 尽管大部分部署过程都是自动化的,但 持续交付 通常 保留手动发布的控制权。发布到生产环境的最终决定由相关人员评估,可以的话再通过手动的方式来发布生产环境
持续交付流程图
何为持续部署?
持续部署是持续交付的进一步扩展。在持续部署中,所有的代码更改在通过自动化测试和验证后,都会自动部署到生产环境中。与持续交付不同,持续部署不通过手动发布
来发布生产环境,而是自动发布生产环境。一般来说,非生产环境的持续部署基本都能实现。但生产环境的持续部署并不是每个企业都能做到,主要原因是受限于各种系统功能依赖、自动化测试不完善等因素,自动化方式部署到生产,将可能造成严重生产事故。 所以实际我觉得没几个企业这样做。能做到持续交付就已经很不错了。生产环境的部署 一定要认为控制。持续部署 听听就行了,不要玩火呀! 哈哈!😂😂😂😂😂😂😂😂😂😂😂😂
持续部署的关键要素: - 自动化构建、测试和部署: 持续部署依赖于完全自动化的构建、测试和部署流程,以确保每次代码更改都能被快速、可靠地部署到生产环境中。 - 强大的精准的测试覆盖: 持续部署需要非常高的测试覆盖率,包括单元测试、集成测试、端到端测试等,以确保所有代码更改都能被全面验证。 - 快速回滚机制: 当新代码引入问题时,必须有快速回滚的机制,以确保生产环境的稳定性。 - 持续监控: 持续监控生产环境中的应用性能和健康状态,确保及时发现和解决问题
注意:
无论是持续集成、持续交付还是持续部署,如果要想实现,都离不开CI服务器!
ok到这里你对CI/CD有自己的理解了吗?下边我们来学习一个非常重要且常见功能丰富的CI/CD 工具 : Jenkins ! 想玩CI/CD以及再往大一点的DevOps? 那么首先玩转Jnekins是必不可少的。换句话说,其实Jenkins是CI/CD、DevOps 这些概念的 其中一个重要 “实现”
!
介绍完CI/CD 下边我们开始学习Jenkins
Jenkins 安装、启动、初始化
以下说明是我选择哪种方式安装jenkins的过程记录,这里也记录下来,做个备忘。
说明1:为什么不使用docker安装jenkins? 其实我也想使用docker安装,但是当我从docker hub中找到对应的镜像进行下载时,发现要么是下载不下来镜像,要么是下载下来的镜像 运行时的jenkins版本过低,导致一些插件安装报错,使得我很恼火。
下载不下来镜像: 到docker hub 去找到对应镜像 ,戳此进: jenkins 的 docker hub
执行docker pull 镜像 发现下载失败,都是超时。。。。
- 版本过低插件安装不了: ,后来终于有两个镜像可以下载了 就是这个镜像:
jenkins/jenkins:lts-jdk11
和jenkins/jenkins:latest
镜像,但是却提示jenkins版本过低导致一些插件安装不了,报错如下:因为这个搞了半天,其实最主要原因可能就是欺负我的虚拟机没开vpn,哎 手头紧,暂时先不开了毕竟有点小贵,所以就决定弃启用docker安装jenkins, 我用war或RPM也行呀,真是的,😄
- 版本过低插件安装不了: ,后来终于有两个镜像可以下载了 就是这个镜像:
- 说明2:为什么安装jenkins 2.252版本?
- 由于在使用jenkins过程中我需要一些最新插件,而 LTS(
官方长期支持版本
)版本缺少对最新插件的支持,所以这里弃用LTS版本而使用较新的版本来安装部署学习,我使用的是: 2.452 (生产环境还是建议使用LTS版本来安装启动jenkins
)
- 由于在使用jenkins过程中我需要一些最新插件,而 LTS(
- 说明3:为什么选择war包安装jenkins?
- 首先第一原因是因为上边的说明1才迫使我使用war安装jenkins,另外因为我是centos7,所以其实我本应该使用
RPM软件包
方式安装jenkins,对应的版本是redhat的 LTS Release 的 redhat-stable(已发布的LTS版本)来安装jenkins 下边的引导页面戳这里,,但是因为遇到了一些问题主要还是网络问题(还是欺负我虚拟机没vpn 😂😂 再欺负我真要买Strong vpn了啊 哈哈),所以我不用此方式,如果网络好(能fq)可以使用,(安装指南戳这里)
- 最终:我选择使用war包安装jenkins ,因为经过实践我发现此方式比较好用不用担心被q的问题,选择war安装的话点击下边这个LTS Release:
war-stable
然后找到我要安装的版本(注意在安装此版本之前,我安装过较低版本 (LTS版本的2.361)但是我发现有些插件不能用,必须高版本才行所以这里选择较高的一个版本
2.452
,ok接下来开干
- 首先第一原因是因为上边的说明1才迫使我使用war安装jenkins,另外因为我是centos7,所以其实我本应该使用
ps: 其实某些场合下,docker部署不一定是最优方案。不一定要执着于所有东西都往docker堆,当然如果是开发测试环境,当我没说。
下载war、启动并初始化 jenkins
有了上边的铺垫,接下来我们首先找到2.452版本
的war包:
下载war包
之后使用命令下载war包:
bash wget https://mirrors.jenkins-ci.org/war/2.452/jenkins.war --no-check-certificate
编写启动脚本 来启动jenkins
ok从上边截图可知下载成功,接下来编写jenkins启动脚本: 完整jenkins启动脚本在这: ```bash
!/bin/bash
args=$1
注意修改jenkinswar包的目录
jenkinswarpath="/usr/local/soft_hzz/jenkins"
jenkins开放端口
jenkinshttpport="8079"
java安装路径
javahome="/usr/lib/jvm/java-11-openjdk-11.0.22.0.7-1.el79.x86_64"
日志文件路径
jenkinslogpath="/tmp/data/logs/jenkins.log"
function isRunning(){ local jenkinsPID=$(ps -ef | grep jenkins.war | grep -v grep | awk '{print $2}') if [ -z ${jenkinsPID} ]; then echo "0" else echo ${jenkinsPID} fi }
停止jenkins
function stop(){ local runFlag=$(isRunning) if [ ${runFlag} -eq "0" ]; then echo "Jenkins is already stopped." else kill -9 ${runFlag} echo "Stop Jenkins success." fi }
启动jenkins
function start(){ local runFlag=$(isRunning) echo "${runFlag}" if [ ${runFlag} -eq "0" ]; then # nohup ${javahome}/bin/java -jar ${jenkinswarpath}/jenkins.war --httpPort=${jenkinshttpport} > ${jenkinslog_path} 2>&1 &
# 对jenkins内存大小进行限制 否则总是超内存 被系统kill
nohup ${java_home}/bin/java -Xms512m -Xmx2g -jar ${jenkins_war_path}/jenkins.war --httpPort=${jenkins_http_port} > ${jenkins_log_path} 2>&1 &
if [ $? -eq 0 ]; then
echo "Start Jenkins success."
exit
else
echo "Start Jenkins fail."
fi
else
echo "Jenkins is running now."
fi
}
重启jenkins
function restart(){ local runFlag=$(isRunning) if [ ${runFlag} -eq "0" ]; then echo "Jenkins is already stopped." exit else stop start echo "Restart Jenkins success." fi }
根据输入的参数执行不同的动作
参数不能为空
if [ -z ${args} ]; then echo "Arg can not be null." exit
参数个数必须为1个
elif [ $# -ne 1 ]; then echo "Only one arg is required: start|stop|restart"
参数为start时启动jenkins
elif [ ${args} = "start" ]; then start
参数为stop时停止jenkins
elif [ ${args} = "stop" ]; then stop
参数为restart时重启jenkins
elif [ ${args} = "restart" ]; then restart else echo "One of following args is required: start|stop|restart" exit 0 fi ``` 接下来启动: