實(shí)踐:devops之K8s環(huán)境持續(xù)部署
目錄
推薦文章
https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩轉(zhuǎn)Typora》
1、Kubectl 發(fā)布流水線
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-X2Q6MzL1-1688896509292)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709101119001.png)]
CI流水線:
- 下載代碼
- 構(gòu)建單元測試
- 代碼掃描
- 構(gòu)建鏡像
- 更新發(fā)布文件
CD流水線:
- 輸入版本,從git下載部署文件;
- 使用kubectl發(fā)布;
- 使用kubectl回滾;
環(huán)境準(zhǔn)備
jenkins
gitlab
sonarQube
harbor
使用之前的npm項目
- 使用之前的npm項目
devops6-npm-service
如何構(gòu)建,請看npm構(gòu)建項目部分。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-r4q8SmS3-1688896509300)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230703121000171.png)]
- 新建
Dockerfile
FROM nginx:1.17.0
COPY index.html /usr/share/nginx/html/
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-lzJ028a5-1688896509300)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230703121318027.png)]
- 編輯
index.html
文件
<h1>VERSION: main</h1>
- 配置好sonar參數(shù)
創(chuàng)建sonar-project.properties
文件
# 定義唯一的關(guān)鍵字
sonar.projectKey=devops6-npm-service
# 定義項目名稱
sonar.projectName=devops6-npm-service
# 定義項目的版本信息
sonar.projectVersion=1.0
# 指定掃描代碼的目錄位置(多個逗號分隔)
sonar.sources=src
# 執(zhí)行項目編碼
sonar.sourceEncoding=UTF-8
# 指定sonar Server
sonar.host.url=http://172.29.9.101:9000
# 認(rèn)證信息
sonar.login=admin
sonar.password=Admin@123
然后提交項目代碼。
創(chuàng)建一條新pipeline
- 以原
devops6-maven-service_CI
為基礎(chǔ)拷貝一條新流水線devops6-npm-service_K8SCI
:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-5UIEyAJB-1688896509302)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230703124225860.png)]
?? 注意:但是這里的Git選項參數(shù)一直沒效果,測試不出來,很奇怪。。。因此,就直接用默認(rèn)的選項參數(shù)就好。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-twPJgr04-1688896509302)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230703124106609.png)]
- 開始進(jìn)行構(gòu)建
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-jMu8aj2R-1688896509302)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230703124309393.png)]
可以看待,前面幾個過程都是ok的,這里上傳制品過程,不需要。
創(chuàng)建harbor倉庫
- 鏡像命名規(guī)范:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-R0WQFu0j-1688896509303)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704055658325.png)]
- 創(chuàng)建倉庫
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-bdwXxoa3-1688896509303)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704055323738.png)]
- 修改本地 docker 服務(wù)使用 http 協(xié)議和私有倉庫通信(否則會報錯)
#配置可信任(如果倉庫是HTTPS訪問不用配置)
#在 daemon.json 中添加以下參數(shù)
[root@harbor ~]# vim /etc/docker/daemon.json #創(chuàng)建此文件,并寫入以下內(nèi)容
{
"insecure-registries": ["172.29.9.120"]
}
#重啟docker 服務(wù)
[root@harbor ~]# systemctl daemon-reload && systemctl restart docker
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-diQld9hR-1688896509304)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704061032271.png)]
編寫CI pipeline
- 創(chuàng)建
k8sci.jenkinsfile
@Library("devops06@main") _
//import src/org/devops/xxx.groovy
def checkout = new org.devops.CheckOut()
def build = new org.devops.Build()
def sonar = new org.devops.Sonar()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent {label "build"}
//跳過默認(rèn)的代碼檢出功能
options {
skipDefaultCheckout true
}
stages{
stage("CheckOut"){
steps{
script{
checkout.CheckOut()
//獲取commitID
env.commitID = checkout.GetCommitID()
println("commitID: ${env.commitID}")
// Jenkins構(gòu)建顯示信息
currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${env.commitID}"
currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
//currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
}
}
}
stage("Build"){
steps{
script{
build.Build()
}
}
}
stage("CodeScan"){
// 是否跳過代碼掃描?
when {
environment name: 'skipSonar', value: 'false'
}
steps{
script{
sonar.SonarScannerByPlugin()
}
}
}
stage("ImageBuild"){
steps{
script{
//PushArtifactByPlugin()
//PushArtifactByPluginPOM()
// init package info
appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service_CI
repoName = appName.split('-')[0] //devops6
imageName = "${repoName}/${appName}"
imageTag = "${env.branchName}-${env.commitID}"
sh """
#登錄鏡像倉庫
docker login -u admin -p Harbor12345 172.29.9.120
# 構(gòu)建鏡像
docker build -t 172.29.9.120/${imageName}:${imageTag} .
# 上傳鏡像
docker push 172.29.9.120/${imageName}:${imageTag}
# 刪除鏡像
sleep 2
docker rmi 172.29.9.120/${imageName}:${imageTag}
"""
}
}
}
}
}
- 在回放里運(yùn)行
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-2KOVJP2U-1688896509305)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704061342760.png)]
- 然后將代碼提交到共享庫里。
準(zhǔn)備k8s環(huán)境
- 啟動好k8s環(huán)境
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-elTtOolP-1688896509305)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704220639938.png)]
- 在devops06機(jī)器上安裝kubectl工具
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
[root@Devops6 ~]#yum install -y kubectl-1.20.0 --disableexcludes=kubernetes
- 然后把k8s集群master節(jié)點(diǎn)下的
~/.kube/config
文件拷貝到devops6機(jī)器~/.kube/目錄下
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-nEALoTSP-1688896509305)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230704221711066.png)]
- 然后在k8s的2個節(jié)點(diǎn)先配置好 修改本地 docker 服務(wù)使用 http 協(xié)議和私有倉庫通信(否則會報錯)
#配置可信任(如果倉庫是HTTPS訪問不用配置)
#在 daemon.json 中添加以下參數(shù)
[root@harbor ~]# vim /etc/docker/daemon.json #創(chuàng)建此文件,并寫入以下內(nèi)容
{
"insecure-registries": ["172.29.9.120"]
}
#重啟docker 服務(wù)
[root@harbor ~]# systemctl daemon-reload && systemctl restart docker
記得:只需要在node1 node2上配置就行。
- 自己k8s集群需不是一個ingress-controller。
這里之前已經(jīng)部署好ingress-controller了。
- 配置下kubectl的自動補(bǔ)全
#安裝軟件包
yum install -y epel-release bash-completion
#執(zhí)行命令
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc
創(chuàng)建一個devops6-deploy-repo
倉庫
- 創(chuàng)建
Deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: devops6-npm-service
spec:
replicas: 3
revisionHistoryLimit: 3
selector:
matchLabels:
app: devops6-npm-service
template:
metadata:
labels:
app: devops6-npm-service
spec:
containers:
- image: 172.29.9.120/devops6/devops6-npm-service:main-ed12ce10
name: devops6-npm-service
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: devops6-npm-service
spec:
type: ClusterIP
selector:
app: devops6-npm-service
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: devops6-npm-service
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: devops.test.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: devops6-npm-service
port:
name: http
- 自己部署應(yīng)用測試
創(chuàng)建新命名空間devops6
[root@Devops6 ~]#kubectl create ns devops6
部署應(yīng)用:
[root@Devops6 ~]#kubectl -n devops6 apply -f Deployment.yaml
deployment.apps/devops6-npm-service created
service/devops6-npm-service created
ingress.networking.k8s.io/devops6-npm-service created
注意:這里直接加上命名空間后,應(yīng)用就會直接被部署到此命名空間了。
[root@Devops6 ~]#kubectl get po -ndevops6
NAME READY STATUS RESTARTS AGE
devops6-npm-service-bd4978ff9-27bpp 1/1 Running 0 32s
devops6-npm-service-bd4978ff9-clkhm 1/1 Running 0 32s
devops6-npm-service-bd4978ff9-x2sw8 1/1 Running 0 32s
配置ingress域名解析:
[root@Devops6 ~]#vim /etc/hosts
172.29.9.31 devops.test.com
[root@Devops6 ~]#kubectl get ingress -ndevops6
NAME CLASS HOSTS ADDRESS PORTS AGE
devops6-npm-service <none> devops.test.com 172.29.9.31 80 8m11s
測試效果:
[root@Devops6 ~]#curl devops.test.com
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vuedemo</title>
</head>
<body>
<div id="app">
<h1>VERSION: main</h1>
</div>
<!-- built files will be auto injected -->
</body>
</html>
新建devops6-npm-service
版本分支,特性分支
- 以main為基礎(chǔ)新建
devops6-npm-service
版本分支RELEASE-1.1.1
修改index.html的內(nèi)容為RELEASE-1.1.1
。
- 運(yùn)行一次CI流水線
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4kNrjchh-1688896509307)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230705133823641.png)]
要記得改下這里的jenkinsfile文件:
成功生成鏡像:
- 我們再來更新一個版本的應(yīng)用程序看下
[root@Devops6 ~]#vim Deployment.yaml
將
- image: 172.29.9.120/devops6/devops6-npm-service:main-ed12ce10
替換為
172.29.9.120/devops6/devops6-npm-service:RELEASE-1.1.1-7d906f68
#然后部署應(yīng)用:
[root@Devops6 ~]#kubectl apply -f Deployment.yaml -ndevops6
#驗證
[root@Devops6 ~]#curl devops.test.com
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vuedemo</title>
</head>
<body>
<div id="app">
<h1>VERSION: RELEASE-1.1.1</h1>
</div>
<!-- built files will be auto injected -->
</body>
</html>
#可以看到,已經(jīng)更新成功了。
- 我們來測試下回滾
回滾命令:
## 查看歷史
kubectl rollout history deployment/anyops-devopsdocker-ui
## 查看具體某一個歷史版本信息
kubectl rollout history deployment/anyops-devopsdocker-ui --revision=2
## 回滾上個版本
kubectl rollout undo deployment/anyops-devopsdocker-ui -n anyops
## 回滾指定版本
kubectl rollout undo deployment/nginx --to-revision=2
查看當(dāng)前應(yīng)用版本:
[root@Devops6 ~]#kubectl rollout history deployment devops6-npm-service -ndevops6
deployment.apps/devops6-npm-service
REVISION CHANGE-CAUSE
1 <none>
2 <none>
#可以看到有2個歷史版本
我們打算回滾到上個歷史版本:
先來查看下當(dāng)前應(yīng)用版本:
watch -n 1 "curl devops.test.com"
watch -n 1 "curl -s devops.test.com"
開始回滾:
[root@Devops6 ~]#kubectl rollout undo deployment devops6-npm-service -ndevops6
deployment.apps/devops6-npm-service rolled back
回滾結(jié)果:
回滾成功。
- 這里調(diào)的是gitlab的api
調(diào)用gitlab api自動更新配置文件。
- jenkins裝一個插件
HTTP Request
-
devops6-npm-service
項目ProjectID為11。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-eHFPfPmU-1688896509312)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707070500615.png)]
- 創(chuàng)建
devops6-npm-service
目錄
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-QSlYcVW9-1688896509312)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707060343353.png)]
將Deployment.yaml
里的image改為__IMAGE_NAME__
- pipeline代碼
Gitlab.groovy
package org.devops
//獲取文件內(nèi)容
def GetRepoFile(projectId,filePath,branchName){
//GET /projects/:id/repository/files/:file_path/raw
apiUrl = "/projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"
response = HttpReq('GET', apiUrl)
return response
}
//更新文件內(nèi)容
def UpdateRepoFile(projectId,filePath,fileContent, branchName){
apiUrl = "projects/${projectId}/repository/files/${filePath}"
reqBody = """{"branch": "${branchName}","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}"""
response = HttpReqByPlugin('PUT',apiUrl,reqBody)
println(response)
}
//創(chuàng)建文件
def CreateRepoFile(projectId,filePath,fileContent, branchName){
apiUrl = "projects/${projectId}/repository/files/${filePath}"
reqBody = """{"branch": "${branchName}","encoding":"base64", "content": "${fileContent}", "commit_message": "update a new file"}"""
response = HttpReqByPlugin('POST',apiUrl,reqBody)
println(response)
}
// 封裝HTTP
def HttpReqByPlugin(reqType, reqUrl,reqBody ){
def gitServer = "http://172.29.9.101:8076/api/v4"
withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d',
variable: 'GITLABTOKEN')]) {
response = httpRequest acceptType: 'APPLICATION_JSON_UTF8',
consoleLogResponseBody: true,
contentType: 'APPLICATION_JSON_UTF8',
customHeaders: [[maskValue: false, name: 'PRIVATE-TOKEN', value: "${GITLABTOKEN}"]],
httpMode: "${reqType}",
url: "${gitServer}/${reqUrl}",
wrapAsMultipart: false,
requestBody: "${reqBody}"
}
return response
}
//發(fā)起HTTP請求
//調(diào)用gitlab api
def HttpReq(method, apiUrl){
withCredentials([string(credentialsId: '5782c77d-ce9d-44e5-b9ba-1ba2097fc31d', variable: 'gitlabtoken')]) {
response = sh returnStdout: true,
script: """
curl --location --request ${method} \
http://172.29.9.101:8076/api/v4/${apiUrl} \
--header "PRIVATE-TOKEN: ${gitlabtoken}"
"""
}
//新增這段代碼
try {
response = readJSON text: response - "\n" //json數(shù)據(jù)的讀取方式
} catch(e){
println(e)
}
return response
}
//獲取ProjectID
def GetProjectIDByName(projectName, groupName){
apiUrl = "projects?search=${projectName}"
response = HttpReq("GET", apiUrl)
if (response != []){
for (p in response) {
if (p["namespace"]["name"] == groupName){
return response[0]["id"]
}
}
}
}
//獲取分支CommitID
def GetBranchCommitID(projectID, branchName){
apiUrl = "projects/${projectID}/repository/branches/${branchName}"
response = HttpReq("GET", apiUrl)
return response.commit.short_id
}
k8sci.jenkinsfile
@Library("devops06@main") _
//import src/org/devops/xxx.groovy
def checkout = new org.devops.CheckOut()
def build = new org.devops.Build()
def sonar = new org.devops.Sonar()
def mygit = new org.devops.Gitlab()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent {label "build"}
//跳過默認(rèn)的代碼檢出功能
options {
skipDefaultCheckout true
}
stages{
stage("CheckOut"){
steps{
script{
checkout.CheckOut()
//獲取commitID
env.commitID = checkout.GetCommitID()
println("commitID: ${env.commitID}")
// Jenkins構(gòu)建顯示信息
currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${env.commitID}"
currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
//currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
}
}
}
stage("Build"){
steps{
script{
build.Build()
}
}
}
stage("CodeScan"){
// 是否跳過代碼掃描?
when {
environment name: 'skipSonar', value: 'false'
}
steps{
script{
sonar.SonarScannerByPlugin()
}
}
}
stage("ImageBuild"){
steps{
script{
//PushArtifactByPlugin()
//PushArtifactByPluginPOM()
// init package info
appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service_CI
repoName = appName.split('-')[0] //devops6
imageName = "${repoName}/${appName}"
imageTag = "${env.branchName}-${env.commitID}"
env.fullImageName = "172.29.9.120/${imageName}:${imageTag}"
sh """
#登錄鏡像倉庫
docker login -u admin -p Harbor12345 172.29.9.120
# 構(gòu)建鏡像
docker build -t ${env.fullImageName} .
# 上傳鏡像
docker push ${env.fullImageName}
# 刪除鏡像
sleep 2
docker rmi ${env.fullImageName}
"""
}
}
}
stage("UpdateEnvFile"){
steps{
script {
// 更新部署文件
projectId = 11
fileName = "Deployment.yaml" //模板文件
branchName = "main"
//下載模板文件
fileData = mygit.GetRepoFile(projectId,fileName,branchName)
sh "rm -fr ${fileName}"
//模板文件內(nèi)容保存到本地
writeFile file: fileName , text: fileData
env.deployFile = fileName
//替換鏡像
sh "sed -i 's#__IMAGE_NAME__#${env.fullImageName}#g' ${env.deployFile} "
sh "ls -l ; cat ${fileName}"
//創(chuàng)建/更新發(fā)布文件
newYaml = sh returnStdout: true, script: "cat ${env.deployFile}"
println(newYaml)
//更新gitlab文件內(nèi)容
base64Content = newYaml.bytes.encodeBase64().toString()
appName = "${JOB_NAME}".split('_')[0] //devops6-npm-service
env.groupName = appName.split('-')[0] //devops6
env.projectName = appName
// 會有并行問題,同時更新報錯
try {
mygit.UpdateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
} catch(e){
mygit.CreateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
}
}
}
}
}
}
- 再次新建版本分支
RELEASE-2.1.1
,jenkins里記得配置下該分支名。
- 運(yùn)行
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-Fl78o5Hw-1688896509314)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707070829381.png)]
點(diǎn)擊approve
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-7IVfeaqS-1688896509315)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707070202014.png)]
符合預(yù)期。
【GitOps最重要的一個特性: 自動更新部署文件】
更新生成版本文件
- 步驟: 拿到 env倉庫中的deployments.yaml模板文件, 然后替換內(nèi)容,更新到版本庫。
-
更新對象:
-
- RELEASE_VERSION(鏡像TAG)
-
stage("UpdateEnvFile"){ steps{ script { // 更新部署文件 projectId = 11 fileName = "Deployment.yaml" //模板文件 branchName = "main" //下載模板文件 fileData = mygit.GetRepoFile(projectId,fileName,branchName) sh "rm -fr ${fileName}" //模板文件內(nèi)容保存到本地 writeFile file: fileName , text: fileData env.deployFile = fileName //替換鏡像 sh "sed -i 's#__IMAGE_NAME__#${env.fullImageName}#g' ${env.deployFile} " sh "ls -l ; cat ${fileName}" //創(chuàng)建/更新發(fā)布文件 newYaml = sh returnStdout: true, script: "cat ${env.deployFile}" println(newYaml) //更新gitlab文件內(nèi)容 base64Content = newYaml.bytes.encodeBase64().toString() appName = "${JOB_NAME}".split('_')[0] //devops6-npm-service env.groupName = appName.split('-')[0] //devops6 env.projectName = appName // 會有并行問題,同時更新報錯 try { mygit.UpdateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main") } catch(e){ mygit.CreateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main") } } } }
-
更新后的版本文件
編寫CD pipeline
- 創(chuàng)建一個CD的job
devops6-npm-service_K8SCD
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4XfROLK7-1688896509317)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707073334556.png)]
配置git倉庫:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-tgke6cqI-1688896509317)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707074103792.png)]
- 編寫pipeline
k8scd.jenkinsfile
文件
@Library("devops06@main") _
def mygit = new org.devops.Gitlab()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent { label "build"}
options {
skipDefaultCheckout true
}
stages{
stage("GetManifests"){
steps{
script{
//下載發(fā)布文件
projectId = 11
env.deployFile = "${env.branchName}.yaml" //版本分支RELEASE-2.1.1.yaml
env.appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
filePath = "${env.appName}%2f${env.deployFile}" //devops6-npm-service/RELEASE-2.1.1.yaml
branchName = "main"
fileData = mygit.GetRepoFile(projectId,filePath,branchName)
sh "rm -fr ${env.deployFile}"
writeFile file: env.deployFile , text: fileData
sh "ls -l ; cat ${env.deployFile}"
}
}
}
stage("Deploy"){
steps{
script{
env.namespace = "${env.appName}".split('-')[0] //devops6
sh """
## 發(fā)布應(yīng)用
kubectl apply -f ${env.deployFile} -n ${env.namespace}
"""
// 獲取應(yīng)用狀態(tài)
5.times{
sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.appName}"
}
}
}
}
stage("RollBack"){
input {
message "是否進(jìn)行回滾"
ok "提交"
submitter ""
parameters {
choice(choices: ['yes', 'no'], name: 'opts')
}
}
steps{
script{
switch("${opts}") {
case "yes":
sh "kubectl rollout undo deployment/${env.appName} -n ${env.namespace} "
break
case "no":
break
}
}
}
}
}
}
- 運(yùn)行流水線
我們來提前觀察下此時版本:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-BKX6r4sR-1688896509318)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707074135231.png)]
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-LUNSLDKn-1688896509318)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707074148261.png)]
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-NiFkheLy-1688896509319)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230707074204527.png)]
符合預(yù)期。
完整代碼
完整代碼如下:
鏈接:https://pan.baidu.com/s/1XFtZ0epIwgVwu0jzQHyJkA?pwd=0820
提取碼:0820
2023.7.9-day9-k8s-ci-cd
(kubectl和helm ci-cd)
CI/CD共享庫源碼
前端項目 (Dockerfile)
K8s清單文件代碼倉庫
helm chart倉庫
環(huán)境:
gitlab-ce:15.0.3-ce.0
jenkins:2.346.3-2-lts-jdk11
sonarqube:9.9.0-community
harbor v2.6.2
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-5ofFJYun-1688896509320)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709083713029.png)]
k8sci.jenkinsfile
文件
@Library("devops06@main") _
//import src/org/devops/xxx.groovy
def checkout = new org.devops.CheckOut()
def build = new org.devops.Build()
def sonar = new org.devops.Sonar()
def mygit = new org.devops.Gitlab()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent {label "build"}
//跳過默認(rèn)的代碼檢出功能
options {
skipDefaultCheckout true
}
stages{
stage("CheckOut"){
steps{
script{
checkout.CheckOut()
//獲取commitID
env.commitID = checkout.GetCommitID()
println("commitID: ${env.commitID}")
// Jenkins構(gòu)建顯示信息
currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${env.commitID}"
currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
//currentBuild.description = "Trigger by user jenkins \n branch: ${env.branchName}"
}
}
}
stage("Build"){
steps{
script{
build.Build()
}
}
}
stage("CodeScan"){
// 是否跳過代碼掃描?
when {
environment name: 'skipSonar', value: 'false'
}
steps{
script{
sonar.SonarScannerByPlugin()
}
}
}
stage("ImageBuild"){
steps{
script{
//PushArtifactByPlugin()
//PushArtifactByPluginPOM()
// init package info
appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service_CI
repoName = appName.split('-')[0] //devops6
imageName = "${repoName}/${appName}"
imageTag = "${env.branchName}-${env.commitID}"
env.fullImageName = "172.29.9.120/${imageName}:${imageTag}"
sh """
#登錄鏡像倉庫
docker login -u admin -p Harbor12345 172.29.9.120
# 構(gòu)建鏡像
docker build -t ${env.fullImageName} .
# 上傳鏡像
docker push ${env.fullImageName}
# 刪除鏡像
sleep 2
docker rmi ${env.fullImageName}
"""
}
}
}
stage("UpdateEnvFile"){
steps{
script {
// 更新部署文件
projectId = 11
fileName = "Deployment.yaml" //模板文件
branchName = "main"
//下載模板文件
fileData = mygit.GetRepoFile(projectId,fileName,branchName)
sh "rm -fr ${fileName}"
//模板文件內(nèi)容保存到本地
writeFile file: fileName , text: fileData
env.deployFile = fileName
//替換鏡像
sh "sed -i 's#__IMAGE_NAME__#${env.fullImageName}#g' ${env.deployFile} "
sh "ls -l ; cat ${fileName}"
//創(chuàng)建/更新發(fā)布文件
newYaml = sh returnStdout: true, script: "cat ${env.deployFile}"
println(newYaml)
//更新gitlab文件內(nèi)容
base64Content = newYaml.bytes.encodeBase64().toString()
appName = "${JOB_NAME}".split('_')[0] //devops6-npm-service
env.groupName = appName.split('-')[0] //devops6
env.projectName = appName
// 會有并行問題,同時更新報錯
try {
mygit.UpdateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
} catch(e){
mygit.CreateRepoFile(projectId,"${env.projectName}%2f${env.branchName}.yaml",base64Content, "main")
}
}
}
}
}
}
k8scd.jenkinsfile
文件:
@Library("devops06@main") _
def mygit = new org.devops.Gitlab()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent { label "build"}
options {
skipDefaultCheckout true
}
stages{
stage("GetManifests"){
steps{
script{
//下載發(fā)布文件
projectId = 11
env.deployFile = "${env.branchName}.yaml" //版本分支RELEASE-2.1.1.yaml
env.appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
filePath = "${env.appName}%2f${env.deployFile}" //devops6-npm-service/RELEASE-2.1.1.yaml
branchName = "main"
fileData = mygit.GetRepoFile(projectId,filePath,branchName)
sh "rm -fr ${env.deployFile}"
writeFile file: env.deployFile , text: fileData
sh "ls -l ; cat ${env.deployFile}"
}
}
}
stage("Deploy"){
steps{
script{
env.namespace = "${env.appName}".split('-')[0] //devops6
sh """
## 發(fā)布應(yīng)用
kubectl apply -f ${env.deployFile} -n ${env.namespace}
"""
// 獲取應(yīng)用狀態(tài)
5.times{
sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.appName}"
}
}
}
}
stage("RollBack"){
input {
message "是否進(jìn)行回滾"
ok "提交"
submitter ""
parameters {
choice(choices: ['yes', 'no'], name: 'opts')
}
}
steps{
script{
switch("${opts}") {
case "yes":
sh "kubectl rollout undo deployment/${env.appName} -n ${env.namespace} "
break
case "no":
break
}
}
}
}
}
}
2、Helm CI/CD流水線
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-7HKAlX3F-1688896509321)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709102602647.png)]
環(huán)境準(zhǔn)備
刪除devops6命名空間
[root@Devops6 ~]#kubectl delete ns devops6
集群安裝helm
[root@Devops6 ~]#tar xf helm-v3.7.2-linux-amd64.tar.gz
[root@Devops6 ~]#cd linux-amd64/
[root@Devops6 linux-amd64]#cp helm /usr/bin/
[root@Devops6 linux-amd64]#chmod +x /usr/bin/helm
[root@Devops6 linux-amd64]#helm version
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
version.BuildInfo{Version:"v3.7.2", GitCommit:"663a896f4a815053445eec4153677ddc24a0a361", GitTreeState:"clean", GoVersion:"go1.16.10"}
[root@Devops6 linux-amd64]#helm repo add stable http://mirror.azure.cn/kubernetes/charts/
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
"stable" has been added to your repositories
[root@Devops6 linux-amd64]# helm repo list
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
NAME URL
stable http://mirror.azure.cn/kubernetes/charts/
[root@Devops6 linux-amd64]#echo "source <(helm completion bash)" >> ~/.bashrc
[root@Devops6 linux-amd64]#source ~/.bashrc
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
[root@Devops6 linux-amd64]#helm list
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
[root@Devops6 linux-amd64]#
- 具體安裝文檔參考鏈接:
https://blog.csdn.net/weixin_39246554/article/details/123955289?ops_request_misc=&request_id=5c6a4510d72e40eabbcc39450945e6e4&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2blogkoosearch~default-2-123955289-null-null.268v1control&utm_term=helm&spm=1018.2226.3001.4450
創(chuàng)建helm倉庫
devops6-helm-repo
helm手動安裝包
- 生成helm chart
[root@Devops6 ~]#helm create devops6-npm-service
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
Creating devops6-npm-service
[root@Devops6 ~]#cd devops6-npm-service/
[root@Devops6 devops6-npm-service]#ls
charts Chart.yaml templates values.yaml
- 編輯
values.yaml
修改如下2處地方:
[root@Devops6 devops6-npm-service]#vim values.yaml
image:
repository: 172.29.9.120/devops6/devops6-npm-service
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "RELEASE-2.1.1-8a398eee"
……
ingress:
enabled: true
className: ""
annotations:
kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: devops.test.com
paths:
- path: /
pathType: Prefix
- 生成部署文件
[root@Devops6 devops6-npm-service]#helm template --output-dir manifests .
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
wrote manifests/devops6-npm-service/templates/serviceaccount.yaml
wrote manifests/devops6-npm-service/templates/service.yaml
wrote manifests/devops6-npm-service/templates/deployment.yaml
wrote manifests/devops6-npm-service/templates/ingress.yaml
wrote manifests/devops6-npm-service/templates/tests/test-connection.yaml
- 部署
[root@Devops6 devops6-npm-service]#helm install devops6-npm-service . -ndevops6 --create-namespace
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
NAME: devops6-npm-service
LAST DEPLOYED: Sat Jul 8 10:57:40 2023
NAMESPACE: devops6
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
http://devops.test.com/
- 驗證
[root@Devops6 devops6-npm-service]#kubectl get po -ndevops6
NAME READY STATUS RESTARTS AGE
devops6-npm-service-7bcb6c49b5-rls6f 1/1 Running 0 28s
[root@Devops6 devops6-npm-service]#watch -n 1 "curl -s devops.test.com"
Every 1.0s: curl -s devops.test.com Sat Jul 8 10:58:46 2023
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vuedemo</title>
</head>
<body>
<div id="app">
<h1>VERSION: RELEASE-2.1.1</h1>
</div>
<!-- built files will be auto injected -->
</body>
</html>
部署成功。
- 將次helm chart推送到剛才創(chuàng)建的helm倉庫
#先刪除manifests目錄
[root@Devops6 devops6-npm-service]#pwd
/root/devops6-npm-service
[root@Devops6 devops6-npm-service]#ls
charts Chart.yaml manifests templates values.yaml
[root@Devops6 devops6-npm-service]#rm -rf manifests/
#推送 (注意:這次試驗這里是master分支)
cd existing_folder
git init
git remote add origin http://172.29.9.101:8076/devops6/devops6-helm-repo.git
git add .
git commit -m "Initial commit"
git push -u origin master
harbor上開啟helm chart
- 默認(rèn)harbor沒有helm chart功能,需要另外配置下才行
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-z3ufZLk3-1688896509323)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230708111712317.png)]
- 配置
開啟helm charts
./install.sh --with-chartmuseum
helm repo add devops6repo http://172.29.9.120/chartrepo/devops6/ --username=admin --password=Harbor12345
配置完后,harbor界面就出現(xiàn)了helm chart選項了:
添加過程:
[root@Devops6 devops6-npm-service]#helm repo list
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
NAME URL
stable http://mirror.azure.cn/kubernetes/charts/
[root@Devops6 devops6-npm-service]#helm repo add devops6repo http://172.29.9.120/chartrepo/devops6/ --username=admin --password=Harbor12345
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
"devops6repo" has been added to your repositories
[root@Devops6 devops6-npm-service]#helm repo list
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
NAME URL
stable http://mirror.azure.cn/kubernetes/charts/
devops6repo http://172.29.9.120/chartrepo/devops6/
helm安裝cm-push軟件
CI pipeline
pipeline代碼
創(chuàng)建CI 流水線
- 以
devops6-npm-service_K8SCI
為基礎(chǔ)新創(chuàng)建devops6-npm-service_HELMCI
項目
修改為helmci.jenkinsfile
。
- 最終
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-5zPkUFwi-1688896509328)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709083045417.png)]
CI 測試
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-0OQCRI7B-1688896509329)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709083152825.png)]
CD pipeline
pipeline代碼
創(chuàng)建CD流水線
- 以
devops6-npm-service_K8SCD
為基礎(chǔ)新創(chuàng)建devops6-npm-service_HELMCD
項目
修改為helmcd.jenkinsfile
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-yySe5cMn-1688896509330)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230708111355792.png)]
修改選線參數(shù):
最終:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-vAv9AVLO-1688896509330)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709082857194.png)]
CD測試
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-fduuq5i4-1688896509331)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709083003688.png)]
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-PVASiBcl-1688896509331)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709082930825.png)]
完整代碼
完整代碼如下:
鏈接:https://pan.baidu.com/s/1XFtZ0epIwgVwu0jzQHyJkA?pwd=0820
提取碼:0820
2023.7.9-day9-k8s-ci-cd
(kubectl和helm ci-cd)
CI/CD共享庫源碼
前端項目 (Dockerfile)
K8s清單文件代碼倉庫
helm chart倉庫
環(huán)境:
gitlab-ce:15.0.3-ce.0
jenkins:2.346.3-2-lts-jdk11
sonarqube:9.9.0-community
harbor v2.6.2
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-3DTfFIZE-1688896509332)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230709084520218.png)]
helmci.jenkinsfile
文件
@Library("devops06@main") _
//import src/org/devops/Build.groovy
def build = new org.devops.Build()
def sonar = new org.devops.Sonar()
def checkouts = new org.devops.CheckOut()
def mygit = new org.devops.Gitlab()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
pipeline {
agent { label "build"}
options {
skipDefaultCheckout true
}
stages{
stage("CheckOut"){
steps{
script{
checkouts.CheckOut()
}
}
}
stage("Build"){
steps{
script{
build.Build()
}
}
}
stage("CodeScan"){
steps{
script{
sonar.SonarScannerByPlugin()
}
}
}
stage("ImageBuild"){
steps{
script{
//PushArtifactByPlugin()
//PushArtifactByPluginPOM()
// init package info
appName = "${JOB_NAME}".split('_')[0] //devops6-maven-service
repoName = appName.split('-')[0] //devops6
//commitID
commitID = checkouts.GetCommitID()
println(commitID)
// Jenkins構(gòu)建顯示信息
currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${commitID}"
currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
imageName = "${repoName}/${appName}"
env.imageTag = "${env.branchName}-${commitID}"
env.fullImageName = "172.29.9.120/${imageName}:${env.imageTag}"
sh """
#登錄鏡像倉庫
docker login -u admin -p Harbor12345 172.29.9.120
# 構(gòu)建鏡像
docker build -t ${env.fullImageName} .
# 上傳鏡像
docker push ${env.fullImageName}
# 刪除鏡像
sleep 2
docker rmi ${env.fullImageName}
"""
}
}
}
stage("UpdateEnvFile"){
steps{
script {
// 更新部署文件
projectId = 12 //helm repo id
fileName = "values.yaml" //模板文件
branchName = "master"
//下載模板文件
fileData = mygit.GetRepoFile(projectId,fileName,branchName)
sh "rm -fr ${fileName}"
//修改鏡像tag
yamlData = readYaml text: fileData
yamlData.image.tag = "${env.imageTag}"
//模板文件內(nèi)容保存到本地
writeYaml file: "${fileName}" , data: yamlData
//創(chuàng)建/更新發(fā)布文件
newYaml = sh returnStdout: true, script: "cat ${fileName}"
println(newYaml)
//更新gitlab文件內(nèi)容
base64Content = newYaml.bytes.encodeBase64().toString()
// 會有并行問題,同時更新報錯
try {
mygit.UpdateRepoFile(projectId,"${fileName}",base64Content, "master")
} catch(e){
mygit.CreateRepoFile(projectId,"${fileName}",base64Content, "master")
}
}
}
}
stage("HelmPackage"){
steps{
script{
// helm pakcage & push harbor
appName = "${JOB_NAME}".split('_')[0]
sh "pwd && ls -l"
sh "mkdir -p ${appName} && cd ${appName}"
ws("${workspace}/${appName}"){
checkout([$class: 'GitSCM', branches: [[name: '*/master']],
extensions: [],
userRemoteConfigs: [[credentialsId: 'gitlab-root',
url: 'http://172.29.9.101:8076/devops6/devops6-helm-repo.git']]])
sh "ls -l"
}
//helm package
chartVersion = "${env.branchName}".split("-")[-1] //1.1.1
sh """
helm package ${appName} --version ${chartVersion}
helm-cm-push ${appName}-${chartVersion}.tgz devops6repo
"""
}
}
}
}
}
helmcd.jenkinsfile
文件
@Library("devops06@main") _
def checkout = new org.devops.CheckOut()
def build = new org.devops.Build()
//使用git 參數(shù)需要格式化
env.branchName = "${env.branchName}" - "origin/"
println(env.branchName)
//commitID
env.commitID = checkouts.GetCommitID()
println(commitID)
// Jenkins構(gòu)建顯示信息
currentBuild.displayName = "第${BUILD_NUMBER}次構(gòu)建-${env.commitID}"
currentBuild.description = "構(gòu)建分支名稱:${env.branchName}"
pipeline {
agent { label "build"}
options {
skipDefaultCheckout true
}
stages{
stage("GetHelmChart"){
steps{
script{
//下載helm chart
env.chartVersion = "${env.branchName}".split("-")[-1]
env.appName = "${JOB_NAME}".split('_')[0]
sh """
helm repo update devops6repo
helm pull devops6repo/${env.appName} --version ${env.chartVersion}
"""
}
}
}
stage("Deploy"){
steps{
script{
env.namespace = "${env.appName}".split('-')[0] //devops6
sh """
## 發(fā)布應(yīng)用
helm upgrade --install --create-namespace "${env.appName}" ./"${env.appName}"-${env.chartVersion}.tgz -n ${env.namespace}
helm history "${env.appName}" -n ${env.namespace}
"""
// 獲取應(yīng)用狀態(tài)
5.times{
sh "sleep 2; kubectl -n ${env.namespace} get pod | grep ${env.appName}"
}
//收集history
env.revision = sh returnStdout: true,
script: """helm history ${env.appName} -n ${env.namespace} | grep -v 'REVISION' | awk '{print \$1}' """
println("${env.revision}")
println("${env.revision.split('\n').toString()}")
env.REVISION = "${env.revision.split('\n').toString()}"
println("${env.REVISION}")
}
}
}
stage("RollOut"){
input {
message "是否進(jìn)行回滾"
ok "提交"
submitter ""
parameters {
choice(choices: ['yes', 'no'], name: 'opts')
}
}
steps{
script{
switch("${opts}") {
case "yes":
def result = input message: "選擇回滾版本?",
parameters: [choice(choices: env.REVISION, name: 'rversion')]
println("${result}")
sh "helm rollback ${env.appName} ${result} -n ${env.namespace} "
break
case "no":
break
}
}
}
}
}
}
關(guān)于我
我的博客主旨:
- 排版美觀,語言精煉;
- 文檔即手冊,步驟明細(xì),拒絕埋坑,提供源碼;
- 本人實(shí)戰(zhàn)文檔都是親測成功的,各位小伙伴在實(shí)際操作過程中如有什么疑問,可隨時聯(lián)系本人幫您解決問題,讓我們一起進(jìn)步!
?? 微信二維碼
x2675263825 (舍得), qq:2675263825。
?? 微信公眾號
《云原生架構(gòu)師實(shí)戰(zhàn)》
?? 語雀
https://www.yuque.com/xyy-onlyone
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-jcxIcx9Z-1688896509333)(https://bucket-hg.oss-cn-shanghai.aliyuncs.com/img/image-20230624093747671.png)]
?? csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
?? 知乎
https://www.zhihu.com/people/foryouone
最后
“”“helm history ${env.appName} -n ${env.namespace} | grep -v ‘REVISION’ | awk ‘{print $1}’ “””
println(“
e
n
v
.
r
e
v
i
s
i
o
n
"
)
p
r
i
n
t
l
n
(
"
{env.revision}") println("
env.revision")println("{env.revision.split(‘\n’).toString()}”)
env.REVISION = “KaTeX parse error: Undefined control sequence: \n at position 22: …evision.split('\?n?').toString()}"…{env.REVISION}”)
}
}
}文章來源:http://www.zghlxwxcb.cn/news/detail-542067.html
stage("RollOut"){
input {
message "是否進(jìn)行回滾"
ok "提交"
submitter ""
parameters {
choice(choices: ['yes', 'no'], name: 'opts')
}
}
steps{
script{
switch("${opts}") {
case "yes":
def result = input message: "選擇回滾版本?",
parameters: [choice(choices: env.REVISION, name: 'rversion')]
println("${result}")
sh "helm rollback ${env.appName} ${result} -n ${env.namespace} "
break
case "no":
break
}
}
}
}
}
}文章來源地址http://www.zghlxwxcb.cn/news/detail-542067.html
## 關(guān)于我
我的博客主旨:
- 排版美觀,語言精煉;
- 文檔即手冊,步驟明細(xì),拒絕埋坑,提供源碼;
- 本人實(shí)戰(zhàn)文檔都是親測成功的,各位小伙伴在實(shí)際操作過程中如有什么疑問,可隨時聯(lián)系本人幫您解決問題,讓我們一起進(jìn)步!
?? 微信二維碼
x2675263825 (舍得), qq:2675263825。
[外鏈圖片轉(zhuǎn)存中...(img-2zH5h7IE-1688896509332)]
?? 微信公眾號
《云原生架構(gòu)師實(shí)戰(zhàn)》
[外鏈圖片轉(zhuǎn)存中...(img-j8ISJdtA-1688896509332)]
?? 語雀
https://www.yuque.com/xyy-onlyone
[外鏈圖片轉(zhuǎn)存中...(img-jcxIcx9Z-1688896509333)]
?? csdn
[https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421](https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421)
[外鏈圖片轉(zhuǎn)存中...(img-C9UTIB9P-1688896509333)]
?? 知乎
[https://www.zhihu.com/people/foryouone](https://www.zhihu.com/people/foryouone)
[外鏈圖片轉(zhuǎn)存中...(img-UKUKP8qs-1688896509333)]
## 最后
好了,關(guān)于本次就到這里了,感謝大家閱讀,最后祝大家生活快樂,每天都過的有意義哦,我們下期見!
到了這里,關(guān)于實(shí)踐:devops之K8s環(huán)境持續(xù)部署的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!