一、运行Jenkins流水线流程思路:
场景:java微服务应用, 单体仓库,多个微服务模块,(并行构建、自动化构建、根据模块变更仅更新特定模块) java、nodejs
CI阶段 并行方式; 根据模块变更仅更新特定模块
1、准备项日;
目录结构 (源代码 、dockerfile 、deploy.yaml资源清单文件)
2、下载代码
3、漏洞检测;
4、项目编译;
5、镜像制作;
6、部署测试环境;
CD阶段:
1、拉取harbor中的镜像;
2、交付到生产环境;
3、添加回退阶段;
二、部署springcloud 若依项目
本文不做详细的部署细节,可参考以前的写的: https://blog.csdn.net/Nightwish5/article/details/130308650
1、准备项目;
目录结构 (源代码、Dockerfile、deploy.yaml资源清单文件)
deploy.yaml中要替换的变量:
{namespace}
{image}
ui {host}
monitor {host} ingress
前置条件:
1、harbor.oldxu.net/springcloud/skywalking-java-agent:8.8
2、依赖的MySQL、Redis、Skywalking、Nacos(配置)得有;
ruoyi-gateway-dev.yml
ruoyi-auth-dev.yml
ruoyi-monitor-dev.yml
ruoyi-system-dev.yml
1、提交代码到gitlab
2、下载代码
大致说明:
部署基础组件: ruoyi的springcloud部署顺序
1、mysql (若依项目的DB库)
2、redis
3、nacos 、 mysql(nacos依赖的库)
配置nacos中的对应的yml文件
4、sentinel
5、skywalking (oap和ui)
#part 6可以在CICD过程中部署
6、service-all
1、system-dp
2、auth-dp
3、gateway-dp
4、monitor-dp-ingress
5、ui-dp-ingress
三、将代码提交到gitlab
gitlab创建项目:RuoYiCloud
git init
git config --global user.email "123456@qq.com"
git config --global user.name "old133"
git remote add origin http://gitlab.oldxu.net:30080/root/ruoyicloud.git
git add .
git commit -m "初始化"
git checkout -b k8s
git push --set-upstream origin k8s
#方式2:
代码上传到gitee , gitlab导入项目 -> 从URL导入仓库
四、创建流水线 springcloud-ruoyi-CI
2、下载代码
3、漏洞检测;
并行;
进入到对应的微服务文件夹中;
不规则的,需要再cd进个子目录:
cd ruoyi-monitor
cd ruoyi-system
4.1 获取代码和代码扫描和漏洞扫描结果
pipeline{
agent {
kubernetes {
cloud 'kubernetes'
yaml '''
apiVersion: v1
kind: Pod
spec:
imagePullSecrets:
- name: harbor-admin
volumes:
- name: data
nfs:
server: 192.168.79.33
path: /data/maven
- name: dockersocket
hostPath:
path: /run/docker.sock
containers:
- name: maven
image: harbor.oldxu.net/ops/maven:3.8.6
imagePullPolicy: IfNotPresent
command: ["cat"]
tty: true
volumeMounts:
- name: data
mountPath: /root/.m2
- name: nodejs
image: harbor.oldxu.net/ops/nodejs:14.20
imagePullPolicy: IfNotPresent
command: ["cat"]
tty: true
- name: sonar
image: harbor.oldxu.net/ops/sonar-scanner:2.3.0
imagePullPolicy: IfNotPresent
command: ["cat"]
tty: true
- name: docker
image: harbor.oldxu.net/ops/docker:20.10
imagePullPolicy: IfNotPresent
command: ["cat"]
tty: true
volumeMounts:
- name: dockersocket
mountPath: /run/docker.sock
- name: kubectl
image: harbor.oldxu.net/ops/kubectl:1.18.0
imagePullPolicy: IfNotPresent
command: ["cat"]
tty: true
'''
} //kubernetes ned
} //agent end
environment{
Gitlab_Id = "gitlab-root-token"
Gitlab_Pro = "http://gitlab.oldxu.net:30080/root/ruoyi-cloud.git"
} //environment end
stages{
stage('获取代码'){
steps{
container('maven'){
//注意这里的分支是k8s
checkout([$class: 'GitSCM', branches: [[name: '*/k8s']], extensions: [], userRemoteConfigs: [[credentialsId: "${Gitlab_Id}", url: "${Gitlab_Pro}"]]])
sh 'pwd && ls -l'
}
}
} //获取代码 end
stage('代码扫描'){
//并行处理
parallel{
// 1 检测Gateway
stage('检测Gateway'){
environment{
AppName="ruoyi-gateway"
}
steps{
withSonarQubeEnv('sonar-k8s'){
container('sonar'){
sh ' cd $(find ./ type -d -name "${AppName}") && \
sonar-scanner \
-Dsonar.projectKey=${AppName} \
-Dsonar.java.binaries=src \
-Dsonar.sources=.'
}
}
}
}
// 2 Auth
stage('检测Auth'){
environment{
AppName="ruoyi-Auth"
}
steps{
withSonarQubeEnv('sonar-k8s'){
container('sonar'){
sh ' cd $(find ./ type -d -name "${AppName}") && \
sonar-scanner \
-Dsonar.projectKey=${AppName} \
-Dsonar.java.binaries=src \
-Dsonar.sources=.'
}
}
}
}
// 3 system
stage('检测system'){
environment{
AppName="ruoyi-system"
}
steps{
withSonarQubeEnv('sonar-k8s'){
container('sonar'){
sh ' cd $(find ./ type -d -name "${AppName}") && \
sonar-scanner \
-Dsonar.projectKey=${AppName} \
-Dsonar.java.binaries=src \
-Dsonar.sources=.'
}
}
}
}
// 4 monitor
stage('检测monitor'){
environment{
AppName="ruoyi-monitor"
}
steps{
withSonarQubeEnv('sonar-k8s'){
container('sonar'){
sh ' cd $(find ./ type -d -name "${AppName}") && \
sonar-scanner \
-Dsonar.projectKey=${AppName} \
-Dsonar.java.binaries=src \
-Dsonar.sources=.'
}
}
}
}
// 5 UI
stage('检测UI'){
environment{
AppName="ruoyi-ui"
}
steps{
withSonarQubeEnv('sonar-k8s'){
container('sonar'){
sh ' cd $(find ./ type -d -name "${AppName}") && \
sonar-scanner \
-Dsonar.projectKey=${AppName} \
-Dsonar.java.binaries=src \
-Dsonar.sources=.'
}
}
}
}
}//parallel end
} //代码扫描 stage end
stage('检查漏洞扫描结果'){
steps{
container('sonar'){
script{
timeout(5){
def qg = waitForQualityGate()
if (qg.status != 'OK'){
error "Sonarqube 代码检查失败, error的原因 ${qg.status}"
}
}
}
}
}
}//检查漏洞扫描结果 stage end
}//stages end
}//pipeline end
五、项目编译(maven和nodejs)
#思路:
也是要并行构建
Java:
找到这个微服务模块的路径 (使用刚才的find方法)
mvn package -Dmaven.test.skip=true -pl ${模块路径} -am
NodeJS:
npm install --registry=https://registry.npmmirror.com
npm run build:prod
maven编译举例:
5.1 对应的pipeline代码:
stages{
stage('代码编译'){
parallel{
// 1、编译Gateway
stage('编译Gateway'){
environment{
AppName = "ruoyi-gateway"
}
steps{
container('maven'){
sh '''
Build_Path=$(find ./ -type d -name "${AppName}")
mvn package -Dmaven.test.skip=true -pl ${Build_Path} -am
'''
}
}
}
// 2、编译Auth
stage('编译Auth'){
environment{
AppName = "ruoyi-auth"
}
steps{
container('maven'){
sh '''
Build_Path=$(find ./ -type d -name "${AppName}")
mvn package -Dmaven.test.skip=true -pl ${Build_Path} -am
'''
}
}
}
// 3、编译system
stage('编译system'){
environment{
AppName = "ruoyi-system"
}
steps{
container('maven'){
sh '''
Build_Path=$(find ./ -type d -name "${AppName}")
mvn package -Dmaven.test.skip=true -pl ${Build_Path} -am
'''
}
}
}
// 4、编译monitor
stage('编译monitor'){
environment{
AppName = "ruoyi-monitor"
}
steps{
container('maven'){
sh '''
Build_Path=$(find ./ -type d -name "${AppName}")
mvn package -Dmaven.test.skip=true -pl ${Build_Path} -am
'''
}
}
}
// 5、编译UI
stage('编译UI'){
environment{
AppName = "ruoyi-ui"
}
steps{
container('nodejs'){
sh '''
cd $(find ./ -type d -name "${AppName}") && \
npm install --registry=https://registry.npmmirror.com && \
npm run build:prod
'''
}
}
}
} // parallel end
}//代码编译 stage end
}//总stages end
运行结果:
六、制作Docker镜像
6.1 对应的pipeline代码