【k8s】Jenkins实现Java springboot应用CI、CD实践 【二】

news2024/11/24 20:47:23

一、运行Jenkins流水线流程思路:

场景1:常规java应用,使用jenkins pipeline 交付到Kubernetes集群中

1、准备好java代码、Dockerfile、 deploy. yaml资源清单文件

CI阶段:
1、获取代码
2、漏洞扫描
3、检测漏洞扫描结果,如果正常则继续、否则就终止
4、使用maven进行编译,打包
5、制作Docker镜像、推送到Harbor仓库
6、交付应用到K8S


CD阶段:
1、获取完整的镜像名称;从Harbor中获取 (curl命令去获取)
2、将完整的镜像名称替换到deploy.yaml这个资源清单中;
3、直接部署到K8S的生产环境名称空间;
4、询问是否需要回退;

二 - java代码提交

1、下载代码

代码地址: https://gitee.com/oldxuedu/springboot-helloworld
wget https://gitee.com/oldxuedu/springboot-helloworld/repository/blazearchive/master.zip

做域名解析 如 10.240.0.201  gitlab.oldxu.net

在这里插入图片描述

2、创建新仓库,推送到gitlab仓库
在这里插入图片描述
在这里插入图片描述

[root@master01 springboot-CICD]# cd springboot-helloworld-master/
[root@master01 springboot-helloworld-master]# 
[root@master01 springboot-helloworld-master]# ls
deploy.yaml  Dockerfile  entrypoint.sh  pom.xml  push_jar.sh  README.md  src


git init
git add remote origin http://gitlab.oldxu.net/root/springboot.git
git add .

git config --global user.email "123456@qq.com"
git config --global user.name  "oldxu"

git commit -m "初始化"
git push -u origin master

在这里插入图片描述

deploy.yaml 需要替换的变量:
	{NameSpace}
	{Image}
	{host}

三、Pipeline流水线-获取代码

3.0 本小段流程思路:

			1、获取代码
				调用git来获取即可;   
						1、slavePod如何访问Gitlab
							1、通过gitlab的service地址去访问项目;
							2、通过Coredns配置自定义域名解析;(*本文采用该方式)
						
						2、Gitlab项目是私有的 如何处理;
							需要 在jenkins上配置好对应gitlab认证的信息;
				
				才能使用pipeline去获取代码
				  environment{
					Gitlab_Id = "gitlab-root-token"
					Gitlab_Pro = "http://gitlab.oldxu.net/root/springboot.git"
				}


				stage('获取代码') {
				  steps {
					container('maven') {
					  checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: "${Gitlab_Id}", url: "${Gitlab_Pro}"]]])
					}
				  }
				}

3.1 修改coredns

#过Coredns配置自定义域名解析;

kubectl edit configmap -n kube-system coredns

根据实际情况加上:
 hosts {
          192.168.79.31 gitlab.oldxu.net 
          192.168.79.32 gitlab.oldxu.net 
          192.168.79.33 gitlab.oldxu.net
          fallthrough  
}

在这里插入图片描述
在这里插入图片描述

3.2 Jenkins -> 系统管理 -> 全局凭据 -> New credentials

将gitlab的登录信息添加
http://jenkins.oldxu.net:30080/manage/credentials/store/system/domain/_/
在这里插入图片描述

3.3 Jenkins -> 流水线语法 -> 生成对应的gitlab下拉项目的代码

选中checkout from version control
在这里插入图片描述
在这里插入图片描述

checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: 'gitlab-root-token', url: 'http://gitlab.oldxu.net:30080/root/springboot.git']])

3.4 编写对应pipeline代码:

主要看environment和stage的 ,

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 end
  }//agent end
  
environment{
    Gitlab_Id="gitlab-root-token"
    Gitlab_Pro="http://gitlab.oldxu.net:30080/root/springboot.git"
}

  stages{
    stage('获取代码'){
        steps{
            container('maven'){
                checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: "${Gitlab_Id}", url: "${Gitlab_Pro}"]])
                sh 'pwd && ls -l'
            }
        
        }
    }
    
    stage('docker'){
        steps{
            container('docker'){
               sh 'docker ps'
            }
                
        }          
    }
        
 
  }//stages end
} //pipeline end

结果:
在这里插入图片描述

四、Pipeline流水线-漏洞扫描

4.0 本小段流程思路(1、漏洞扫描 sonarqube来实现):

				1、dns解析,slavePod需要访问sonarqube服务端;<--> jenkins  
				2、让Jenkins集成Sonarqube  ???why		sqa_01d17b84079611472bbfcf89f2a67e7556510fda
				3、sonar-scanner客户端工具; (获取这个工具的实现方式以及实现参数等等)
				4、编写Stage;

4.1 修改coredns

kubectl edit cm -n kube-system coredns

 hosts {
          192.168.79.31 gitlab.oldxu.net sonar.oldxu.net jenkins.oldxu.net
          192.168.79.32 gitlab.oldxu.net sonar.oldxu.net jenkins.oldxu.net
          192.168.79.33 gitlab.oldxu.net sonar.oldxu.net jenkins.oldxu.net
          fallthrough  
}

4.2 Jenkins集成Sonarqube

Sonarqube申请令牌 (http://sonar.oldxu.net:30080/account/security)
我的账号 -> 安全 -> 添加令牌
在这里插入图片描述
在这里插入图片描述

系统管理 -> 系统配置 -> Sonarqube
添加凭证:

在这里插入图片描述
sonarqube servers的配置:
在这里插入图片描述

4.3 sonar-scanner客户端工具

打开sonarqube网页, 项目 -> 手工
在这里插入图片描述
“分析你的项目”

#这个指令是要去到 代码路径上执行/分析
sonar-scanner \
  -Dsonar.projectKey=springboot \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://sonar.oldxu.net:30080 \
  -Dsonar.login=sqa_62e525a80cecb1a6d0ebe0cafcd52c41b0e5729c

代码路径指的是:
在这里插入图片描述
在这里插入图片描述

4.4、编写Stage;

//这里与上面给复制的代码还是有几处不一样的。
    stage('代码扫描'){
        steps{
            withSonarQubeEnv('sonar-k8s'){  //对应配置中的 sonorqube servers
                container('sonar'){
                    sh 'pwd && ls -l'
                    sh 'sonar-scanner \
                        -Dsonar.projectKey=springboot \
                        -Dsonar.java.binaries=src \
                        -Dsonar.sources=.'
                }
            }
          
        }
    }

检测漏洞扫描结果,如果正常则继续、否则就终止

1、配置Sonarqube,让其将结果通知给Jenkins
						http://admin:admin123@jenkins.oldxu.net/sonarqube-webhook
						
2、编写Stage,判断Sonarqube返回的检查结果,如果ok,则继续,否则就终止步骤的执行;

http://sonar.oldxu.net:30080/admin/webhooks
sonarqube网页 -> 配置 -> 网络调用 -> 创建

名称:jenkins
URL:http://admin:admin12345@jenkins.oldxu.net:30080/sonarqube-webhook
#注意要写对URL ,不然会一直卡5分钟,然后暂停检测

在这里插入图片描述
流水线语法:waitForQualityGate
在这里插入图片描述
可根据具体情况调整“质量阈”的条件指标
在这里插入图片描述
代码:

stage('检查漏洞扫描结果'){
        steps{
            container('sonar'){
                script{
                    timeout(5){
                        def qg = waitForQualityGate()
                        if (qg.status != 'OK'){
                            error "Sonarqube 代码检查失败, error的原因 ${qg.status}"
                        }
                    }
                }
            }
        }
    }

运行结果:
在这里插入图片描述

五、Pipeline流水线-代码编译

5.0 使用maven进行编译,打包

    stage('编译代码'){
        steps{
            container('maven'){
                sh 'mvn package -Dmaven.test.skip=true'
                sh 'pwd && ls -l'
            }
        }
    
    }
        

在这里插入图片描述

六、Pipeline流水线-制作Docker镜像

6.0 本小段思路

制作Docker镜像、推送到Harbor仓库  (Dockerfile文件)
				1、配置域名解析,让SlavePod能够访问到Harbor
				2、配置凭据,确保后续在推送到Harbor仓库时,认证没有问题;
				
				3、docker build  根据dockerfilee生成Docker的镜像
				4、推送到Harbor仓库

在这里插入图片描述

6.1、配置域名解析,让SlavePod能够访问到Harbor

kubectl edit cm -n kube-system coredns
加上 192.168.79.34 harbor.oldxu.net

6.2、配置凭据,确保后续在推送到Harbor仓库时,认证没有问题;

http://jenkins.oldxu.net:30080/manage/credentials/store/system/domain/_/
Dashboard -> 系统管理 -> 凭据 -> 系统 -> 全局凭据 (unrestricted)
在这里插入图片描述
在这里插入图片描述

6.3 编写stage

3、docker build  根据dockerfilee生成Docker的镜像
4、推送到Harbor仓库

流水线语法: 加载刚才创建的harbor-auth用户名和密码
withCredentials: Bind credentials to variables -> Username and password (separated)
在这里插入图片描述

[root@master01 springboot-helloworld-master]# ls
deploy.yaml  Dockerfile  entrypoint.sh  pom.xml  push_jar.sh  README.md  src
[root@master01 springboot-helloworld-master]# git log -n1 --pretty=format:'%h'
4131cad

编写生成tag的流水线语法
在这里插入图片描述

sh returnStdout: true, script: '''git log -n1 --pretty=format:\'%h\'
#sh(returnStdout: true, script: "git log -n1 --pretty=format:'%h'").trim()

sh returnStdout: true, script: '''date +%Y%m%d_%H%M%S
#sh(returnStdout: true, script: "date +%Y%m%d_%H%M%S").trim()

//注意单引号和双引号的使用

environment{
    Gitlab_Id="gitlab-root-token"
    Gitlab_Pro="http://gitlab.oldxu.net:30080/root/springboot.git"
    
    //harbor相关的全局变量
    Url = "harbor.oldxu.net"
    Pro = "base"
    ImageName = "${Url}/${Pro}/springboot"
    HARBOR_ID = "harbor-auth"
}//environment end

stage('生成镜像Tag'){
        steps{
            container('maven'){
                script{
                    //本次git提交的commid  (git log -n1 --pretty=format:'%h')
                    env.COMMITID = sh(returnStdout: true, script: "git log -n1 --pretty=format:'%h'").trim()
                    //构件时间
                    env.BuildTime = sh(returnStdout: true, script: "date +%Y%m%d_%H%M%S").trim()
                    //完整的镜像Tag (c106654_20221115_133911)
                    env.ImageTag = COMMITID + "_" BuildTime
                }
                
                sh 'echo "镜像的Tag: ${ImageTag}"'
            }
        }
    }

    stage('制作docker镜像'){
        steps{
          container('docker'){
            withCredentials([usernamePassword(credentialsId: "${HARBOR_ID}", passwordVariable: 'HARBOR_PASSWORD', usernameVariable: 'HARBOR_USER')]) {
                //登陆harbor
                sh 'echo "${HARBOR_PASSWORD}" | docker login ${Url} -u "${HARBOR_USER}" --password-stdin '
                
                // 构建 / 推送  / 删除本地镜像
                sh 'docker build -t ${ImageName}:${ImageTag} .'
                sh 'docker push ${ImageName}:${ImageTag}'
                sh 'docker rmi ${ImageName}:${ImageTag}'
            }
          }
         }
    }


运行效果:
在这里插入图片描述

七、Pipeline流水线-交付应用至K8S

7.0 本小段思路

				1、将应用交付到哪个K8S集群;  (slavepod能够与对应的集群通信就行)
				2、如何连接上对应的K8S集群;
				
				
				
				1、配置Jenkins,将config文件制作为一个Scretfile;
				2、编写Stage,在Stage引用这个config文件; 就可以操作对应的集群了;
					{namespace}
					{Image}
					{host}

		
				3、部署的名称空间需要提前创建  (k8s namespace dev)
				4、需要创建对应的Harbor认证Secrets harbor-admin  (k8s的kubectl create secret docker-registry harbor-admin )

deploy.yaml内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-dev
  namespace: {namespace}			#修改为{}特殊字符,后期好替换
spec:
  replicas: 3
  selector:
    matchLabels:
      app: spring-dev
  template:
    metadata:
      labels:
        app: spring-dev
    spec:
      imagePullSecrets:
      - name: harbor-admin
      containers:
      - name: springboot-dev
        image: {Image}			# 修改为{}特殊字符,后期好替换
        ports:
        - name: http
          containerPort: 8080
        env:            # 传递初始堆内存和最大堆内存占用
        - name: XMS_OPTS
          valueFrom:
            resourceFieldRef:
              resource: requests.memory
        - name: XMX_OPTS
          valueFrom:
            resourceFieldRef:
              resource: limits.memory
        resources:
          requests:
            memory: 150Mi
          limits:
            memory: 300Mi
        readinessProbe:         # 就绪探针;如果端口不存活,则从负载均衡中移除
          tcpSocket:
            port: http          # http是一个名字;它会获取这个名字对应的端口;
          initialDelaySeconds: 10
          failureThreshold: 3
        livenessProbe:          # 存活探针;获取url,状态码不对那么则触发重启操作
          httpGet:
            path: /
            port: http
          initialDelaySeconds: 10
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: spring-dev-svc
  namespace: {namespace}
spec:
  selector:
    app: spring-dev
  ports:
  - port: 8080
    targetPort: 8080

---
#apiVersion: networking.k8s.io/v1
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: springboot-ingress
  namespace: {namespace}
spec:
  ingressClassName: "nginx"
  rules:
  - host: "{host}"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          serviceName: spring-dev-svc
          servicePort: 8080
          #service:
          #  name: spring-dev-svc
          #  port:
          #    number: 8080

7.1 配置Jenkins,将config文件制作为一个Scret file;

#master节点,下载config文件
sz ~/.kube/config

Jenkins新增凭证(secret file)
http://jenkins.oldxu.net:30080/manage/credentials/store/system/domain/_/
在这里插入图片描述
流水线语法:
在这里插入图片描述

withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
    // some block
}

7.2 编写pipeline

environment{
   
    //对外暴露的域名
    Ingress_Host = "spring-dev.oldxu.net"
}//environment end

    stage('交付至k8s'){
        steps{
            container('kubectl'){
                withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
                    sh 'mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config'
                                     
                    //替换
                    sh 'sed  -i "s#{namespace}#dev#g" deploy.yaml'
                    sh 'sed  -i "s#{Image}#${ImageName}:${ImageTag}#g" deploy.yaml'
                    sh 'sed  -i "s#{host}#${Ingress_Host}#g" deploy.yaml'
                    sh 'cat deploy.yaml'
                    
                    sh 'kubectl apply -f deploy.yaml'
                }
            }
        }
    }

运行结果:

在这里插入图片描述
网页访问:
在这里插入图片描述

更新代码:验证再次发版:

修改代码的HomeController.java内容。
在这里插入图片描述

八、Pipeline流水线-全自动CI过程及测试

Jenkins的pipeline配置 -> 构建触发器 -> 勾上“build when a change …” ,生成secret令牌
在这里插入图片描述
高级
在这里插入图片描述

gitlab配置 开启外发请求
菜单 -> 管理员 -> 管理中心 -> 设置 -> 网络 -> 外发请求 -> 勾上两个“允许”
http://gitlab.oldxu.net:30080/admin/application_settings/network
在这里插入图片描述
springboot项目 -> 设置 -> webhook
参考地址:http://gitlab.oldxu.net:30080/root/springboot/-/hooks
在这里插入图片描述
可测试
在这里插入图片描述
在这里插入图片描述

更新代码,看看会不会触发自动发版CI
在这里插入图片描述

springboot-CI完整的pipeline代码

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 end
  }//agent end
  
environment{
    Gitlab_Id="gitlab-root-token"
    Gitlab_Pro="http://gitlab.oldxu.net:30080/root/springboot.git"
    
    //harbor相关的全局变量
    Url = "harbor.oldxu.net"
    Pro = "base"
    ImageName = "${Url}/${Pro}/springboot"
    HARBOR_ID = "harbor-auth"
    
    //对外暴露的域名
    Ingress_Host = "spring-dev.oldxu.net"
}//environment end

  stages{
    stage('获取代码'){
        steps{
            container('maven'){
                checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: "${Gitlab_Id}", url: "${Gitlab_Pro}"]])
                sh 'pwd && ls -l'
            }
        
        }
    }
    
    stage('代码扫描'){
        steps{
            withSonarQubeEnv('sonar-k8s'){  //对应配置中的 sonorqube servers
                container('sonar'){
                    sh 'pwd && ls -l'
                    sh 'sonar-scanner \
                        -Dsonar.projectKey=springboot \
                        -Dsonar.java.binaries=src \
                        -Dsonar.sources=.'
                }
            }
            
        }
    }
    
    stage('检查漏洞扫描结果'){
        steps{
            container('sonar'){
                script{
                    timeout(5){
                        def qg = waitForQualityGate()
                        if (qg.status != 'OK'){
                            error "Sonarqube 代码检查失败, error的原因 ${qg.status}"
                        }
                    }
                }
            }
        }
    }
    
    stage('编译代码'){
        steps{
            container('maven'){
                sh 'mvn package -Dmaven.test.skip=true'
                sh 'pwd && ls -l'
            }
        }
    }
    
    stage('生成镜像Tag'){
        steps{
            container('maven'){
                script{
                    //本次git提交的commid  (git log -n1 --pretty=format:'%h')
                    env.COMMITID = sh(returnStdout: true, script: "git log -n1 --pretty=format:'%h'").trim()
                    //构件时间
                    env.BuildTime = sh(returnStdout: true, script: "date +%Y%m%d_%H%M%S").trim()
                    //完整的镜像Tag (c106654_20221115_133911)
                    env.ImageTag = COMMITID + "_" + BuildTime
                }
                
                sh 'echo "镜像的Tag: ${ImageTag}"'
            }
        }
    }
    
    stage('制作docker镜像'){
        steps{
          container('docker'){
            withCredentials([usernamePassword(credentialsId: "${HARBOR_ID}", passwordVariable: 'HARBOR_PASSWORD', usernameVariable: 'HARBOR_USER')]) {
                //登陆harbor
                sh 'echo "${HARBOR_PASSWORD}" | docker login ${Url} -u "${HARBOR_USER}" --password-stdin '
                
                // 构建 / 推送  / 删除本地镜像
                sh 'docker build -t ${ImageName}:${ImageTag} .'
                sh 'docker push ${ImageName}:${ImageTag}'
                sh 'docker rmi ${ImageName}:${ImageTag}'
            }
          }
         }
    }
    
    stage('交付至k8s'){
        steps{
            container('kubectl'){
                withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
                    sh 'mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config'
                    
                    //替换
                    sh 'sed  -i "s#{namespace}#dev#g" deploy.yaml'
                    sh 'sed  -i "s#{Image}#${ImageName}:${ImageTag}#g" deploy.yaml'
                    sh 'sed  -i "s#{host}#${Ingress_Host}#g" deploy.yaml'
                    sh 'cat deploy.yaml'
                    
                    sh 'kubectl apply -f deploy.yaml'
                }
            }
        }
    }
        
 
  }//stages end
} //pipeline end

九、PipelineCD流水线-获取Harbor镜像Tag

9.0 CD阶段的思路

CD阶段:
			1、获取完整的镜像名称;   从Harbor中获取  (curl命令去获取)
			
				shell命令写出来;
				curl -s -uadmin:Harbor12345 -H'Content-Type: application/json' -X GET https://harbor.oldxu.net/v2/base/springboot/tags/list | sed -r 's#(\{.*\[)(.*)(\]\})#\2#g' | xargs -d "," -n1 | xargs -n1 | sort -t "_" -k2 -k3 -nr | head -5

				级联变量的方式来提取对应的tag;
					
					三个变量:
						Harbor_Url
						Harbor_Pro
						Image_Name
						Image_Tag
						
				def get_tag = [ "bash", "-c", "curl -s -uadmin:Harbor12345 -H 'Content-Type: application/json' -X GET https://${Harbor_Url}/v2/${Harbor_Pro}/${Image_Name}/tags/list | sed -r 's#(\\{.*\\[)(.*)(\\]\\})#\\2#g' | xargs -d ',' -n1 | xargs -n1 | sort -t '_' -k2 -k3 -nr | head -5"]

				return get_tag.execute().text.tokenize("\n")

			
			
			2、生产环境中已经是部署了对应的项目的;
			2、kubectl set image;
			3、直接部署到K8S的生产环境名称空间;
			4、询问是否需要回退;
				kubectl rollout undo deployment springboot -n prod

9.1 操作过程

安装active choices插件。 新建springboot-CD流水线,使用参数化构建过程

参数化构建过程
#1 Harbor_Url
添加参数 -> 选Active Choices Parameter
Name 填 Harbor_Url
Script -> Groovy Script 填 return ["harbor.oldxu.net","harbor-dev.oldxu.net","harbor-prod.oldxu.net"]

#2 Harbor_Pro
添加参数 -> 选Active Choices Parameter
Name 填 Harbor_Pro
Script -> Groovy Script 填 return ["base","app","springcloud","ops"]

#3 Image_Name 
添加参数 -> 选Active Choices Parameter
Name 填 Image_Name 
Script -> Groovy Script 填 return ["springboot","java","springcloud","shopping"]

在这里插入图片描述

#4 Image_Tag
添加参数 -> 选 Active Choices Reactive Parameter

Groovy Script填写:
def get_tag = [ "bash", "-c", "curl -s -uadmin:Harbor12345 -H 'Content-Type: application/json' -X GET https://${Harbor_Url}/v2/${Harbor_Pro}/${Image_Name}/tags/list | sed -r 's#(\\{.*\\[)(.*)(\\]\\})#\\2#g' | xargs -d ',' -n1 | xargs -n1 | sort -t '_' -k2 -k3 -nr | head -5"]
return get_tag.execute().text.tokenize("\n")

#
Referenced parameters框填写:Harbor_Url,Harbor_Pro,Image_Name 

在这里插入图片描述

build with parameters效果

在这里插入图片描述

编写CD - pipeline

pipeline{
    agent{
        kubernetes{
            cloud 'kubernetes'
            yaml '''
              apiVersion: v1
              kind: Pod
              spec:
                imagePullSecrets:
                - name: harbor-admin
                containers:
                - name: kubectl
                  image: harbor.oldxu.net/ops/kubectl:1.18.0
                  imagePullPolicy: IfNotPresent
                  command: ["cat"]
                  tty: true
            '''
        }
    }
    
    environment{
        Full_Image = "${Harbor_Url}/${Harbor_Pro}/${Image_Name}:${Image_Tag}"
    }//environment end
    
    stages{
        stage('输出完整的镜像名称'){
            steps{
                sh 'echo 镜像名称-tag: ${Full_Image}'
            }
            
        }
    }
    
}//pipeline end

在这里插入图片描述

十、PipelineCD流水线-部署应用至K8S生产环境

kubectl create namespace prod
kubectl create secret docker-registry harbor-admin --docker-username=admin --docker-password=Harbor12345 --docker-server=harbor.oldxu.net -n prod

先在生产环境部署 deploy-prod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot
  namespace: prod			#修改为{}特殊字符,后期好替换
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-prod
  template:
    metadata:
      labels:
        app: spring-prod
    spec:
      imagePullSecrets:
      - name: harbor-admin
      containers:
#      - name: springboot-prod   
      - name: springboot    #注意这里的名字,要与 kubectl set images的一致
        image: harbor.oldxu.net/base/springboot:fa71353_20230521_175420			# 修改为{}特殊字符,后期好替换
        ports:
        - name: http
          containerPort: 8080
        env:            # 传递初始堆内存和最大堆内存占用
        - name: XMS_OPTS
          valueFrom:
            resourceFieldRef:
              resource: requests.memory
        - name: XMX_OPTS
          valueFrom:
            resourceFieldRef:
              resource: limits.memory
        resources:
          requests:
            memory: 150Mi
          limits:
            memory: 300Mi
        readinessProbe:         # 就绪探针;如果端口不存活,则从负载均衡中移除
          tcpSocket:
            port: http          # http是一个名字;它会获取这个名字对应的端口;
          initialDelaySeconds: 10
          failureThreshold: 3
        livenessProbe:          # 存活探针;获取url,状态码不对那么则触发重启操作
          httpGet:
            path: /
            port: http
          initialDelaySeconds: 10
          failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: spring-prod-svc
  namespace: prod
spec:
  selector:
    app: spring-prod
  ports:
  - port: 8080
    targetPort: 8080
---
#apiVersion: networking.k8s.io/v1
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: springboot-ingress
  namespace: prod
spec:
  ingressClassName: "nginx"
  rules:
  - host: "spring-prod.oldxu.net"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          serviceName: spring-prod-svc
          servicePort: 8080
          #service:
          #  name: spring-prod-svc
          #  port:
          #    number: 8080

在这里插入图片描述
如果dev环境没问题,则手动发布到prod环境
在这里插入图片描述
构建:
在这里插入图片描述
在这里插入图片描述

+ kubectl set image deployment/springboot springboot=harbor.oldxu.net/base/springboot:ccf31a9_20230521_213116 -n prod

9.2 对应pipeline代码:

 stage('部署应用至生产 K8S'){
            steps{
                withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
                    container('kubectl'){
                        sh 'mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config'
                        sh 'kubectl set image deployment/${Image_Name} ${Image_Name}=${Full_Image} -n prod'
                    }
                }
    
            
            }
        }

十一、PipelineCD流水线-应用回滚

	4、询问是否需要回退;
				kubectl rollout undo deployment springboot -n prod

流水线语法:

input message: '是否回退到上个版本', parameters: [choice(choices: ['No', 'Yes'], name: 'rollback')]

在这里插入图片描述
验证:发布与回滚
在这里插入图片描述
选择yes ,回滚
在这里插入图片描述

+ kubectl rollout undo deployment springboot -n prod

在这里插入图片描述

springboot-CD的完整代码

pipeline{
    agent{
        kubernetes{
            cloud 'kubernetes'
            yaml '''
              apiVersion: v1
              kind: Pod
              spec:
                imagePullSecrets:
                - name: harbor-admin
                containers:
                - name: kubectl
                  image: harbor.oldxu.net/ops/kubectl:1.18.0
                  imagePullPolicy: IfNotPresent
                  command: ["cat"]
                  tty: true
            '''
        }
    }
    
    environment{
        Full_Image = "${Harbor_Url}/${Harbor_Pro}/${Image_Name}:${Image_Tag}"
       
    }//environment end
    
    stages{
        stage('输出完整的镜像名称'){
            steps{
                sh 'echo 镜像名称-tag: ${Full_Image}'
           

            }
            
        }
        
        stage('部署应用至生产 K8S'){
            steps{
                withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
                    container('kubectl'){
                        sh 'mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config'
                        sh 'kubectl set image deployment/${Image_Name} ${Image_Name}=${Full_Image} -n prod'
                    }
                }
    
            
            }
        }
        
        stage('快速回滚'){
            steps{
              withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')]) {
                container('kubectl'){
                    script{
                        timeout(time: 1, unit: 'HOURS'){
                            def UserInput = input message: '是否回退到上个版本', parameters: [choice(choices: ['No', 'Yes'], name: 'rollback')]
                            if (UserInput == "Yes"){
                               sh 'mkdir -p ~/.kube && cp ${KUBECONFIG} ~/.kube/config'
                               sh 'kubectl rollout undo deployment $Image_Name -n prod'
 
                            }
                            
                        }
                    }
                }
              }

            }
        }
        
    }//stages end
       
}//pipeline end

END 5.8~5.21 ELK+CICD

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/555312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenAI ChatGPT3.5-turbo实际解决问题能力评测

OpenAI ChatGPT3.5-turbo实际解决问题能力评测 ​ 程序员在coding的时候会经常遇到需要查阅资料的情况&#xff0c;最好的结果是直接能拿到一份好用的demo版本code&#xff0c;本次我们来评测&#xff1a;bing搜索和chatGPT3.5&#xff0c;解决实际问题&#xff1a;“html 图片…

【Proteus仿真】51单片机矩阵按键+中断+数码管显示+串口输出

【Proteus仿真】51单片机矩阵按键中断数码管显示串口输出 &#x1f4cc;相关篇《【Proteus仿真】51单片机矩阵按键扫描外部中断使用》&#x1f4cd;《【Proteus仿真】51单片机串口输出实验》&#x1f388; 《【Proteus仿真】51单片机定时器计数共阴数码管驱动显示》 &#x1f5…

PMP-敏捷管理知识总结

敏捷管理 敏捷管理 01敏捷开发是一种以人为核心、迭代、循序渐进的开发方法&#xff0c;在敏捷开发中&#xff0c;项目的构建被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备集成和可运行的特征 。 敏捷项目管理简化了繁琐的流程和文档管理&…

考研考公太卷了,出国留学能弯道超车吗?

这届年轻人太难了&#xff01; 国内高考人数越来越多&#xff0c;考上好大学的难度很大。2022年&#xff0c;高考报名人数是1193万&#xff0c;但考上本科的只有466万&#xff0c;考上双一流大学的不足50万&#xff0c;上双一流大学考生的比例不到5%。 高考只是卷的开始&…

软件代码设计-小优化(五)

产品需求&#xff1a; 按照天统计策略信收信人数和收信次数。以前策略信只有发送是没有收集的&#xff0c;现在要数据咋办&#xff0c;得收集啊。 设计方案&#xff1a; 因为策略信的发送是在一个单独的工程里&#xff0c;没有连接数据库。于是收集策略信放到了redis的list里&a…

第03章 流程控制语句

流程控制语句是用来控制程序中各语句执行顺序的语句&#xff0c;可以把语句组合成能完成一定功能的小逻辑模块。 程序设计中规定的三种流程结构&#xff0c;即&#xff1a; 顺序结构 程序从上到下逐行地执行&#xff0c;中间没有任何判断和跳转。 分支结构 根据条件&#xff0…

软件测试理论----测试设计方法论

1、测试用例格式 &#xff08;1&#xff09;用例编号&#xff1a;用例的唯一标识&#xff0c;要求具有易识别性和易维护性&#xff0c;能能够根据用例编号识别用例的目的和作用&#xff0c;一般格式为&#xff1a;A-B-C-D 其中 A&#xff1a;一般表示产品或者项目名称B&#…

Linux的启动流程

文章目录 Linux的启动流程BIOS、boot loader与kernel加载BIOSboot loader加载内核检测硬件与 initramfs 的功能 Linux的启动流程 本文章参考&#xff1a; [Uncertainty!!]的Linux的启动流程 Linux的启动流程是一个非常复杂的过程&#xff0c;下面是对Linux启动流程的详细分析&a…

JDBC-Java与数据库之间的桥梁

1、JDBC 1.1、数据的持久化 持久化(persistence)&#xff1a;把数据保存到可掉电式存储设备中以供之后使用。大多数情况下&#xff0c;特别是企业级应用&#xff0c; 数据持久化意味着将内存中的数据保存到硬盘上加以”固化”&#xff0c;而持久化的实现过程大多通过各种关系数…

IO流详解

IO流 1. 文件 1.1 什么是文件 文件对大家来说都不陌生&#xff1a; 文件是保存数据的地方&#xff0c;它可以保存文字、图片、视频等等例如大家平时使用的word文档、Excel文档、PPT文档等都是文件 1.2 文件流 文件在程序中是以流的形式来操作的流是指数据在数据源&#x…

mydumper - 备份恢复工具

文章目录 介绍部署安装功能 参数详解mydumpermyloader配置文件 实际示例操作性能验证 补充definerlock 总结相关链接 介绍 部署安装 # 当前最新 release wget https://github.com/mydumper/mydumper/releases/download/v0.14.4-8/mydumper-0.14.4-8.el7.x86_64.rpm# 安装 rpm…

Linux 之 firewalld 防火墙

目录 firewalld概述firewalld 与 iptables 的区别&#xff1a;firewalld 区域的概念firewalld防火墙预定义了9个区域:firewalld 数据处理的流程 firewalld防火墙的配置方法&#xff1a;永久保存配置 firewalld概述 firewalld防火墙是Centos7系统默认的防火墙管理工具&#xff…

数据分析与预处理常用的图和代码

1.训练集和测试集统计数据描述之间的差异作图&#xff1a; def diff_color(x):color red if x<0 else (green if x > 0 else black)return fcolor: {color}(train.describe() - test.describe())[features].T.iloc[:,1:].style\.bar(subset[mean, std], alignmid, colo…

国内做校园信息化的龙头企业公司有哪些?

随着数字化转型的加速&#xff0c;越来越多的学校开始寻求校园信息化的解决方案&#xff0c;相比于传统信息化模式&#xff0c;国内有哪些做校园信息化做得比较好的企业&#xff1f;他们采用的又是什么样的方式&#xff1f; 一文带你了解&#xff0c;零代码平台搭建校园信息化…

Android 14 又来了?别扶!抬起我来吧!

Android 14 又来了&#xff1f;别扶&#xff01;抬起我来吧&#xff01; 大家好&#xff0c;好久不见&#xff0c;从去年底写完年终总结之后就再也没有更新过文章&#xff0c;之前最多也就间隔一两个月时间&#xff0c;但这回间隔时间确实有点长&#xff0c;基本快半年了&…

每日一练 | 网络工程师软考真题 Day7

1、如果希望别的计算机不能通过ping命令测试效劳器的连通情况&#xff0c;可以 &#xff08;1&#xff09; 。如果希望通过默认的Telnet端口连接效劳器&#xff0c;那么下面对防火墙配置正确的选项是 &#xff08;2&#xff09; 。 &#xff08;1&#xff09; A&#xff0…

为什么说2023年是学华为认证的最佳时机?学华为认证有什么优势?

华为认证数通方向2016年以前叫数通&#xff0c;2017年开始改为R&S&#xff08;路由交换&#xff09;&#xff0c;2021年正式升级为Datacom。 新版数通认证更聚焦于技术在现实工作场景中的应用&#xff0c;并融入了大量新技术新应用&#xff0c;实用价值更高。 通过系统学…

用java带你了解IO模型

目录 1.BIO1.1 简述1.2 代码示例1.3优点和缺点1.4 思考 2. NoBlockingIO2.1 简述2.2 代码示例2.3 优点和缺点2.4 思考 3. NIO&#xff08;NewIO&#xff09;3.1 简述3.2 代码示例3.3 优点和缺点3.3 思考 4. 扩展select/poll、epoll4.1 简述4.2 select/poll4.3 epoll4.4 扩展话题…

设计模式之【备忘录模式】,“后悔药”是可以有的

文章目录 一、什么是备忘录模式1、备忘录模式使用场景2、备忘录模式优缺点3、备忘录模式的三大角色4、白箱备忘录和黑箱备忘录5、思考&#xff1a;备份频率快&#xff0c;备份对象大的备忘录应该如何设计 二、实例1、备忘录模式的一般写法2、使用栈管理富文本编辑器3、游戏状态…

【Linux】shell编程—sed编辑器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、sed编辑器1.sed工作流程2.sed工作场景3.sed常用选项 二、sed编辑器基本用法1.打印操作2.打印行号3.增加操作4.插入操作5.替换操作7.字符转换 一、sed编辑器 sed…