1、CICD流程总览
部署流程
1、通过jenkins拉取开发人员提交到gitee上最新的代码
2、通过maven进行打包
3、调用sonarqube进行代码质量检查
4、通过dockerfile制作镜像
5、提交制作的镜像到镜像仓库
6、通过k8s拉取最新的镜像,重启pod
2、项目准备
这次我准备了一个微服务项目,是依照Ruiyi-Cloud进行了一些修改,所得到的微服务项目。项目地址为:https://gitee.com/qi-guohui/qgh-cloud,大家请fork到自己的代码仓库中。
3、流水线方式的任务
1、通过jenkins拉取开发人员提交到gitee上最新的代码
1、新建流水线方式
2、配置git地址
3、在代码长库中添加流水线文件Jenkinsfile
jenkinsfile文件内容为:
pipeline {// 指定任务在哪个集群节点中执行agent any// 声明全局变量,方便后面使用environment {}stages {stage('拉取git仓库代码') {steps {echo 'Hello World'}}}
}
把生成的脚本放到jenkinsfile中,修改后的jenkinsfile内容如下:
pipeline {// 指定任务在哪个集群节点中执行agent anystages {stage('拉取git仓库代码') {steps {checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'b3716fb8-9358-4326-8b18-4bc7b7e6ec1c', url: 'https://gitee.com/qi-guohui/qgh-cloud.git']])}}}
}
4、配置项目变量
1、配置tag
2、配置选项参数
配置完成后,构建页面如下图所示:
2、通过maven进行打包
1、配置jenkinsfile
pipeline {// 指定任务在哪个集群节点中执行agent anytools {// 指定要使用的 Maven 版本,需要配置mavenmaven 'maven_home' }stages {stage('拉取git仓库代码') {steps {checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'b3716fb8-9358-4326-8b18-4bc7b7e6ec1c', url: 'https://gitee.com/qi-guohui/qgh-cloud.git']])}}stage('项目打包') {steps {script {// 打包doPackage()}}}}}def doPackage() {if (env.program_name == 'yueyang-ui') {// 前端,需要设置权限,不然jenkins容器没有目录的权限,会导致下载前端依赖失败// sh 'chmod -R 777 /var/jenkins_home/workspace/yueyang-ui && cd yueyang-ui && npm cache clean --force && npm install --registry=https://registry.npmmirror.com --unsafe-perm && npm run build:prod'sh '''chmod -R 777 /var/jenkins_home/workspace/yueyang-uicd yueyang-uirm -rf node_modules/npm cache clean --forcenpm install --registry=https://registry.npmmirror.com --unsafe-permnpm run build:prod'''} else {// 后端 sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'sh 'mvn clean package -DskipTests'}}
这里在tools组件中指定了maven,运行是按指定的maven打包,这里需要特殊注意一下,maven配置的值必须是全局工具配置的变量的名称,如果没配置,必须要配置,按如下图配置
3、调用sonarqube进行代码质量检查
1、启动sonarqube服务
修改docker-compose.yml文件,添加sonarqube
services:jenkins:image: jenkins/jenkins:qghcontainer_name: jenkinsports:- 8080:8080- 50000:50000volumes:- ./data1/:/var/jenkins_home/- /etc/localtime:/etc/localtimenetworks:- my_cloud_network db:image: postgrescontainer_name: dbports:- 5432:5432networks:- my_cloud_networkenvironment:POSTGRES_USER: sonarPOSTGRES_PASSWORD: sonarsonarqube:image: sonarqube:8.9.6-communitycontainer_name: sonarqubedepends_on:- dbports:- "9000:9000"networks:- my_cloud_networkenvironment:SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonarSONAR_JDBC_USERNAME: sonarSONAR_JDBC_PASSWORD: sonarnetworks:my_cloud_network:external: true
部署服务docker-compose up -d
启动报错
修改配置: vi /etc/sysctl.conf
#使文件生效: sysctl -p
#重启服务 : docker-compose up -d
2、获取sonarqube 的token
访问http://ip:9000/ 默认用户名密码是admin/admin
本人密码最后改成sonarqube
3、修改sonarqube插件配置
#进入jenkins容器,修改sonarqube-sconar
docker exec -it jenkins /bin/bash
vim /var/jenkins_home/sonar-scanner/conf/sonar-scanner.properties
sonar.host.url=http://sonarqube:9000
sonar.sourceEncoding=UTF-8
4、配置jenkinsfile
pipeline {// 指定任务在哪个集群节点中执行agent any// 声明全局变量,方便后面使用environment {sonarqubeToken='6daf20a303e0fd298f077f3e60c962579dc2d2a7'}tools {// 指定要使用的 Maven 版本,需要配置mavenmaven 'maven_home' }stages {stage('拉取git仓库代码') {steps {checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'b3716fb8-9358-4326-8b18-4bc7b7e6ec1c', url: 'https://gitee.com/qi-guohui/qgh-cloud.git']])}}stage('项目打包') {steps {script {// 打包doPackage()}}}stage('通过Sonarqube做代码质量检测') {steps {script {doSonarqube()}}}}}def doPackage() {if (env.program_name == 'yueyang-ui') {// 前端,需要设置权限,不然jenkins容器没有目录的权限,会导致下载前端依赖失败// sh 'chmod -R 777 /var/jenkins_home/workspace/yueyang-ui && cd yueyang-ui && npm cache clean --force && npm install --registry=https://registry.npmmirror.com --unsafe-perm && npm run build:prod'sh '''chmod -R 777 /var/jenkins_home/workspace/yueyang-uicd yueyang-uirm -rf node_modules/npm cache clean --forcenpm install --registry=https://registry.npmmirror.com --unsafe-permnpm run build:prod'''} else {// 后端 sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'sh 'mvn clean package -DskipTests'}}def doSonarqube() {def scriptContent = '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./' + env.program_name + ' -Dsonar.projectname=' + env.JOB_NAME + ' -Dsonar.login=' + env.sonarqubeToken + ' -Dsonar.projectKey=' + env.JOB_NAME + ' -Dsonar.java.binaries=./' + env.program_name + '/target'// 定义程序所在目录env.program_dir_path = env.program_nameif (env.program_name == 'yueyang-gateway' || env.program_name == 'yueyang-auth') {echo 'scriptContent: ' + scriptContentecho 'env.program_dir_path: ' + env.program_dir_pathif(sh(script: scriptContent, returnStatus: true) != 0) {error '代码检查失败!'} else {echo '代码检查成功!'}} else if (env.program_name == 'yueyang-ui') {echo 'env.program_dir_path: ' + env.program_dir_path// 页面不检查echo '页面检查成功!'} else if (env.program_name == 'yueyang-file' || env.program_name == 'yueyang-gen'|| env.program_name == 'yueyang-job' || env.program_name == 'yueyang-system') {// 子模块scriptContent = '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./yueyang-modules/' + env.program_name + ' -Dsonar.projectname=' + env.JOB_NAME + ' -Dsonar.login=' + env.sonarqubeToken + ' -Dsonar.projectKey=' + env.JOB_NAME + ' -Dsonar.java.binaries=./yueyang-modules/' + env.program_name + '/target'echo 'scriptContent: ' + scriptContentenv.program_dir_path= 'yueyang-modules/' + env.program_nameecho 'env.program_dir_path: ' + env.program_dir_pathif(sh(script: scriptContent, returnStatus: true) != 0) {error '代码检查失败!'} else {echo '代码检查成功!'}} else {// 代码检查失败error '代码检查失败, 项目名称不存在!'}
}
注意:sonarqubeToken要换成自己生成的token
4、通过dockerfile制作镜像
1、容器内docker的安装
容器内安装docker有如下两种方式,
1、让jenkins中拥有docker(和主机拥有同一个docker)
2、可以在jenkins内部装一个docker
我们采用第一种方式
#修改宿主机的配置
cd /var/run
# 修改权限
chown root:root docker.sock
chmod o+rw docker.sock
修改docker-compose.yml
- /var/run/docker.sock:/var/run/docker.sock- /usr/bin/docker:/usr/bin/docker- /etc/docker/daemon.json:/etc/docker/daemon.json
#重启jenkins
docker-compose up -d 或者 docker-compose restart jenkins
2、创建阿里云镜像仓库
1、在阿里云中搜索 容器镜像服务,创建个人镜像仓库,步骤如下
2、docker登陆镜像仓库
3、修改镜像仓库地址
#vim /etc/docker/daemon.json
#sudo systemctl restart docker
3、添加构建镜像脚本
// 声明全局变量,方便后面使用environment {sonarqubeToken='6daf20a303e0fd298f077f3e60c962579dc2d2a7'
harbor_addr='crpi-y28tc52b6by7jt80.cn-hangzhou.personal.cr.aliyuncs.com/qgh-cloud-learning'}
........tools {// 指定要使用的 JDK 版本,需要配置jdkjdk 'java_home' // 替换为你的自定义JDK名称或者路径// 指定要使用的 Maven 版本,需要配置mavenmaven 'maven_home' // 替换为你配置的 Maven 版本,需要安装nodejs插件nodejs 'node_home'}
........stage('通过Docker制作自定义镜像') {steps {script {if (env.program_name == 'yueyang-ui') {sh '''rm -rf ./docker/yueyang-ui/distmv ./yueyang-ui/dist ./docker/yueyang-ui/cd ./docker/${program_dir_path}docker build -t ${harbor_addr}/${JOB_NAME}:${tag} .'''} else {sh '''rm -rf ./docker/${program_dir_path}/java/mkdir -p ./docker/${program_dir_path}/java/mv ./${program_dir_path}/target/*.jar ./docker/${program_dir_path}/java/cd ./docker/${program_dir_path}docker build -t ${harbor_addr}/${JOB_NAME}:${tag} .'''}}}}
5、提交制作的镜像到镜像仓库
添加构建脚本
stage('上传镜像到镜像仓库') {steps {sh '''docker image prunedocker push ${harbor_addr}/${JOB_NAME}:${tag}'''}}
最后附上完整的jenkinsfile文件内容
pipeline {// 指定任务在哪个集群节点中执行agent any// 声明全局变量,方便后面使用environment {sonarqubeToken='6daf20a303e0fd298f077f3e60c962579dc2d2a7'harbor_addr='crpi-y28tc52b6by7jt80.cn-hangzhou.personal.cr.aliyuncs.com/qgh-cloud-learning'}tools {jdk 'java_home' maven 'maven_home' nodejs 'node_home'}stages {stage('拉取git仓库代码') {steps {checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[credentialsId: 'b3716fb8-9358-4326-8b18-4bc7b7e6ec1c', url: 'https://gitee.com/qi-guohui/qgh-cloud.git']])}}stage('项目打包') {steps {script {// 打包doPackage()}}}stage('通过Sonarqube做代码质量检测') {steps {script {doSonarqube()}}}stage('通过Docker制作自定义镜像') {steps {script {if (env.program_name == 'yueyang-ui') {sh '''rm -rf ./docker/yueyang-ui/distmv ./yueyang-ui/dist ./docker/yueyang-ui/cd ./docker/${program_dir_path}docker build -t ${harbor_addr}/${JOB_NAME}:${tag} .'''} else {sh '''rm -rf ./docker/${program_dir_path}/java/mkdir -p ./docker/${program_dir_path}/java/mv ./${program_dir_path}/target/*.jar ./docker/${program_dir_path}/java/cd ./docker/${program_dir_path}docker build -t ${harbor_addr}/${JOB_NAME}:${tag} .'''}}}}stage('上传镜像到镜像仓库') {steps {sh '''docker image prune -fdocker push ${harbor_addr}/${JOB_NAME}:${tag}'''}}}}def doPackage() {if (env.program_name == 'yueyang-ui') {// 前端,需要设置权限,不然jenkins容器没有目录的权限,会导致下载前端依赖失败// sh 'chmod -R 777 /var/jenkins_home/workspace/yueyang-ui && cd yueyang-ui && npm cache clean --force && npm install --registry=https://registry.npmmirror.com --unsafe-perm && npm run build:prod'sh '''chmod -R 777 /var/jenkins_home/workspace/yueyang-uicd yueyang-uirm -rf node_modules/npm cache clean --forcenpm install --registry=https://registry.npmmirror.com --unsafe-permnpm run build:prod'''} else {// 后端 sh '/var/jenkins_home/maven/bin/mvn clean package -DskipTests'sh 'mvn clean package -DskipTests'}}def doSonarqube() {def scriptContent = '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./' + env.program_name + ' -Dsonar.projectname=' + env.JOB_NAME + ' -Dsonar.login=' + env.sonarqubeToken + ' -Dsonar.projectKey=' + env.JOB_NAME + ' -Dsonar.java.binaries=./' + env.program_name + '/target'// 定义程序所在目录env.program_dir_path = env.program_nameif (env.program_name == 'yueyang-gateway' || env.program_name == 'yueyang-auth') {echo 'scriptContent: ' + scriptContentecho 'env.program_dir_path: ' + env.program_dir_pathif(sh(script: scriptContent, returnStatus: true) != 0) {error '代码检查失败!'} else {echo '代码检查成功!'}} else if (env.program_name == 'yueyang-ui') {echo 'env.program_dir_path: ' + env.program_dir_path// 页面不检查echo '页面检查成功!'} else if (env.program_name == 'yueyang-file' || env.program_name == 'yueyang-gen'|| env.program_name == 'yueyang-job' || env.program_name == 'yueyang-system') {// 子模块scriptContent = '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./yueyang-modules/' + env.program_name + ' -Dsonar.projectname=' + env.JOB_NAME + ' -Dsonar.login=' + env.sonarqubeToken + ' -Dsonar.projectKey=' + env.JOB_NAME + ' -Dsonar.java.binaries=./yueyang-modules/' + env.program_name + '/target'echo 'scriptContent: ' + scriptContentenv.program_dir_path= 'yueyang-modules/' + env.program_nameecho 'env.program_dir_path: ' + env.program_dir_pathif(sh(script: scriptContent, returnStatus: true) != 0) {error '代码检查失败!'} else {echo '代码检查成功!'}} else {// 代码检查失败error '代码检查失败, 项目名称不存在!'}}