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 any
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']])
}
}
}
}
4、配置项目变量
1、配置tag
2、配置选项参数
配置完成后,构建页面如下图所示:
2、通过maven进行打包
1、配置jenkinsfile
pipeline {
// 指定任务在哪个集群节点中执行
agent any
tools {
// 指定要使用的 Maven 版本,需要配置maven
maven '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-ui
cd yueyang-ui
rm -rf node_modules/
npm cache clean --force
npm install --registry=https://registry.npmmirror.com --unsafe-perm
npm 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:qgh
container_name: jenkins
ports:
- 8080:8080
- 50000:50000
volumes:
- ./data1/:/var/jenkins_home/
- /etc/localtime:/etc/localtime
networks:
- my_cloud_network
db:
image: postgres
container_name: db
ports:
- 5432:5432
networks:
- my_cloud_network
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
sonarqube:
image: sonarqube:8.9.6-community
container_name: sonarqube
depends_on:
- db
ports:
- "9000:9000"
networks:
- my_cloud_network
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
networks:
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 版本,需要配置maven
maven '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-ui
cd yueyang-ui
rm -rf node_modules/
npm cache clean --force
npm install --registry=https://registry.npmmirror.com --unsafe-perm
npm 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_name
if (env.program_name == 'yueyang-gateway' || env.program_name == 'yueyang-auth') {
echo 'scriptContent: ' + scriptContent
echo 'env.program_dir_path: ' + env.program_dir_path
if(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: ' + scriptContent
env.program_dir_path= 'yueyang-modules/' + env.program_name
echo 'env.program_dir_path: ' + env.program_dir_path
if(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 版本,需要配置jdk
jdk 'java_home' // 替换为你的自定义JDK名称或者路径
// 指定要使用的 Maven 版本,需要配置maven
maven 'maven_home'
// 替换为你配置的 Maven 版本,需要安装nodejs插件
nodejs 'node_home'
}
........
stage('通过Docker制作自定义镜像') {
steps {
script {
if (env.program_name == 'yueyang-ui') {
sh '''
rm -rf ./docker/yueyang-ui/dist
mv ./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 prune
docker 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/dist
mv ./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 -f
docker 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-ui
cd yueyang-ui
rm -rf node_modules/
npm cache clean --force
npm install --registry=https://registry.npmmirror.com --unsafe-perm
npm 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_name
if (env.program_name == 'yueyang-gateway' || env.program_name == 'yueyang-auth') {
echo 'scriptContent: ' + scriptContent
echo 'env.program_dir_path: ' + env.program_dir_path
if(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: ' + scriptContent
env.program_dir_path= 'yueyang-modules/' + env.program_name
echo 'env.program_dir_path: ' + env.program_dir_path
if(sh(script: scriptContent, returnStatus: true) != 0) {
error '代码检查失败!'
} else {
echo '代码检查成功!'
}
} else {
// 代码检查失败
error '代码检查失败, 项目名称不存在!'
}
}