CI/CD
1. 概念
- 持续集成(Continuous Integration,CI):是一种软件开发实践,要求开发团队成员频繁地将各自的代码变更合并到主干分支(通常是主分支)中。每次代码提交后,会自动触发构建过程,包括编译代码、运行单元测试等操作,以便尽早发现集成问题,确保代码的质量和一致性。例如,一个多人协作开发的Java 项目,不同开发人员每天多次将自己编写的代码提交到 Git 仓库的主分支,每次提交都会触发 CI流程来验证代码是否能正确编译和通过基本测试。
- 持续部署(Continuous Deployment,CD):在持续集成的基础上更进一步,是指当代码通过了所有的测试和质量检查后,自动将其部署到生产环境或者预生产环境等目标环境中,实现软件的快速、频繁发布,减少人工干预带来的错误和延迟,让用户能够更快地使用到新功能或修复后的版本。比如一个电商网站的后端服务,新功能开发完成并通过CI 流程验证后,能直接通过持续部署流程快速上线,让用户可以体验到新特性。
2. 意义及重要性
- 提高代码质量:通过频繁的集成和自动化测试,能及时发现代码中的语法错误、逻辑问题以及不同模块间的集成冲突等,在问题产生的早期就进行修复,避免问题在后续开发过程中积累和放大,使得最终交付的代码更加稳定可靠。
- 加速软件开发周期:减少了手动构建、测试和部署的时间成本,开发人员可以快速得到代码变更后的反馈,一旦代码通过验证就能快速部署上线,提高了软件发布的频率,让产品能够更快地响应市场需求和用户反馈,增强竞争力。
- 增强团队协作:明确了开发流程和规范,每个开发人员的代码变更都需要经过统一的 CI/CD
流程检验,促使大家遵循相同的代码标准和集成规范,便于团队成员之间更好地协同工作,降低因代码合并等问题产生的沟通成本和冲突。
持续集成/持续发布–项目—开发(git) -->git主库–>jenkins(调用maven打包+测试)–>发布到后端服务器
CI/CD实现流程图
前提条件
所需安装软件:
Docker:《Docker安装部署及常用命令》
GitLab:《Docker Compose部署GitLab》
Jenkins:《Linux—Jenkins安装部署》
Harbor:《Linux—Harbor 镜像仓库部署实战》
如果采用单节点部署所有所需软件,硬件要求如下:
- Linux操作系统,Ubuntu 或 CentOS
- 服务器内存至少8Gi
- 服务器CPU至少4C
- 服务器磁盘至少10G
本文采用多节点部署,配置信息如下:
软件名称 | 所在服务器IP | 主机名 | 部署路径 | 版本 |
---|---|---|---|---|
Docker | 192.168.200.128 | node001 | /usr/bin | v26.1.4 |
Docker-compose | 192.168.200.128 | node001 | /usr/local/bin/docker-compose | v2.31.0 |
Java | 192.168.200.128 | node001 | /root/java17/jdk17 | v17.0.3.1 |
Tomcat | 192.168.200.128 | node001 | /root/tomcat11/tomcat11 | v11.0.1.0 |
Maven | 192.168.200.128 | node001 | /opt/maven | v3.9.9 |
Jenkins | 192.168.200.128 | node001 | /root/tomcat11/tomcat11/webapps/jenkins | v2.463 |
Git | 192.168.200.128 | node001 | /usr/bin | v1.8.3.1 |
Gitlab | 192.168.200.128 | node001 | Docker Compose方式部署 | v17.6 |
Harbor | 192.168.200.129 | node002 | /opt/harbor/harbor/ | v2.11.2 |
一、配置Jenkins环境
1. 全局配置
Dashboard -> Manage Jenkins ->Tools
1.1 配置JDK
1.2 配置Maven
记得上述操作需要点击应用和Save保存。
2. 系统配置
Dashboard -> Manage Jenkins ->System
2.1 配置JDK
2.2配置Maven
至此,Jenkisn中的Java和Maven环境搭建完成。
3. 安装Git插件
这个插件是为了方便后续我们去代码仓库拉取代码.Dashboard -> Manage Jenkins ->Plugins
3.1搜索需要安装的插件名称
3.2 搜索安装Git插件
4. 安装Maven插件
点击 新建任务 ,若新建任务中没有,Maven构建选项,按照上述Jenkins下载插件那里,输入Maven,点击安装即可,就会出现Maven构建选项。
这个插件是为了Jenkins拉取代码后调用Maven工具对项目进行打包。
5. 安装凭证插件
在系统管理下没有凭证管理这个插件,也是按照上述安装插件方式进行安装,安装重启Jenkins后就会看到凭证管理,凭证管理插件是这个-Credentials Binding Plugin。
6. 配置gtilab-token
gtilab-token获取方式,浏览器访问GitLab环境,添加新令牌
6.1 创建令牌
6.2 复制令牌
7. 添加GitLab令牌到Jenkins
Dashboard->Manage Jenkins->Credentials
8. 添加Harbor用户到Jenkins
9. 访问Jenkins配置gtilab-token
Dashboard -> Manage Jenkins ->System
二、Jenkins构建一个Maven项目
因为我们的案例是一个微服务项目,因此我们这里用Maven来构建一个简单拉取代码的流水线。
Dashboard->新建Item
1. 新建Maven项目
2. 配置GitLab连接信息
3. 配置maven指令
配置完成后点击应用、Save。
4. 构建项目
执行构建我们刚刚创建好的maven项目。
查看构建日志
5. 配置SSH凭证拉取代码
上述我们使用用户名和密码凭证来拉取代码,假设项目之前做Jenkins的流水线采用的gitlab账号的密码忘记,或者账号注销了,那咱们流水线拉取代码就无法实现了,因此对于服务之间之间认证,最好采用SSH认证。
我们可以使用SSH生成一份公钥和私钥密文文件,将公钥存在在代码仓库(Gitee或GitLab)服务上,然后在Jenkins服务中存放私钥。后续通过SSH认证拉取代码即可。
5.1 生成公钥和私钥
ssh到我们Jenkins所在服务器,执行以下命令生成公钥和私钥
ssh-keygen -t rsa
5.2 查看生成的秘钥
cd /root/.ssh
ll
5.3 将生成的公钥存放在Gitlab中(公钥)
登录Gitlab后,点击头像,选择设置,找到SSH公钥
5.4 使用SSH凭证拉取代码(私钥)
添加Git凭证
Dashboard->Manage Jenkins->Credentials
查看私钥信息
cd /root/.ssh
cat id_rsa
添加私钥信息,保存。
6. 配置Git连接信息
回到我们刚刚创建好的maven项目,增添Git连接配置。
至此一个Maven项目任务已创建完成!
三、Jenkins构建一个流水线Pipeline项目
以上步骤如果你已经都已完成,接下来我们就开始可以构建一个Pipeline项目来实现CI/CD构建了。
1. 新建Pipeline项目
Dashboard->新建Item
1.1 新建Pipeline
1.2 配置GitLab工程连接
1.3 配置Jenkinsfile
我的Jenkinsfile配置内容如下:
pipeline {
agent any
environment {
// 配置GitLab凭据和Harbor凭据
GIT_CREDENTIALS = '8fc27d58-f587-40e6-bd90-a3a419ffa4fc' // GitLab凭据ID
HARBOR_CREDENTIALS = 'harbor-id' // Harbor凭据ID
HARBOR_HOST = '192.168.200.129:85' //Harbor地址
HARBOR_PROJECT = 'mogu' //Harbor中的项目名称
}
stages {
stage('Checkout Code') {
steps {
// 从GitLab拉取代码
git (credentialsId: "${GIT_CREDENTIALS}", url: 'ssh://[email protected]:8222/root/mogu.git',branch: 'Nacos')
}
}
stage('Maven Build') {
steps {
// 使用Maven构建项目
script {
sh "cd $WORKSPACE/ && mvn clean install"
}
}
}
stage('Build Docker Image') {
steps {
// 构建Docker镜像
script {
//env.imageTag = sh(script: "echo `date '+%Y%m%d%H%M%S'`", returnStdout: true).trim()
//echo "${imageTag}"
sh 'docker version'
sh 'pwd && ls -alh'
sh 'cd $WORKSPACE/ && docker build -f mogu_admin/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_admin:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_gateway/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_gateway:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_monitor/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_monitor:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_picture/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_picture:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_search/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_search:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_sms/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_sms:1.0 . '
sh 'cd $WORKSPACE/ && docker build -f mogu_web/src/main/resources/Dockerfile -t ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_web:1.0 . '
//sh "docker build -t ${DOCKER_IMAGE_NAME}:${imageTag} ."
}
}
}
stage('Push Docker Image to Harbor') {
steps {
// 登录Harbor并推送镜像
script {
withCredentials([usernamePassword(credentialsId: "${HARBOR_CREDENTIALS}", usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) {
sh 'docker login -u $HARBOR_USERNAME -p $HARBOR_PASSWORD ${HARBOR_HOST}'
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_admin:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_gateway:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_monitor:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_picture:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_search:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_sms:1.0"
sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_web:1.0"
}
}
}
}
}
post {
always {
// 清理工作,删除构建的临时镜像等
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_admin:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_gateway:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_monitor:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_picture:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_search:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_sms:1.0 || true'
sh 'docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/mogu_web:1.0 || true'
}
}
}
2. 执行构建
3. 查看构建结果
4. 设置GitLab Webhook
如果你希望GitLab代码提交后自动触发Jenkins构建,可以配置GitLab的Webhook来调用Jenkins的构建触发API。
4.1 在GitLab项目中,进入“Settings” -> “Webhooks”
4.2 输入你的代码URL
4.3 设置触发条件
4.4配置Jenkins的构建触发器
至此一个Pipeline项目已实现CI/CD构建!