武平縣網(wǎng)站建設(shè)搜索引擎競(jìng)價(jià)廣告
目錄
一、實(shí)驗(yàn)
1.環(huán)境
2.GitLab 更新deployment文件
3.GitLab更新共享庫(kù)前端項(xiàng)目CI與CD流水線
4.K8S查看前端項(xiàng)目版本
5.Jenkins 構(gòu)建前端項(xiàng)目
6.Jenkins 再次構(gòu)建前端項(xiàng)目
二、問(wèn)題
1. Jenkins 構(gòu)建CI 流水線報(bào)錯(cuò)
2. Jenkins 構(gòu)建CI 流水線彈出腳本報(bào)錯(cuò)
3. Jenkins 構(gòu)建CD 流水線報(bào)錯(cuò)
4.URL中特殊字符實(shí)現(xiàn)哪些功能
5.sed如何實(shí)現(xiàn)替換特殊字符
?
?
一、實(shí)驗(yàn)
1.環(huán)境
(1)主機(jī)
表1 主機(jī)
主機(jī) | 架構(gòu) | 版本 | IP | 備注 |
master1 | K8S master節(jié)點(diǎn) | 1.20.6 | 192.168.204.180 | jenkins slave (從節(jié)點(diǎn)) |
node1 | K8S node節(jié)點(diǎn) | 1.20.6 | 192.168.204.181 | ? |
node2 | K8S node節(jié)點(diǎn) | 1.20.6 | 192.168.204.182 | ? |
jenkins | ?jenkins主節(jié)點(diǎn)? ? ?? | 2.414.2 | 192.168.204.15:8080 | ?gitlab?runner (從節(jié)點(diǎn)) |
? | harbor私有倉(cāng)庫(kù) | 1.2.2 | 192.168.204.15 | ? |
gitlab | gitlab 主節(jié)點(diǎn)??????? | 12.10.14 | 192.168.204.8:82 | jenkins slave (從節(jié)點(diǎn)) |
? | sonarqube | 9.6 | 192.168.204.8:9000 | ? |
?
2.GitLab 更新deployment文件
(1)項(xiàng)目新建目錄,用于存放上傳的deployment 替換文件
(2)準(zhǔn)備更新模板文件deployment.yaml
__APPNAME__(應(yīng)用名稱)對(duì)應(yīng)Jenkins作業(yè)名稱__NAMESPACE__ (名稱空間) 對(duì)應(yīng)業(yè)務(wù)名稱__INAGENAME__(鏡像名稱)
(3)更新完成
(4)項(xiàng)目目錄如下:
?
3.GitLab更新共享庫(kù)前端項(xiàng)目CI與CD流水線
(1)查看項(xiàng)目架構(gòu)
(2)更新K8S CI流水線 (k8sci.jenkinsfile)
@Library("mylib@master") _
import org.devops.*def checkout = new Checkout()
def build = new Build()
def unittest = new UnitTest()
def sonar = new Sonar()
def gitlabutil = new Gitlab()pipeline {agent { label "build"}options {skipDefaultCheckout true}stages{stage("Checkout"){steps{script {println("GetCode")checkout.GetCode("${env.srcUrl}","${env.branchName}")}}}stage("build"){steps{script{println("Build")build.CodeBuild("${env.buildTool}")}}}stage("UnitTest"){steps{script{println("Test")unittest.CodeTest("${env.buildTool}")}}}stage("SonarScan"){steps {script {groupName = "${JOB_NAME}".split("/")[0]projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]sonar.CodeSonar("${env.buildTool}",projectName,groupName)}}}stage("PushImage"){steps {script {repoName = "${JOB_NAME}".split("/")[0]projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]env.registry = "192.168.204.15"env.imageName = "${env.registry}/${repoName}/${projectName}:${env.branchName}"withCredentials([usernamePassword(credentialsId: '8c662308-4991-4576-9826-74a5417de685', passwordVariable: 'DOCKER_PASSWD', usernameVariable: 'DOCKER_USER')]) {sh """#重寫HTML首頁(yè)echo "${env.imageName}" > dist/index.html #構(gòu)建鏡像docker build -t ${env.imageName} .#登錄鏡像倉(cāng)庫(kù)docker login -u ${DOCKER_USER} -p ${DOCKER_PASSWD} ${env.registry}#上傳鏡像docker push ${env.imageName}#刪除鏡像sleep 2docker rmi ${env.imageName}"""}}}}stage("ReleaseFile"){steps{script{// 獲取模板文件fileData = gitlabutil.GetRepoFile(22,"deployment.yaml", "master")sh "rm -fr deployment.yaml"writeFile file: 'deployment.yaml', text: fileData// 替換模板文件內(nèi)容namespace = "${JOB_NAME}".split("/")[0]appName ="${JOB_NAME}".split("/")[-1].split("_")[0]sh """sed -i 's#__PORT__#${env.port}#g' deployment.yamlsed -i 's#__APPNAME__#${appName}#g' deployment.yamlsed -i 's#__NAMESPACE__#${namespace}#g' deployment.yamlsed -i 's#__IMAGENAME__#${env.imageName}#g' deployment.yaml"""// 上傳替換后的版本文件(新建文件或者更新文件)newYaml = sh returnStdout: true, script: 'cat deployment.yaml'println(newYaml)//更新gitlab文件內(nèi)容base64Content = newYaml.bytes.encodeBase64().toString()// 會(huì)有并行問(wèn)題,同時(shí)更新報(bào)錯(cuò)try {gitlabutil.UpdateRepoFile(22,"${appName}%2f${env.branchName}.yaml",base64Content, "master")} catch(e){gitlabutil.CreateRepoFile(22,"${appName}%2f${env.branchName}.yaml",base64Content, "master")}}}}}}
(3)更新K8S CD流水線 (k8scd.jenkinsfile)
@Library("mylib@master") _
import org.devops.*def gitlabbutil = new Gitlab()
env.groupName = "${JOB_NAME}".split("/")[0]
env.projectName ="${JOB_NAME}".split("/")[-1].split("_")[0]pipeline {agent { label "k8s"}options {skipDefaultCheckout true}stages{stage("GetDeployFile"){steps{script {env.appName = "${env.projectName}"env.deployFile = "${env.appName}/${env.branchName}.yaml"//println("GetCode")fileData = gitlabbutil.GetRepoFile(22,"${env.appName}%2f${env.branchName}.yaml", "master")//println(fileData)sh "rm -fr ${env.deployFile}"writeFile file: "${env.deployFile}", text: fileData//sh "ls -l; cat deployment.yaml"sh "ls -l "}}}stage("DeployAPP"){steps{script{env.namespace = "${env.groupName}"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("RollOut"){input {message "是否進(jìn)行回滾"ok "提交"submitter "david,aa"parameters {choice(choices: ['yes','no'], name: 'opts')}}steps{script{switch ("${opts}"){case "yes":sh " kubectl rollout undo deployment/${env.appName} -n ${env.namespace}"breakcase "no":break}}}}}
}
4.K8S查看前端項(xiàng)目版本
(1)外部測(cè)試訪問(wèn)(當(dāng)前版本為1.1.7)
# curl http://devops03-devops-ui.devops.com:31291
(2)??另開一個(gè)終端用watch命令觀察pod變化
# watch -n 1 "kubectl get pod -n devops03"
?
5.Jenkins 構(gòu)建前端項(xiàng)目
(1)Jenkins給前端項(xiàng)目CI流水線添加參數(shù)添加字符參數(shù)port
(2)Jenkins給前端項(xiàng)目CD流水線添加參數(shù)添加字符參數(shù)branchName
?
(3) 構(gòu)建前端項(xiàng)目CI流水線
(4)成功
?
(5)GitLab查看deployment部署文件已自動(dòng)上傳(RELEASE-1.1.5.yaml)
(6)?構(gòu)建前端項(xiàng)目CD流水線
(7) 觀察pod變化
(8)外部測(cè)試訪問(wèn)(當(dāng)前版本為1.1.5)
# curl http://devops03-devops-ui.devops.com:31291
(9)不進(jìn)行回滾
(10)完成
?
6.Jenkins 再次構(gòu)建前端項(xiàng)目
(1)?構(gòu)建前端項(xiàng)目CI流水線
(2)成功
(3)GitLab查看deployment部署文件已自動(dòng)上傳(RELEASE-1.1.6.yaml)
(4) 構(gòu)建前端項(xiàng)目CD流水線
(5) 觀察pod變化
(6)外部測(cè)試訪問(wèn)(當(dāng)前版本為1.1.6)
# curl http://devops03-devops-ui.devops.com:31291
(7)不進(jìn)行回滾
(8)完成
?
二、問(wèn)題
1. Jenkins 構(gòu)建CI 流水線報(bào)錯(cuò)
(1)報(bào)錯(cuò)
(2)原因分析
函數(shù)名錯(cuò)誤
(3)解決方法
修改函數(shù)名。
修改前:
修改后:
?
?
2. Jenkins 構(gòu)建CI 流水線彈出腳本報(bào)錯(cuò)
(1)報(bào)錯(cuò)
(2)原因分析
script不允許使用靜態(tài)方法
(3)解決方法
運(yùn)行script使用靜態(tài)方法
根據(jù)彈出提示頁(yè)面,點(diǎn)擊進(jìn)入。
點(diǎn)擊Approve
完成
重寫構(gòu)建項(xiàng)目成功
3. Jenkins 構(gòu)建CD 流水線報(bào)錯(cuò)
(1) 報(bào)錯(cuò)
(2)原因分析
yaml文件格式錯(cuò)誤
(3)解決方法
修改deploymeny模板文件
修改前:
修改后:
成功:
?
4.URL中特殊字符實(shí)現(xiàn)哪些功能
(1)URL特殊字符
?
有些符號(hào)在URL中是不能直接傳遞的,如果要在URL中傳遞這些特殊符號(hào),那么就要使用他們的編碼了。
編碼的格式為:%加字符的ASCII碼,即一個(gè)百分號(hào)%,后面跟對(duì)應(yīng)字符的ASCII(16進(jìn)制)碼值。例如 空格的編碼值是"%20"。
如果不使用轉(zhuǎn)義字符,這些編碼就會(huì)當(dāng)URL中定義的特殊字符處理。?
(2)URL特殊符號(hào)及編碼 十六進(jìn)制值
1) + URL 中+號(hào)表示空格 %2B
2) 空格 URL中的空格可以用+號(hào)或者編碼 %20
3) / 分隔目錄和子目錄 %2F
4) ? 分隔實(shí)際的 URL 和參數(shù) %3F
5) % 指定特殊字符 %25
6) # 表示書簽 %23
7) & URL 中指定的參數(shù)間的分隔符 %26
8) = URL 中指定參數(shù)的值 %3D
5.sed如何實(shí)現(xiàn)替換特殊字符
(1)普通操作可以使用冒號(hào)(:)井號(hào)(#)正斜杠(/)來(lái)作為分隔符
sed -i 's#abc#def#g' geng.file ---將文件geng中的abc替換成defcat geng.file | sed 's/abc/def/g' ---打印文件geng,并將其中的abc替換成def
(2)對(duì)于變量做替換
sed 若是單引號(hào)括起來(lái)的,變量上得再額外加個(gè)單引號(hào)才能引用生效;
? ? ? ?若是雙引號(hào)括起來(lái)的,可直接引用生效。
1)舉例
pa='127.0.0.1/32'; field='ip_allow=123'; \
echo $field | sed 's#^ip_allow=.*#ip_allow=${pa}#g' 結(jié)果:ip_allow=${pa} --變量替換未生效2)更改
echo $field | sed 's#^ip_allow=.*#ip_allow='${pa}'#g'結(jié)果:ip_allow=127.0.0.1/323)更改
echo $field | sed "s#^ip_allow=.*#ip_allow=${pa}#g"結(jié)果:ip_allow=127.0.0.1/32
(3)?特殊字符替換,反斜杠、正斜杠、雙引號(hào)、$符
單個(gè)轉(zhuǎn)義:多加個(gè)反斜杠做轉(zhuǎn)義即可:反斜杠(\\)、正斜杠(\/)、雙引號(hào)(\")
單轉(zhuǎn)多個(gè):參考如下列表
表2 特殊字符轉(zhuǎn)換
實(shí)現(xiàn)目標(biāo) | 方法 | 能否用單引號(hào)還是雙引號(hào)括起來(lái) | ||
單引號(hào) | 雙引號(hào) | 為什么 | ||
反斜杠(\)替換成兩個(gè)反斜杠(\\) | sed -i 's#\\#\\\\#g' file 或sed -i 's:\\:\\\\:g' file | √ | × | 反斜杠用雙引號(hào)括起來(lái)會(huì)報(bào)錯(cuò) |
反斜杠(\)替換成正斜杠(/) | sed -i 's#\\#\/#g' file | √ | × | 反斜杠用雙引號(hào)括起來(lái)會(huì)報(bào)錯(cuò) |
雙引號(hào)(")替換成兩個(gè)雙引號(hào)("") | sed -i 's#\"#\"\"#g' file sed -i "s#\"#\"\"#g" file | √ | √ | ? |
單引號(hào)(')替換成兩個(gè)單引號(hào)('') | sed -i "s#'#''#g" file | × | √ | 不能用單引號(hào)括起來(lái),分不清了 |
($)替換成\$ | sed -i 's:\$:\\\$:g' file | √ | × | 不能用雙引號(hào),否則會(huì)認(rèn)為是$(正則匹配結(jié)尾位置)行的結(jié)果追加字符呢 |
(4)curl時(shí)用的變量,sed轉(zhuǎn)化
curl -H 'Content-Type: application/json' -X POST -d?參數(shù)(參數(shù)中涉及到特殊字符都得轉(zhuǎn)義,而且要多轉(zhuǎn)一層,即$得轉(zhuǎn)成\\$,才能原封不動(dòng)的供后續(xù)使用)
#值替換單引號(hào)、反斜杠、雙引號(hào) curl的時(shí)候用,多一層轉(zhuǎn)義,所以\要用\\sed -i "s#'#''#g" ${file} ---單引號(hào)要轉(zhuǎn)成兩個(gè)單引號(hào)sed -i 's#\\#\\\\\\\\#g' ${file} ---反斜杠sed -i "s:\":\\\\\":g" ${file} ---雙引號(hào)sed -i 's:\$:\\\\\$:g' ${file} ---$符
curl引用參數(shù)的這種形式有兩種寫法:
1)直接引用單個(gè)參數(shù)變量
curl -H 'Content-Type: application/json' -X POST -d '{"type":"0","name":" ' ${pa_name} ' "}'
這種需要對(duì)變量額外加上一個(gè)單引號(hào),才能引用生效。2)整個(gè)參數(shù)變量作為一個(gè)整體(推薦)
param="{\"type\":\"0\", \"name\":\"${pa_name}\"}"
curl -H 'Content-Type: application/json' -X POST -d "${param}"
?
?