通過Jenkins構建CI/CD實現全鏈路灰度
作者 | 卜比
本文介紹通過 Jenkins 構建流水線的方式實現全鏈路灰度功能。
在發布過程中,為了整體穩定性,我們總是希望能夠用小部分特定流量來驗證下新發布應用是否正常。即使新版本有問題,也能及時發現,控制影響面,保障了整體的穩定性。
1.整體架構
我們以如下 Demo 為例:
為了保證穩定,我們約定如下上線流程:
其中,在灰度驗證中,有幾種不同的策略:
- 直接使用線上小部分流量來測試(按照百分比放量)
- 從線上按照特定規則選擇流量(比如特定的 header、特定的 cookie 等)
- 在客戶端或瀏覽器上標識出流量是否灰度(比如通過 header 傳遞)
2.部署應用&創建泳道
按照參考文檔部署應用后,我們首先要區分線上流量和灰度流量。創建泳道組,將整個鏈路涉及到的應用全選:
然后創建泳道組,將符合規則的應用劃入 gray 泳道:
注:沒有匹配的流量,會走到基線環境,也就是沒有打標的應用節點上。
配置完成后,訪問網關,如果不符合灰度規則,走基線環境:
如何符合灰度規則,走灰度環境:
3.配置 Jenkins 流水線
本文實踐需要將源碼打包后執行鏡像推送,請確保 Jenkins 有權限推送到鏡像倉庫中。具體操作,請參見使用 kaniko 構建和推送容器鏡像。
在 Jenkins 命名空間下使用生成的 config.json 文件創建名為 jenkins-docker-cfg 的 Secret。
kubectl create secret generic jenkins-docker-cfg -n jenkins --from-file=/root/.docker/config.json
(1)在 Jenkins 中創建全鏈路灰度發布流水線
基于 Jenkins 實現自動化發布的流水線,通過該流水線可以使應用發布具備可灰度、可觀測、可回滾的安全生產三板斧能力。
- 在 Jenkins 控制臺左側導航欄單擊新建任務。
- 輸入任務名稱,選擇流水線,然后單擊確定。
- 在頂部菜單欄單擊流水線頁簽,在流水線區域配置相關參數選擇,輸入腳本路徑,然后單擊保存。
定義:選擇 Pipeline script from SCM。
SCM:選擇 Git。
Repository URL:輸入 Git 倉庫的 URL。
腳本路徑:輸入 Jenkinsfile。
您可以參考以下的文件填寫好指定的參數,當然您也可以根據需求編寫 Jenkinsfile ,并上傳至 Git 的指定路徑下(流水線中指定的腳本路徑)。
#!groovy
pipeline {
// 定義本次構建使用哪個標簽的構建環境,本示例中為 “slave-pipeline”
agent{
node{
label 'slave-pipeline'
}
}
//常量參數,初始確定后一般不需更改
environment{
IMAGE = sh(returnStdout: true,script: 'echo registry.$image_region.aliyuncs.com/$image_namespace/$image_reponame:$image_tag').trim()
BRANCH = sh(returnStdout: true,script: 'echo $branch').trim()
}
options {
//保持構建的最大個數
buildDiscarder(logRotator(numToKeepStr: '10'))
}
parameters {
string(name: 'image_region', defaultValue: 'cn-shanghai')
string(name: 'image_namespace', defaultValue: 'yizhan')
string(name: 'image_reponame', defaultValue: 'spring-cloud-a')
string(name: 'image_tag', defaultValue: 'gray')
string(name: 'branch', defaultValue: 'master')
string(name: 'number_of_pods', defaultValue: '2')
}
//pipeline的各個階段場景
stages {
stage('代碼打包') {
steps{
container("maven") {
echo "鏡像構建......"
sh "cd A && mvn clean package"
}
}
}
stage('鏡像構建及發布'){
steps{
container("kaniko") {
sh "kaniko -f `pwd`/A/Dockerfile -c `pwd`/A --destination=${IMAGE} --skip-tls-verify"
}
}
}
stage('灰度部署') {
steps{
container('kubectl') {
echo "灰度部署......"
sh "cd A && sed -i -E \"s/${env.image_reponame}:.+/${env.image_reponame}:${env.image_tag}/\" A-gray-deployment.yaml"
sh "cd A && sed -i -E \"s/replicas:.+/replicas: ${env.number_of_pods}/\" A-gray-deployment.yaml"
sh "kubectl apply -f A/A-gray-deployment.yaml -n default"
}
}
}
stage('結束灰度') {
input {
message "請確認是否全量發布"
ok "確認"
parameters {
string(name: 'continue', defaultValue: 'true', description: 'true為全量發布,其他為回滾')
}
}
steps{
script {
env.continue = sh (script: 'echo ${continue}', returnStdout: true).trim()
if (env.continue.equals('true')) {
container('kubectl') {
echo "全量發布......"
sh "cd A && sed -i -E \"s/${env.image_reponame}:.+/${env.image_reponame}:${env.image_tag}/\" A-deployment.yaml"
sh "cd A && sed -i -E \"s/replicas:.+/replicas: ${env.number_of_pods}/\" A-deployment.yaml"
sh "kubectl apply -f A/A-deployment.yaml -n default"
}
} else {
echo '回滾'
}
container('kubectl') {
sh "kubectl delete -f A/A-gray-deployment.yaml -n default"
}
}
}
}
}
}
(2)構建 Jenkins 流水線
- 在 Jenkins 控制臺單擊流水線右側的圖標。
- 單擊流水線的開始構建。
說明:第一次構建因為需要從 Git 倉庫拉取配置并初始化流水線,所以可能會報錯,再次執行 Build with Parameters,生成相關的參數,填寫相關的參數,再次執行構建。
查看部署狀態,代碼打包,鏡像構建及發布,灰度部署階段都已經完成,結束灰度階段等待確認。
如果驗證結果符合預期,則執行全量發布,請參見后文的全量發布應用。
如果驗證結果不符合預期時,則執行回滾,請參見后文的回滾應用。
(3)結果驗證
- 登錄容器服務控制臺,在控制臺左側導航欄中,單擊集群。
- 在集群列表頁面中,單擊目標集群名稱或者目標集群右側操作列下的詳情。
- 在集群管理頁面左側導航欄選擇工作負載 > 無狀態。
- 在無狀態應用列表頁面,spring-cloud-a-gray應用已經自動創建,并且它的鏡像已經替換為spring-cloud-a:gray版本。
- 在集群管理頁面左側導航欄選擇網絡 > 服務,選擇設置的命名空間,單擊zuul-slb服務的外部端點,查看真實的調用情況。
不帶灰度 Header 進行調用,發現路由到 A 的正常節點。
Curl 命令:
curl http://182.92.XX.XX/A/a
執行結果如下:
A[10.4.XX.XX] -> B[10.4.XX.XX] -> C[10.4.XX.XX]%
帶上符合條件的參數進行訪問,路由到 A 的灰度節點中。
Curl 命令:
curl http://182.92.XX.XX/A/a?name=xiaoming
執行結果如下:
Agray[10.4.XX.XX] -> B[10.4.XX.XX] -> C[10.4.XX.XX]%
- 6. 登錄 MSE 治理中心控制臺,在應用詳情頁面,可以看到灰度流量已經進入到灰度的 Pod 中。
(4)全量發布應用
結果驗證通過之后,確認全量發布。
- 在 Jenkins 控制臺中,單擊目標流水線名稱。
- 單擊需要全量發布的階段,在請確認是否全量發布對話框中輸入 true,然后單擊確認。
- 在容器服務控制臺,發現 spring-cloud-a-gray 應用已經被刪除,并且 spring-cloud-a 應用的鏡像已經替換為 spring-cloud-a:gray 版本。
- 在 MSE治理中心控制臺,發現灰度流量已經消失。
(5)回滾應用
如果發現驗證結果不符合預期時,則回滾應用。
- 在 Jenkins 控制臺中,單擊目標流水線名稱。
- 單擊需要全量發布的階段,在請確認是否全量發布對話框中輸入 false,然后單擊確認。
- 在容器服務控制臺,發現 spring-cloud-a-gray 應用已經被刪除,并且 spring-cloud-a 應用的鏡像仍然是老版本。
- 在 MSE 治理中心控制臺,發現灰度流量已經消失。
4.總結
在微服務治理架構中,全鏈路灰度功能能提供虛擬泳道,極大的方便了測試、發布時的快速驗證,能夠幫助 DevOPs 提升線上穩定性。阿里云微服務引擎(MSE)能夠給您帶來全生命周期的、全方位的微服務治理能力,保障您的線上穩定性、提升開發、運維效率。相關鏈接:
參考文檔:https://github.com/aliyun/alibabacloud-microservice-demo/blob/master/mse-simple-demo/helm/mse-simple-demo/README.md
示例代碼倉庫地址:https://gitee.com/mse-group/alibabacloud-microservice-demo/tree/master/mse-simple-demo
容器服務控制臺:https://cs.console.aliyun.com/#/k8s/cluster/list
MSE治理中心控制臺:https://mse.console.aliyun.com/#/overview?
使用 kaniko 構建和推送容器鏡像:https://help.aliyun.com/document_detail/106712.htm?