通過Jenkins構建CI/CD實現全鏈路灰度

語言: CN / TW / HK

作者:卜比

本文介紹通過 Jenkins 構建流水線的方式實現全鏈路灰度功能。

在釋出過程中,為了整體穩定性,我們總是希望能夠用小部分特定流量來驗證下新發布應用是否正常。

即使新版本有問題,也能及時發現,控制影響面,保障了整體的穩定性。

整體架構

我們以如下 Demo 為例:

1.png

為了保證穩定,我們約定如下上線流程:

2.png

其中,在灰度驗證中,有幾種不同的策略:

  • 直接使用線上小部分流量來測試(按照百分比放量)
  • 從線上按照特定規則選擇流量(比如特定的 header、特定的 cookie 等)
  • 在客戶端或瀏覽器上標識出流量是否灰度(比如通過 header 傳遞)

部署應用&建立泳道

按照參考文件部署應用後,我們首先要區分線上流量和灰度流量。

建立泳道組,將整個鏈路涉及到的應用全選:

3.png

然後建立泳道組,將符合規則的應用劃入 gray 泳道:

4.png

注:沒有匹配的流量,會走到基線環境,也就是沒有打標的應用節點上。

配置完成後,訪問閘道器,如果不符合灰度規則,走基線環境:

5.png

如何符合灰度規則,走灰度環境:

6.png

配置 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

在 Jenkins 中建立全鏈路灰度釋出流水線

基於 Jenkins 實現自動化釋出的流水線,通過該流水線可以使應用釋出具備可灰度、可觀測、可回滾的安全生產三板斧能力。

  1. 在 Jenkins 控制檯左側導航欄單擊新建任務

  2. 輸入任務名稱,選擇流水線,然後單擊確定

  3. 在頂部選單欄單擊流水線頁籤,在流水線區域配置相關引數選擇,輸入指令碼路徑,然後單擊儲存

7.png

    • 定義:選擇 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" } } } } } } ```

構建 Jenkins 流水線

  1. 在 Jenkins 控制檯單擊流水線右側的圖示。

  2. 單擊流水線的開始構建

說明:第一次構建因為需要從 Git 倉庫拉取配置並初始化流水線,所以可能會報錯,再次執行 Build with Parameters,生成相關的引數,填寫相關的引數,再次執行構建。

8.png

檢視部署狀態,程式碼打包,映象構建及釋出,灰度部署階段都已經完成,結束灰度階段等待確認。

9.png

    • 如果驗證結果符合預期,則執行全量釋出,請參見後文的全量釋出應用。
    • 如果驗證結果不符合預期時,則執行回滾,請參見後文的回滾應用。

結果驗證

  1. 登入容器服務控制檯,在控制檯左側導航欄中,單擊叢集

  2. 叢集列表頁面中,單擊目標叢集名稱或者目標叢集右側操作列下的詳情

  3. 在叢集管理頁面左側導航欄選擇工作負載 > 無狀態

  4. 無狀態應用列表頁面,spring-cloud-a-gray應用已經自動建立,並且它的映象已經替換為spring-cloud-a:gray版本。

10.png

  1. 在叢集管理頁面左側導航欄選擇網路 > 服務,選擇設定的名稱空間,單擊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]%

  1. 登入 MSE 治理中心控制檯,在應用詳情頁面,可以看到灰度流量已經進入到灰度的 Pod 中。

11.png

全量釋出應用

結果驗證通過之後,確認全量釋出。

  1. 在 Jenkins 控制檯中,單擊目標流水線名稱。

  2. 單擊需要全量釋出的階段,在請確認是否全量釋出對話方塊中輸入 true,然後單擊確認

12.png

  1. 在容器服務控制檯,發現 spring-cloud-a-gray 應用已經被刪除,並且 spring-cloud-a 應用的映象已經替換為 spring-cloud-a:gray 版本。

13.png

  1. 在 MSE治理中心控制檯,發現灰度流量已經消失。

14.png

回滾應用

如果發現驗證結果不符合預期時,則回滾應用。

  1. 在 Jenkins 控制檯中,單擊目標流水線名稱。

  2. 單擊需要全量釋出的階段,在請確認是否全量釋出對話方塊中輸入 false,然後單擊確認

15.png

  1. 在容器服務控制檯,發現 spring-cloud-a-gray 應用已經被刪除,並且 spring-cloud-a 應用的映象仍然是老版本。

16.png

  1. 在 MSE 治理中心控制檯,發現灰度流量已經消失。

17.png

總結

在微服務治理架構中,全鏈路灰度功能能提供虛擬泳道,極大的方便了測試、釋出時的快速驗證,能夠幫助 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