天天看點

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

作者:閃念基因

1.背景介紹

CI/CD是一種通過在應用開發階段引入自動化來頻繁向客戶傳遞應用的方法。CI/CD 的核心概念是持續內建、持續傳遞和持續部署。作為一種面向開發和運維團隊的解決方案,CI/CD 主要針對在內建新代碼時所引發的問題(亦稱:“內建地獄”)。CI/CD建立了一個可重複的、可靠的且可預見的釋出流程,進而大大縮短了釋出周期,不僅節省下了巨大的金錢成本,還節省了包括建立和維護這樣一個釋出系統所需要的時間投入。

在引入CI/CD技術之前,公司測試人員自動化打包主要依賴Jenkins實作,在配置任務的源碼、建構觸發器、建構環境、建構、建構後操作等步驟後,可以觸發建構任務。相比傳統的拉代碼、運作指令打包、整理上傳更新檔案,重新開機服務等繁瑣的操作,Jenkins任務建構這種方式在一定程度上節省了測試和研發人員的時間。但随着代碼倉庫數量的日益增長,以及Jenkins在公司内部使用程度越來越深,一些問題也逐漸暴露。例如:

  • 每一套代碼或服務都需要繁瑣的job配置工作,且大部分是重複勞動。
  • 研發人員和測試人員都在使用Jenkins,需要一定的學習成本。
  • 缺少打包結果通知,不能及時擷取打包結果。
  • 建構完成後需要手動下載下傳歸檔檔案,并整理後建立更新任務。
  • 公用測試環境,頻繁更新重新開機服務(特别是封版期間)導緻服務中斷的問題。

為了解決以上問題,我們使用了Kubernetes 原生 CI/CD 建構架構Tekton和基于Kubernetes的聲明式持續傳遞工具Argo CD,并将流水線接入項目管理平台Redmine,簡化了代碼打包步驟、降低了使用人員的學習成本、提供穩定的測試環境、自動粘貼歸檔檔案下載下傳連結、自動建立更新任務等,進一步提高了持續內建的效率。

2. 系統設計

流水線系統設計以項目管理平台為入口,Kubernetes為環境基礎,使用Tekton完成CI部分功能,在建構完成後更新服務編排檔案。Argo CD則負責持續監控應用狀态,并更新應用。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

2.1Kubernetes簡介

Kubernetes是一個開源的,用于管理雲平台中多個主機上的容器化的應用,Kubernetes的目标是讓部署容器化的應用簡單并且高效(powerful),Kubernetes提供了應用部署、規劃、更新、維護的一種機制。

Kubernetes一個核心的特點就是能夠自主的管理容器來保證雲平台中的容器按照使用者的期望狀态運作着(比如使用者想讓apache一直運作,使用者不需要關心怎麼去做,Kubernetes會自動去監控,然後去重新開機,建立,總之,讓apache一直提供服務),管理者可以加載一個微型服務,讓規劃器來找到合适的位置,同時,Kubernetes也系統提升工具以及人性化方面,讓使用者能夠友善的部署自己的應用(就像canary deployments)。

2.2Tekton簡介

Tekton 是一個基于 Kubernetes 的雲原生 CI/CD 開源架構,屬于 CD 基金會的項目之一。Tekton 通過定義 CRD 的方式,讓使用者以靈活的自定義流水線以滿足自身 CI/CD 需求。

Tekton 最主要的四個概念為:Task、TaskRun、Pipeline 以及 PipelineRun。

  • Task: Task 為建構任務,是 Tekton 中不可分割的最小機關,正如同 Pod 在 Kubernetes 中的概念一樣。在 Task 中,可以有多個 Step,每個 Step 由一個 Container 來執行。
  • Pipeline: Pipeline 由一個或多個 Task 組成。在 Pipeline 中,使用者可以定義這些 Task 的執行順序以及依賴關系來組成 DAG(有向無環圖)。
  • PipelineRun: PipelineRun 是 Pipeline 的實際執行産物,當使用者定義好 Pipeline 後,可以通過建立 PipelineRun 的方式來執行流水線,并生成一條流水線記錄。
  • TaskRun: PipelineRun 被建立出來後,會對應 Pipeline 裡面的 Task 建立各自的 TaskRun。一個 TaskRun 控制一個 Pod,Task 中的 Step 對應 Pod 中的 Container。當然,TaskRun 也可以單獨被建立。

綜上:Pipeline 由多個 Task 組成,每次執行對應生成一條 PipelineRun,其控制的 TaskRun 将建立實際運作的 Pod。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

2.3Argo CD 簡介

Argo CD 是一個為 Kubernetes 而生的,遵循聲明式 GitOps 理念的持續部署(CD)工具,它的配置和使用非常簡單,并且自帶一個簡單易用的 Dashboard 頁面,并且支援多種配置管理/模闆工具(例如 Kustomize、Helm、Ksonnet、Jsonnet、plain-YAML)。

Argo CD 被實作為一個 Kubernetes 控制器,它持續監控應用的實際狀态,周期性地拉取 Git 倉庫中的配置清單,并将實際狀态與期望狀态進行比較,如果實際狀态不符合期望狀态,就會更新應用的實際狀态以比對期望狀态。

Argo CD的主要功能:

  • 可搭配使用各種配置管理工具(如 ksonnet/jsonnet、Helm 和 kustomize)使應用程式與 Git 中定義的保持一緻。
  • 将應用程式自動部署到指定的目标環境。
  • 持續監控已部署的應用程式。
  • 基于 Web 和 CLI 的操作,以及應用程式可視化。

部署或復原到 Git 倉庫中送出的應用程式的任何狀态(這也是使用 Git 進行版本管理的一大好處。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

2.4項目管理平台Redmine

政通項目管理平台是流水線使用的入口系統,在同步儲存Gitlab倉庫、分支、CI/CD參數後,新增流水線任務時将參數傳給Tekton。流水線任務執行時,會将目前流水線資訊推送到項目管理平台。

流水線打包成功後會将歸檔路徑推送到項目管理平台。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

新增流水線時如果勾選了建立更新任務,也會在流水線打包成功後自動建立更新任務。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

新增流水線時選擇運作測試環境,則會通過Argo CD更新測試服務。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

流水線運作異常時,會将相關資訊推送到項目管理平台,友善排查問題。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

3. 流水線的使用

下面以wizdom-urban-v14代碼為例,介紹流水線打包如何使用。

(1)步驟一:Gitlab參數配置。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路
  • tekton_pipeline_enable:是否啟用流水線,如true。
  • tekton_pipeline_name:流水線名稱,如“執法-vue前端”。
  • tekton_pipeline_extra_params:新增流水線頁面額外顯示的參數,多個參數逗号分隔。可選值:npm_build_params(插件名)。
  • tekton_pipeline_before_hook:僅用于多app前端倉庫,送出記錄中src/pages/後面一級目錄作為打包參數。如:hook_plugins_by_src_pages、hook_plugins_by_src_views。流水線建構中如果需要使用更多參數,可以配置以“tekton_hook_param_”為字首的參數名,流水線任務預處理會判斷并截取這樣的參數。

(2)步驟二:Redmine同步配置管理--項目管理--gitlab同步,同步倉庫、分支、變量。代碼倉庫會在代碼送出後自動同步。變量隻需要在修改後同步1次即可。

(3)步驟三:新增提測單項目管理平台任務處理完成以後,點選任務右上角“生成提測”功能按鈕,從列出的根據送出記錄查詢的代碼倉庫和分支清單中,選擇需要使用的流水線打包的代碼倉庫和分支。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

(4)步驟四:新增流水線。以上步驟完成後,就來到了最關鍵最常用的新增流水線環節,在任務界面點選右上角“新增流水線”功能按鈕,填寫相關資訊。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

背景會根據提測單自動填充部分内容,如有調整,可手動修改。

參數說明如下:

  • 選擇流水線:根據提測單代碼倉庫自動選擇流水線類型。
  • 開始打包時發送通知:根據釘釘token給測試人員(成功或失敗時)和對應的開發人員發送通知(失敗時),一般預設都勾選。
  • 是否生成更新任務:用于生成目前任務的子系統,提供給測試人員發更新使用。面向研發人員是隐藏狀态。任務名稱和内容自動生成,可以自行編輯。
  • 是否運作測試環境:用于自動更新測試環境,預設不勾選,測試人員需要時勾選,結合“産品線”來判斷更新哪一套環境。
  • 測試環境目标版本(不填寫時将在後端自動計算):運作測試環境的目标版本。
  • 産品線:勾選運作測試環境後生效,用來判斷更新哪一套測試環境。
  • 歸檔類型:預設zip主代碼分支:根據提測單自動生成。
  • 項目代碼分支:根據提測單自動生成。
  • 資料庫類型:預設為mysql。如果有oracle和dm時自行切換。
  • 插件名:根據提測單自動生成,也可以手動填寫,以逗号分隔。
  • 歸檔的檔案和路徑(不含插件名對應的jar):主要是前端的檔案,多個以逗号分隔。根據提測單自動生成,也可以手動修改。
  • 額外歸檔的檔案或路徑:填寫其他還需要打包時包含的檔案或路徑,多個以逗号分隔。
  • 操作人:目前操作人,自動生成。
  • 操作人釘釘token:目前操作人的釘釘token,自動生成,用來發送消息通知。
  • 研發負責人(處理代碼異常問題):根據“實際研發處理人”自動生成。為空時不顯示此項。在流水線因代碼問題打包失敗時通知研發負責人。

大部分參數都不需要手動填寫,隻需要确認無誤後點選建立,流水線任務即建立成功,等待流水線自動打包完成即可。打包完成或者因代碼問題打包失敗會通知操作人。

4. 流水線任務處理流程

我們從流水線的任務處理流程、流水線任務和步驟來說明流水線中的關鍵技術。

4.1任務接收

流水線任務是通過TektonTrigger接收的,Tekton Trigger是Tekton的一個元件,它可以從各種來源的事件中檢測并提取需要資訊,然後根據這些資訊來運作TaskRun和PipelineRun,還可以将提取出來的資訊傳遞給它們以滿足不同的運作要求。其核心元件如下:

  • EventListener:事件監聽器,是外部事件的入口 ,通常需要通過HTTP方式暴露,以便于外部事件推送,例如項目管理平台的建立流水線操作。
  • Trigger:指定當EventListener檢測到事件發生時會發生什麼,它會定義TriggerBinding、TriggerTemplate以及可選的Interceptor。
  • TriggerTemplate:用于模闆化資源,根據傳入的參數執行個體化Tekton對象資源,比如TaskRun、PipelineRun等。
  • TriggerBinding:用于捕獲事件中的字段并将其存儲為參數,然後會将參數傳遞給TriggerTemplate。
  • ClusterTriggerBinding:和TriggerBinding相似,用于提取事件字段,不過它是叢集級别的對象。
  • Interceptor:攔截器,在TriggerBinding之前運作,用于負載過濾、驗證、轉換等處理,隻有通過攔截器的資料才會傳遞給TriggerBinding。
雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

Tekton Trigger在接收Redmine送出的流水線請求時,使用Interceptor驗證請求、解析參數,包含了新增流水線請求RequestBody的值和根據代碼倉庫id查詢的Gitlab代碼倉庫的CI/CD參數,根據參數值啟動對應的PipelineRun,如智信h5打包的build-mobile-h5或build-mobile-h5-npm。

4.2任務執行

PipelineRun通過pipelineRef指定要運作的Pipeline,Pipeline中定義了多個Task,每個Task又包含一個或多個Step。 以wizdom-urban-v14代碼的流水線為例,主要Task及其執行順序如下:

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路
  • copy-all-code:複制緩存的代碼。
  • fetch-main-code:拉取主代碼。
  • fetch-project-code:拉取項目定制代碼。
  • profiles-resolve:解決profile定義問題,包括合并主架構代碼和項目定制代碼、解析要打包的profile、解決依賴定義問題。
  • maven-run:運作打包。
  • archive:打包結果歸檔。
  • dockerfile:處理war打包結構,生成DockerFile内容
  • docker-build:建構docker鏡像,并将鏡像推送到鏡像倉庫
  • fetch-argocd-app-code:拉取Argo CD配置檔案代碼倉庫
  • branch-to-argocd-version:更新部署檔案的鏡像版本
  • mis-argocd-app:
  • push-argocd-app-code:将修改後的代碼送出推送到Gitlab倉庫。
  • argocd-task-sync-and-wait:觸發Argo CD同步,并等待驗證服務啟動成功。
  • dingtalk-app-start-success:通知服務更新成功。
  • redmine-new-update-task:項目管理平台建立更新更新任務。
  • delete-files:删除臨時檔案。
  • message-dingtalk:建構結果通知釘釘通知。
  • message-dingtalk-without-task: 建構結果通知釘釘通知。
  • message-redmine:打包成功的推送redmine。

除了以上流水線打包的任務外,還在finally部分指定了多個最終任務(finally task),無論Tasks部分聲明的正常任務執行成功還是報錯,最終任務都會在正常任務執行完成後并行執行。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路
  • set-pipeline-run-status:更新項目管理平台任務狀态。
  • notify-admin-onerror:固定錯誤通知管理者。
  • notify-pom-group-onerror:mvn打包失敗發送給pom修正群。
  • notify-dev-onerror:mvn打包失敗發送給研發通知。
  • redmine-comment-onerror:帶有任務号的流水線推送打包錯誤内容到任務上。
  • redmine-comment-on-mvnerror:打包錯誤内容推送到任務上。
  • message-op-user-on-npmerror:打包錯誤内容消息給操作人。
  • message-op-user:消息通知操作人。

任務的執行順序是根據runAfter來決定的,未聲明runAfter的任務可以和其他任務并行執行。另外,隻有when中聲明的條件都滿足時任務才會執行,否則會跳過。例如redmine-new-update-task任務,需要等待歸檔任務(archive)完成後才可能執行,并且隻有當項目管理平台任務号不為空,且建立流水線任務時勾選了建立更新任務,才會在歸檔後建立項目管理平台更新任務。

name: redmine-new-update-task
  retries: 1
  taskRef:
    name: redmine
  runAfter:
    - archive
  when:
    - input: "$(params.issue_id)"
      operator: notin
      values: [ "" ]
    - input: "$(params.new_update_issue_flag)"
      operator: in
      values: [ "true" ]           

4.3典型任務和步驟

Pipeline中的任務雖然看起來非常多,但是大部分是可複用的。另外,與Pipeline中聲明的任務不同,Task中聲明的步驟(step)是按照聲明的順序依次執行的。我們以典型的任務profiles-resolve為例來說明,任務步驟執行順序如下:

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

各個步驟完成的内容為:

  • merge-code:合并主架構代碼和項目定制代碼。
  • profiles-resolve:解決profile定義不規範問題。
  • check-need-mvn:判斷是否需要maven建構,後續任務需要使用,例如判斷是否運作打包。
  • add-profiles-by-product:根據産品線追加profiles。
  • dependencies-fix:修複pom檔案中傳遞依賴定義不完整問題。
  • war-exclude:排查war打包,隻需要更新部分jar時,排斥war打包步驟能夠加快打包速度。
  • fix-git-commit-id-plugin:解決git-commit-id-plugin插件問題。
  • fix-repository:由于内網maven鏡像倉庫位址有調整,修改pom中定義的maven鏡像源。
  • fix-pom-commons-collections4:修複部分版本缺少commons-collections4。

profiles-resolve任務的很多額外步驟是為了解決代碼代碼不規範的問題,例如代碼中profile定義不完整,直接執行maven clean package -P pluginName1,pluginName2,…時,往往不能成功。在profiles-resolve步驟中,通過多次循環補充目前profiles依賴的其他profiles。雖然直接修改代碼也能解決這個問題,但是由于wizdom-urban-v14代碼插件非常多,分支也非常多,改起來會相當耗時。并且由于插件之間依賴關系比較複雜,開發過程中難以維持正确的依賴關系定義。

4.4釋出更新

由上文任務清單可知,服務更新其實也是包含在任務執行中的。我們借助Argo CD的自動同步和部署應用程式的優勢,在打包完成後,制作docker鏡像,并推送到鏡像倉庫。随後更新Argo CD部署檔案代碼,觸發Argo CD同步,Argo CD檢測到部署檔案更新後,将自動與K8S互動,更新服務。K8S滾動更新的特性,能夠在保證服務不中斷的情況下完成更新。

總結起來,流水線的使用流程如下圖:

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

5. 成果和計劃

相比傳統的Jenkins打包,流水線的優勢在于:

  • 省去了繁瑣的建構任務配置,簡化了啟動流程的步驟。研發和測試隻需要在任務平台上新增提測單,新增流水線即可,降低了學習成本。
  • 利用了K8S滾動更新的特性,可以在服務不中斷的情況下進行更新。
  • 任務中靈活的腳本處理,能夠在不改動代碼的情況下,完成依賴修複,鏡像倉庫位址替換等。
  • 任務中增加了異常處理,能夠在打包失敗時第一時間通知流水線操作人、研發處理人。并在項目管理平台任務重附上錯誤日志,便于即使排查解決問題。
  • 流水線完成後自動釋出歸檔檔案下載下傳連結,省去測試人員整理結果上傳百度雲的步驟,提高了工作效率。
  • 自動建立更新任務,測試人員無需手動建立更新任務并粘貼更新檔案下載下傳連結。

截止目前,流水線平台已歸納支援12種類型的代碼結構打包,主要包含了智雲主架構、智雲前端、智信前端、微服務、智雲拆分代碼、智信拆分代碼等。項目管理平台接入流水線僅半年就完成了打包任務數3987,流水線任務總運作8140次。通過Argo CD管理一網統管、資訊采集、城市大腦、基礎平台、市政、執法、星橋、靈珑、社會治理、運管服10條産品線,共67套運作環境。

雲原生架構下的産品自動化釋出、快速部署和持續傳遞實戰之路

後續計劃整合武漢的伺服器,全部虛拟化後,将各産品線測試環境全面接入流水線,研發、測試環境隔離互不幹擾,做到可按需開啟,定時關閉。利用流水線流程的易擴充性,接入單元測試、自動測試流程。

作者:evilkk

來源:微信公衆号:政通技術團隊

出處:https://mp.weixin.qq.com/s/VOgWvI9zdNPXE-QrwmfP1w

繼續閱讀