目录
- 一、对于CI/CD的理解
- 1.1、什么是CI(持续集成)
- 1.2、CI 的主要特点:
- 1.3、CI 的优势:
- **实际开发中的场景举例:**
- 1.4、什么是 CD(持续交付和持续部署)
- 1.5、持续交付(Continuous Delivery)
- 1.6、持续部署(Continuous Deployment)
- 1.7、CI/CD 流程示意
- 1.8、总结:
- 二、CI/CD 工具
- 2.1、一些常见的 CI/CD 工具包括:
- 三、Jenkins 能做什么,可以带来哪些好处?
- 3.1、Jenkins 能做什么:
- 3.2、Jenkins 带来的好处:
- 3.3、总结
- ============ 下面进入实践部分 ===============
- 四、安装Jenkins和所需插件
- 4.1、列出下面所需软件和下载地址
- 4.2、配置Jenkins
- 五、新增自动构建任务
- 5.1、新增自动构建任务-后端
- 备注:配置Linux机器间的免密复制,免密登录
- 5.2、新增自动构建任务-前端
- 备注:Nginx配置Jenkins的反向代理
- 六、总结
一、对于CI/CD的理解
CI/CD 是 Continuous Integration(持续集成)和 Continuous Delivery(持续交付)或 Continuous Deployment(持续部署)的缩写。这两者都是现代软件开发实践中的重要组成部分,主要用于提高软件开发的速度和质量。
1.1、什么是CI(持续集成)
持续集成(Continuous Integration, CI) 是指开发人员将代码频繁地(如每天多次)合并到共享的代码仓库中。每次代码合并后,都会通过自动化构建和测试,以确保新代码与现有代码的兼容性。
1.2、CI 的主要特点:
- 代码合并频繁:开发人员将自己的修改合并到主分支时,立即进行自动化的构建和测试。
- 自动化测试:每次代码变更后,都会自动运行单元测试和集成测试,确保新代码不会破坏已有功能。
- 快速反馈:当新代码引入了错误,CI 系统会及时通知开发人员,从而使他们能够迅速修复问题。
- 减少集成风险:通过频繁的小规模集成,减少了在发布时进行大规模集成的风险。
1.3、CI 的优势:
- 提高代码质量:通过自动化测试和代码审查工具,提升代码质量和稳定性。
- 降低合并冲突:开发人员频繁提交代码,降低了大规模合并时出现冲突的风险
实际开发中的场景举例:
例如:项目A有个test分支
开发小王:从master生产分支切一个bug_123分支,来修改bug,修改完成后合并到test分支。
开发小李:也从master生产分支切一个bug_456分支,来修改bug,修改完成后合并到test分支。
此时小王和小李都需要把test分支的代码部署到测试环境,让测试人员进行测试。
传统的操作:
小王和小李沟通谁去打包test分支,把包上传服务器,启动服务。
使用持续集成后:
开发只需要关注代码开发,并提交代码到test分支,后续的打包、上传、启动服务都可以交由持续集成系统来完成。
自动构建一般情况下有两种触发方式:
第一种是某个代码分支设置钩子,一旦检测到该分支有新的提交,持续集成系统就自动拉取最新代码进行打包部署。(这种情况从预发环境到生产环境的自动构建部署用的比较多)
第二种情况,在持续集成系统中配置一个任务,当需要部署的时候,直接一键构建并部署。(这种情况测试环境用的比较多)
1.4、什么是 CD(持续交付和持续部署)
持续交付(Continuous Delivery, CD) 和 持续部署(Continuous Deployment, CD) 是基于 CI 之上的进一步扩展,用于自动化软件的交付和发布。
1.5、持续交付(Continuous Delivery)
持续交付 是指在代码通过自动化测试后,能够自动构建并准备好随时部署到生产环境。虽然交付过程是自动化的,但最终是否部署到生产环境通常是由人工决定的。
自动化发布流程:持续交付确保每次代码变更都经过构建、测试和打包,并可以通过人工触发快速地部署到生产环境。
可控发布:可以选择何时将经过验证的代码发布到生产环境中。
目的是保持代码随时可发布:持续交付的目标是确保主分支始终处于可部署状态,以便快速响应业务需求。
1.6、持续部署(Continuous Deployment)
持续部署 是持续交付的进一步发展,指的是在通过所有自动化测试后,代码会自动部署到生产环境中,无需人工干预。
完全自动化:从代码提交、测试到生产环境的发布全部自动化。
快速迭代:每次代码变更都能够直接交付给最终用户,使新功能和修复迅速上线。
高要求:持续部署需要非常高的自动化测试覆盖率和质量,确保每次变更都不会引入问题。
1.7、CI/CD 流程示意
一个典型的 CI/CD 流程可以包含以下几个步骤:
-
1、代码提交(Commit):开发人员将新代码提交到版本控制系统(如 Git)。
-
2、持续集成(CI):
代码构建(Build):CI 工具(如 Jenkins、GitLab CI、GitHub Actions 等)自动触发构建脚本,将代码打包成可执行文件。
自动化测试(Test):运行单元测试、集成测试、静态代码分析等。
反馈结果(Feedback):如果构建或测试失败,CI 工具会立即通知开发人员。 -
3、持续交付/持续部署(CD):
自动化部署(Deploy):在测试通过后,将构建的产物部署到测试环境或预生产环境。
人工确认(在持续交付时):人工确认后部署到生产环境。
自动化发布(在持续部署时):自动将变更部署到生产环境中。
1.8、总结:
CI/CD 的核心理念在于“自动化”与“频繁交付”,它帮助开发团队在保证质量的前提下,快速迭代和发布软件。CI 通过自动化测试确保每次代码变更的稳定性,而 CD 则让代码随时可部署甚至自动部署到生产环境,最终实现快速响应业务需求和用户反馈。
CI/CD能减少了手动测试和部署的时间,使开发人员能够专注于编写代码。提高团队的项目交付效率。
提高代码质量和稳定性:自动化测试和代码审查能够在早期阶段发现问题,降低了缺陷进入生产环境的风险。
缩短交付周期:通过自动化的构建和部署流程,可以更快地将新功能或修复交付给用户。
降低发布风险:每次发布的改动量较小,即使出现问题,回滚也更加简单和安全。
大部分小公司可能开发和运维工作都是同一个人完成,这种情况下CI/CD的好处就更加明显了,可以大幅减轻开发人员的工作量(当然前期配置CI/CD环境对于开发人员来说也是个不小的挑战)。
二、CI/CD 工具
2.1、一些常见的 CI/CD 工具包括:
- Jenkins:一个流行的开源自动化服务器,支持各种插件,用于构建、测试、和部署。
- GitLab CI/CD:与 GitLab 深度集成的 CI/CD 工具,适用于 DevOps 流程。
- GitHub Actions:GitHub 提供的 CI/CD 服务,便于在 GitHub 项目中构建自动化工作流。
- CircleCI、Travis CI、Azure DevOps、Bamboo 等也是一些常见的 CI/CD 工具。
三、Jenkins 能做什么,可以带来哪些好处?
3.1、Jenkins 能做什么:
-
①、自动化构建和编译
代码构建:Jenkins 可以在开发人员提交代码后,自动执行构建脚本,编译代码并打包成可执行文件(如 JAR、WAR、Docker 镜像等)。
多语言支持:支持 Java、Python、Node.js、Go 等多种编程语言的构建。 -
②、自动化测试
单元测试:自动运行单元测试,确保代码基本功能的正确性。
集成测试:在代码合并到主分支之前运行集成测试,验证不同模块间的协作是否正常。
UI 和功能测试:结合 Selenium 等工具,自动执行前端 UI 测试和 API 测试,确保用户功能的正确性。 -
③、持续集成与持续交付(CI/CD)
持续集成:在开发人员提交代码后,自动触发构建和测试,确保代码在合并之前稳定可靠。
持续交付/部署:Jenkins 可以将构建后的产物自动部署到测试环境、预生产环境,甚至生产环境中,实现快速发布。 -
④、配置管理与基础设施自动化
基础设施即代码(IaC,Infrastructure as Code):通过集成 Terraform、Ansible 等工具,Jenkins 可以自动化管理云端资源的配置与部署。
环境配置:自动化管理应用所需的环境配置,如数据库迁移、服务启动等。 -
⑤、监控和通知
监控构建状态:通过 Web 界面实时查看构建、测试和部署的状态,并生成报告。
通知集成:支持将构建结果通过邮件、Slack、钉钉等渠道通知到相关人员,确保团队对项目状态及时知悉。 -
⑥、自定义插件支持
丰富的插件生态:Jenkins 拥有大量插件,支持与各种版本控制系统(如 Git、SVN)、云服务(如 AWS、Azure)、构建工具(如 Maven、Gradle)、容器(如 Docker、Kubernetes)等集成。
扩展性:可以根据团队的特定需求开发自定义插件,以满足特殊的自动化流程。
3.2、Jenkins 带来的好处:
-
①、提高开发效率
自动化流程:通过自动化代码构建、测试和部署,开发人员不再需要手动执行这些重复性操作,能够专注于编写和优化代码。
快速反馈:Jenkins 可以在每次代码提交后自动运行测试,并即时反馈测试结果,帮助开发人员尽早发现问题并进行修复。 -
②、提高代码质量和稳定性
自动化测试保障质量:Jenkins 通过自动化测试,能够在每次构建时验证代码的功能和性能,降低缺陷进入生产环境的风险。
持续集成减少集成风险:频繁的小规模集成能够减少开发人员之间的冲突,使代码合并变得更顺畅。 -
③、 加快交付速度
持续交付和部署:通过自动化的部署流水线,可以更快地将新功能、修复或优化版本交付到生产环境中。
支持多环境发布:可以轻松地部署到开发环境、测试环境和生产环境,从而加快测试和上线流程。 -
④、 提高透明度和协作性
可视化构建过程:Jenkins 的控制台和报告功能让团队可以直观地看到每个阶段的状态,构建失败的原因、测试报告等。
团队协作:通过自动化通知和报告,团队成员可以更快地了解项目进展情况,促进协作和沟通。 -
⑤、 降低发布风险
蓝绿发布和回滚:通过与 Kubernetes 等容器编排工具的集成,可以实现蓝绿发布、金丝雀发布等部署策略,从而在发布时确保系统的稳定性。
自动化回滚:在遇到问题时,可以自动执行回滚流程,将服务恢复到先前的稳定状态。
⑥、 支持多平台部署
跨平台兼容性:Jenkins 支持在 Windows、Linux 和 macOS 上运行,因此可以方便地在不同操作系统上进行构建和部署。
容器化支持:与 Docker、Kubernetes 等工具的深度集成,使得 Jenkins 在构建容器镜像、管理容器编排方面也得心应手。
3.3、总结
Jenkins 作为自动化服务器,不仅能够简化开发流程,还能显著提高代码的质量和交付速度。它通过自动化构建、测试、部署等环节,使团队能够更高效地开发和发布软件,减少手动操作和人为错误。同时,Jenkins 丰富的插件生态和强大的自定义能力,使其能够适应各种规模和复杂度的项目需求,是现代 DevOps 实践中不可或缺的工具之一。
============ 下面进入实践部分 ===============
四、安装Jenkins和所需插件
安装环境Linux:
# 查看操作系统
cat /etc/os-release
# 查看处理器架构
uname -m
我自己装的虚拟机:
操作系统:CentOS7
处理器: x86-64架构
生产环境:
操作系统:Red Hat Enterprise Linux 8.10
处理器: x86-64架构
还包括CentOS8 都可以用下面的方式部署。
4.1、列出下面所需软件和下载地址
这里统一放网盘里了,方便一键下载。
基本都是tar.gz格式压缩包,直接使用 tar -zxvf 压缩包名称 解压即可。
下面也都给出了官方的下载地址。
-
①、JDK11 (Jenkins2.432版本启动环境JDK11最低要求,需要登录Oracle账号下载)
https://download.oracle.com/otn/java/jdk/11.0.25+9/60e5d03cc24a4e1c8ab5d29303dbe066/jdk-11.0.25_linux-x64_bin.tar.gz -
②、Jenkins的war包 ,版本 2.432 (这一版是经过我们生产实践过的版本,下载插件一般不会遇到版本问题)
https://mirrors.jenkins.io/war/ -
③、Maven (版本3.9.9)
https://maven.apache.org/download.cgi
-
④、Git (这个版本无所谓,推荐yum安装即可,我安装的版本是1.8.3.1)
yum install -y git
- ⑤、NVM+Node
NVM直接从Github下载解压即可(使用的版本0.38.0)
wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.38.0.tar.gz
nvm解压后,运行下这个命令使nvm生效 source ~/.bashrc
Node直接使用NVM下载管理:
下面简单列出几个nvm使用的命令
# 列出可用的Node版本
nvm ls available
# 安装14.21.3版本(我这个是比较老的依赖Node.js打包的前端项目,所以用的这个版本的Node)
nvm install 14.21.3
# 使用 某个版本的Node
nvm use 14.21.3
# 列出已下载的Node
nvm ls
推荐把Node包管理器的下载地址修改为淘宝的镜像,这样执行npm install命令的时候下载的比较快。
# 设置Node包管理器的包下载地址镜像为最新的淘宝镜像
npm config set registry https://registry.npmmirror.com
# 查看镜像地址
npm config get registry
到这基本上所需的软件都准备好了。
安装都比较简单,直接解压即可。都不用配置环境变量。
因为Jenkins中我们会配置maven和Git的安装目录。
JDK11在启动Jenkins的war包时也会指定JDK11安装目录中的jdk命令。
(这样做的目的是为了节省资源,因为这台机器已经安装了JDK8的环境,并且配置了环境变量,我们再安装一个JDK11仅仅是为了运行Jenkins的war包,我们通过Jenkins构建完成的jar或者war还在本机的JDK8环境下运行)。
这里启动Jenkins的命令如下:
# JDK11 解压目录是/web
# Jenkins的war包位置是/web/jenkins2.432/
# Jenkins日志位置 /web/jenkins2.432/log/info.log
nohup /web/jdk11/bin/java -jar /web/jenkins2.432/jenkins.war --prefix=/jenkins > /web/jenkins2.432/log/info.log 2>&1 &
查看Jenkins启动日志
tail -200f /web/jenkins2.432/log/info.log 2>&1 &
上面启动命令加了--prefix=/jenkins
配置了上下文访问路径/jenkins ,这样方便后期配Nginx代理。
建议上面的软件都安装在统一的目录下。
浏览器输入http://ip:8080/jenkins
上面的ip替换成你部署jenkins的实际机器ip。
Jenkins第一次启动的时候 会在日志里打印一个字符串用于第一次进入系统时输入验证。
这个在启动日志里面有。
查看Jenkins启动日志(按照上面的启动命令启动)
tail -200f /web/jenkins2.432/log/info.log 2>&1 &
然后保证你的Jenkins机器能联外网。直接选安装推荐的插件。(我安装的这个版本Jenkins,目前不会出现插件版本不兼容的问题)
等待插件安装完毕。(按道理来说应该没问题,这个版本算是比较新的不会有插件不兼容的问题)
如果插件安装失败,可以重试几次。
如果仍然失败,可以修改插件下载地址的镜像。重新安装尝试。
再不行就去官网下载插件上传安装(有时候一个插件依赖很多个插件,所以这种方式会比较麻烦)。
再不行可以参考这篇文章
4.2、配置Jenkins
4.2前提是 4.1中的软件都安装完毕。
下面开始配置 Maven、JDK、Git
注意这里配置的JDK是给Jenkins执行构建任务使用的,我们上面下载的JDK11是给Jenkins启动使用的。
①、配置Maven
如果你的插件都安装成功,会有一个汉化插件的,如果没有也可以手动去安装汉化插件。
去系统管理->插件管理 搜索 Chinese 安装即可。
下面配置Maven
进入全局工具配置:
Maven很简单,就配置Maven的settings文件路径和Maven的安装路径即可,setting文件里面配置远程Maven仓库地址,和本地仓库目录地址(这个根据自己项目需求配置)
我的Maven安装在 /web/maven 目录下 就配这个目录
②、配置JDK
上面我们安装的JDK11只是给jenkins启动用的, 我机器中还有一个JDK8,这里打包和运行构建的应用使用的JDK我配置的是JDK8
也很简单 直接配置JDK8的安装目录
③、配置Git
上面我的Git是使用yum安装的,看下目录在哪
whereis git
输出 /usr/bin/git
那么Git 就配置这个地址 /usr/bin/git
配置到这就ok了。
五、新增自动构建任务
5.1、新增自动构建任务-后端
任务:自动构建并部署Springboot后端项目
先列好需要让Jenkins做的事情:
①、Jenkins本身运行在 A机器,让Jenkins从我们指定的Git地址上拉取代码,切换到指定的分支。
②、使用Maven进行打包,这里我打的是jar包(你也可以打war包或者构建docker镜像,视项目需求而定)
③、将构建好的jar,复制到机器B
④、在机器B执行脚本,停止正在运行的jar,启动新的jar。
大致上就上面4步。
现在一步一步来操作:
①、
新建一个freestyle类型的任务
写个描述
然后选择丢弃旧的构建。这样节省空间,如果空间充足或者在生产环境使用,建议设置保留一周。
②、
配置构建步骤
这里构建的是一个结构比较简单的Maven项目,
如果是父子项目结构,这里的目标 需要输入的指令要再复杂些。
简单的Maven项目直接输入 clean package -DskipTests 即可
表示 先clean 再 跳过测试 直接打包 如果maven本地仓库已经全了 也可以再加一个 -o参数 表示离线打包这样更快
clean package -DskipTests -o
备注:配置Linux机器间的免密复制,免密登录
③、如何把构建好的jar包从机器A,传到机器B呢?
这里提供两个思路
思路一、机器A使用NFS共享jenkins的工作目录,机器B挂载 机器A的jenkins工作目录。
思路二、配置远程免密登录、使用scp 远程复制命令
由于第四步还要远程执行脚本,所以这里就利用思路二实现。
对思路一感兴趣的可以参考 我的这篇文章 Linux系统使用NFS挂载共享目录
现在按照思路二,配置免密登录:
这里用服务器A,和服务器B举例:
先看下服务器A scp输入密码远程复制行不行:
先使用scp命令看下
scp a.txt root@192.168.220.220:/root/a.txt
下面221和220是我在本地演示配置免密登录 克隆的两个虚拟机。
可以看到现在是需要输入密码的,输入密码后可以成功copy
如果你输入密码也不能成功copy,就需要在B服务器开启一个配置
vi /etc/ssh/sshd_config
# 配置 PasswordAuthentication yes
保存
然后重启 sshd服务
service sshd restart
当验证好了scp命令可用之后在进行下列配置。
我就直接用root用户生成密钥对了
先在A机器生生密钥对
# -P "" 表示不设置密码
ssh-keygen -t rsa -P ""
会让你选择在哪里生成,就用默认的就好,直接回车
A机器的密钥对就生成好了。
上面生成的.ssh目录是隐藏 ,需要使用cd /root/.ssh 进入后 才能看到里面的密钥对
cd /root/.ssh
ll
其中id_rsa 是私钥,id_rsa.pub是公钥。
把公钥id_rsa.pub copy到服务器B上,也就是右边的服务器
这里我就使用scp 输入密码的方式copy了,你也可以先下载下来,再登录服务器B的FTP服务上传。
scp id_rsa.pub root@192.168.220.220:/root/id_rsa.pub
然后进入服务器B的 /root目录下
可以看到刚才复制的服务器A的公钥
下面在服务器B也生成密钥对:
# -P "" 表示不设置密码
ssh-keygen -t rsa -P ""
此时把刚刚复制过来的A服务器的公钥里面的内容 追加到 服务器B 的 /root/.ssh/authorized_keys 文件中
cd /root
cat id_rsa.pub >> /root/.ssh/authorized_keys
看下服务器B 的authorized_keys的内容:
cat .ssh/authorized_keys
这个时候在A机器上 再用scp复制一个文件到B机器看看
cd ~
touch b.txt
scp b.txt root@192.168.220.220:/root/b.txt
可以看到不用输入密码就复制成功了。
也可以在A机器 使用ssh 命令 直接登录B机器
ssh 192.168.220.220
ip a
至此 免密复制scp 和免密登录 ssh 都配置好了
如果还有其他机器需要配置参照上面配置即可,例如机器C也想免密登录机器B,把机器C的公钥追加到机器B的 authorized_keys文件后面即可。
④、下面我们再配置构建完成后的脚本就行了
#!/bin/bash
echo '复制MyApp.jar到192.168.222.222'
scp /root/.jenkins/workspace/app/target/MyApp.jar root@192.168.222.222:/root/app/MyApp.jar
echo '复制MyApp.jar到192.168.222.222 完成'
# 使用 ssh 远程执行一系列命令
echo '启动MyApp.jar'
ssh root@192.168.222.222 << EOF
mv /root/app/MyApp.jar /service/nacos-jar/
pkill -9 -f MyApp.jar
nohup java -Xms2g -Xmx2g -Xmn1g -jar /service/nacos-jar/MyApp.jar --spring.config.additional-location=file:/service/nacos-jar/bootstrap.properties > /data/nacos-jar/logs/MyApp/info.log 2>&1 &
echo '启动完成,等待应用启动...'
# 轮询检查日志文件中是否包含"Started IbmpApplication"
LOG_FILE="/data/nacos-jar/logs/MyApp/info.log"
while ! grep -q "Started MyApp" \$LOG_FILE; do
sleep 5
echo '应用正在启动...'
done
echo '应用启动成功,查看进程'
ps aux | grep MyApp
EOF
echo 'Jenkins 构建任务完成'
脚本内ip、和应用名称已做处理。
大概解释下上面的脚本,把Jenkins构建完成的jar包远程复制到服务器192.168.222.222的/root/app/MyApp.jar位置。
使用ssh免密登录192.168.222.222,在192.168.222.222机器上执行脚本,杀掉MyApp进程,把新的jar替换,重启新的jar
然后每5秒查询一下jar的日志中启动完成的标记。检查到启动完成后,该任务执行完毕。
上面就是一个最简单的后端构建任务。
5.2、新增自动构建任务-前端
前提,Node环境已配置好。
整体比后端还要简单些。
先列好需要让Jenkins做的事情:
①、Jenkins本身运行在 A机器,让Jenkins从我们指定的Git地址上拉取代码,切换到指定的分支。
②、使用Node进行打包
③、将构建好的前端文件,复制到Nginx所在机器指定目录,覆盖原文件即可
新建freestyle任务
写个描述、勾上丢弃旧的构建
配置Git地址、用户名密码(或者秘钥)、指定分支。
直接在Build Steps里面 配置脚本,进行前端的构建 然后删除原前端文件,复制新打包的文件。
脚本
echo '开始构建'
cd /root/.jenkins/workspace/MyApp前端/ui/web
npm install
npm run package:MyApp-prod
rm -rf /service/MyApp-saas/saas-gateway-ui/MyApp/*
cp -r /root/.jenkins/workspace/MyApp前端/ui/web/dist/* /service/MyApp-saas/saas-gateway-ui/MyApp/
由于Nginx和Jenkins部署在同一台机器,这里的删除和复制就没有使用远程ssh 在另一台机器执行脚本了。
所以这个前端的脚本搞得比较简单。
上面就是最简单的前端自动构建配置。
备注:Nginx配置Jenkins的反向代理
上面说了Jenkins启动的时候加了上下文访问路径 --prefix=/jenkins ,假如部署jenkins的机器ip是 192.168.220.220
那么我们就可以使用http://192.168.220.220:8080/jenkins 来访问了。
如果不想每次都输入8080端口,就可以使用nginx做反向代理。
location /jenkins/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
还是建议启动服务的时候配一下上下文访问路径,这样配置nginx反向代理比较简单,不会出那么多坑,否则配置反向代理很可能出现静态资源无法加载的情况。
配置好后,reload一下nginx的配置文件即可,然后就可以使用http://192.168.220.220/jenkins来访问了,前提nginx要监听80端口。
六、总结
有了Jenkins的安装配置基础、Linux远程操作的基础之后,再去配置各种复杂的构建就有头绪了,当然Jenkins还有很多强大的功能值得探索,由于篇幅有限,后续再另写博客进行学习。
希望对你配置CI/CD环境有所帮助。