返回文章列表

雲原生微服務架構 CI/CD 實踐

本文探討雲原生與微服務架構下的 CI/CD 最佳實踐,涵蓋從單體架構到雲原生架構的演進、無伺服器架構的優勢、持續整合與持續佈署的定義和區別,以及 CI/CD 工具的選擇與 Jenkins Pipeline as Code 的應用。

雲原生 DevOps

雲原生應用程式藉由容器化和微服務架構,實作了高度的彈性、可擴充套件性和可維護性。然而,要充分發揮雲原生架構的優勢,必須搭配完善的 CI/CD 流程。從程式碼提交到自動化測試、構建和佈署,CI/CD Pipeline確保了軟體交付的快速、可靠和高效。本文將會詳細介紹如何利用 Jenkins 建立 CI/CD Pipeline,並探討 Jenkinsfile 的結構、Blue Ocean 的應用以及 GitFlow 模型的整合,以協助開發團隊更好地實踐雲原生 CI/CD。

雲原生與微服務架構下的 CI/CD

雲原生技術的崛起

雲原生(Cloud Native)是一種在現代動態環境中構建和執行可擴充套件應用程式的方法。根據雲原生計算基金會(CNCF)的定義,雲原生技術使組織能夠在公有、私有和混合雲等動態環境中構建和執行可擴充套件的應用程式。容器、服務網格、微服務、不變基礎設施和宣告式 API 等技術是雲原生的典型代表。這些技術使得系統之間的耦合度降低,提高了系統的彈性、可管理性和可觀察性。結合強大的自動化工具,工程師可以頻繁地進行高影響力的變更,並且可以預測變更的結果,同時將工作量降至最低。

雲原生應用的特點

雲原生應用程式被封裝在輕量級的容器中,並以微服務的形式高效佈署。它們使用輕量級的 API 來暴露功能,並透過二進位制和非二進位制協定在內部進行通訊。進一步地,這些應用程式透過敏捷的 DevOps 流程和持續交付工作流程,在彈性的雲基礎設施上進行管理。

雲原生應用的好處

  • 無維運開銷:開發人員可以專注於開發功能和增加業務價值,而不必處理基礎設施的供應和管理。
  • 安全合規:由於應用程式的不同部分被隔離,因此需要簡化的安全監控。一個容器中的安全問題不會影響到應用程式的其他部分。
  • 自動擴充套件:容器可以佈署到不同可用區甚至多個隔離的資料中心(區域)的伺服器叢集中。因此,雲原生應用程式可以利用雲的彈性,在使用高峰期間擴充套件資源,而無需採購和供應物理伺服器。
  • 開發速度:應用程式架構易於理解,因為每個容器代表一個小的功能,並且易於修改。因此,新團隊成員可以快速上手。
  • 彈性:雲原生微服務透過在每個服務之間提供適當的隔離,允許在粒度級別上進行故障處理。它們提供了多種設計模式,可以提高元件的可用性和彈性,例如斷路器(Circuit Breaker)、限流(Throttling)和重試(Retry)模式。

從單體架構到雲原生架構的演進

圖1.3展示了單體架構、微服務架構和雲原生架構之間的區別。雲原生架構允許動態擴充套件,支援大規模的分散式應用程式。

無伺服器架構

無伺服器計算模型始於2014年AWS Lambda的推出。在這種架構中,開發人員可以編寫成本效益高的應用程式,而無需供應或維護複雜的基礎設施。

無伺服器架構的優勢

無伺服器架構進一步簡化了應用程式的佈署和維運,降低了成本,提高了資源利用率。

走向雲原生架構

雲端供應商將客戶的程式碼佈署到完全託管、短暫且有時間限制的容器中,這些容器僅在函式呼叫期間存在。因此,企業可以擴充套件而無需擔心水平擴充套件或維護複雜的基礎設施。

重大注意事項

無伺服器並不意味著「無維運」。使用無伺服器服務時,您仍需要處理監控、佈署和安全問題。

根據無伺服器架構構建的應用程式可能如圖1.4所示。

圖1.4 無伺服器應用程式範例

此圖示呈現了一個典型的無伺服器應用程式架構。

圖表翻譯: 圖1.4顯示了一個無伺服器應用程式的範例架構,其中靜態網頁應用託管於Amazon S3,HTTP請求透過Amazon API Gateway觸發AWS Lambda函式,後者處理應用邏輯並將資料儲存至DynamoDB等完全託管的資料函式庫服務。

與其維護專用的容器或例項來託管靜態網頁應用,不如結合Amazon Simple Storage Service(S3)儲存桶,以更低的成本實作可擴充套件性。來自網站的HTTP請求透過Amazon API Gateway HTTP端點,觸發正確的AWS Lambda函式來處理應用邏輯,並將資料持久化到完全託管的資料函式庫服務(如DynamoDB)。對於特定的使用場景,無伺服器架構具有多項優勢:

  • 減少維運負擔:基礎設施由雲端供應商管理,降低了維運負擔並提高了開發人員的工作效率。作業系統更新和修補由函式即服務(FaaS)供應商負責。
  • 水平自動擴充套件:函式成為擴充套件的基本單位,導致小型、鬆散耦合、無狀態的元件,從而在長期內實作可擴充套件的應用程式。此外,擴充套件機制轉移到雲端供應商,由其決定如何有效地利用基礎設施來服務客戶請求。
  • 成本最佳化:您只需為所消耗的計算時間和資源付費。因此,您無需為閒置資源付費,從而顯著降低了基礎設施成本。
  • 多語言支援:另一個好處是能夠根據使用場景選擇不同的語言執行時。應用程式的一部分可以用Java編寫,而另一部分可以用Python編寫;只要能完成任務,語言選擇並不重要。

重大注意事項

在採用無伺服器架構時,一個重要的考慮因素是供應商鎖定問題。儘管應該優先考慮開發速度和效率,但根據使用場景選擇供應商仍然很重要。

定義持續整合

持續整合(CI)是一種實踐,即擁有分享和集中的程式碼倉函式庫,並將所有變更和功能透過複雜的Pipeline,在將它們整合到中央倉函式庫(如GitHub、Bitbucket或GitLab)之前進行驗證。典型的CIPipeline如下:

  1. 觸發構建:當程式碼提交發生時觸發構建。
  2. 執行單元測試和預整合測試(品質和安全測試)。
  3. 構建工件(例如Docker映像、zip檔案、機器學習訓練模型)。
  4. 執行驗收測試並將結果推播到工件管理倉函式庫(如Docker Registry、Amazon S3儲存桶、Sonatype的Nexus或JFrog Artifactory)。

圖1.5 雲原生應用的基本CI工作流程

此圖示呈現了一個基本的CI工作流程,用於雲原生應用。

圖表翻譯: 圖1.5顯示了一個雲原生應用的基本CI工作流程,包括從GitHub取得程式碼,透過Jenkins進行自動化測試和構建,最終將Docker映像推播到Docker Registry。

基本上,CI自動監控每個開發人員提交的程式碼,並啟動自動化測試。自動化測試是CI/CDPipeline的重要組成部分。沒有自動化測試,CI/CDPipeline將缺乏品品檢查,這對於應用程式的發布至關重要。

定義持續佈署

您可以實施各種型別的測試,以確保軟體符合所有初始需求。以下是一些最常見的測試型別:

  • 單元測試:測試原始碼的每個部分。它們包括測試個別功能和方法。
  • 品質測試:檢查程式碼是否格式良好,遵循最佳實踐,並且沒有嚴重的編碼錯誤。
  • 安全測試:檢查原始碼以發現常見的安全漏洞和安全缺陷。
  • UI測試:透過系統模擬使用者行為,以確保應用程式在所有支援的瀏覽器和平台上正確執行。
  • 整合測試:檢查應用程式使用的服務或元件是否協同工作,沒有缺陷。

手動執行所有這些測試可能耗時且適得其反。因此,您應該始終使用適合應用程式需求的測試框架,以可重複和可靠的方式執行這些測試。

持續佈署(CD)

持續佈署是持續整合的延伸。持續佈署Pipeline中的每個變更,在透過所有階段後,都會自動釋出到預生產環境。在這種過程中,無需決定什麼時候佈署。Pipeline將自動佈署成功離開Pipeline的構建元件/包。

圖1.6 微服務在Kubernetes上的典型CI/CDPipeline

此圖示呈現了微服務在Kubernetes上的典型CI/CDPipeline。

圖表翻譯: 圖1.6顯示了一個典型的CI/CDPipeline,用於在Kubernetes上執行的微服務,包括從程式碼提交到最終佈署的全過程。

然而,純粹的持續佈署方法並不總是適合每個人。例如,許多客戶不希望新版本頻繁地出現在他們面前,他們更喜歡可預測和透明的發布週期。

CI/CD 的基本概念與重要性

CI/CD(持續整合/持續佈署)是現代軟體開發中的關鍵實踐,能夠顯著提升開發效率和軟體品質。企業在採用 CI/CD 時,需要考慮商業和市場因素,以決定何時佈署新版本。

持續佈署與持續交付的區別

持續佈署(Continuous Deployment)是指在透過所有測試後,自動將軟體佈署到生產環境。而持續交付(Continuous Delivery)則需要在佈署到生產環境前進行人工干預或商業決策。持續交付是 DevOps 實踐的絕對要求,只有持續交付程式碼,才能在按下「啟動」按鈕的幾分鐘內為客戶提供價值。

CI/CD 練習的成熟度模型

此圖示展示了 CI/CD 各個實踐之間的關係。 圖表翻譯: 上圖展示了 CI/CD 的成熟度模型,從持續整合到持續交付,最終達到持續佈署。每一步都是軟體開發流程中的重要環節。

採用 CI/CD 實踐的好處

採用 CI/CD 實踐可以為雲原生應用程式帶來更大的敏捷性,主要體現在以下幾個方面:

  1. 早期檢測異常:透過單元測試和功能測試,可以減少技術債務,降低風險。
  2. 構建使用者需要的功能:透過快速反饋,產品團隊可以專注於最受需求的功能,構建高品質的產品。
  3. 加速上市時間:擁有一個隨時可用的生產就緒包,可以加快產品的上市時間。
  4. 提高產品品質和可靠性:透過品質和壓力測試,跟蹤專案的狀態和健康狀況。
  5. 推動創新:透過每次迭代,根據反饋構建高品質的產品。

程式碼範例:基本的 CI/CD 工作流程

# 定義 CI/CD 工作流程
stages:
  - build
  - test
  - deploy

# 編譯階段
build:
  stage: build
  script:
    - docker build -t myapp .

# 測試階段
test:
  stage: test
  script:
    - docker run myapp /bin/bash -c "pytest tests/"

# 佈署階段
deploy:
  stage: deploy
  script:
    - docker tag myapp:latest myregistry/myapp:latest
    - docker push myregistry/myapp:latest

內容解密:

  1. stages 定義了 CI/CD 的三個階段:編譯、測試和佈署。
  2. build 階段使用 Docker 編譯應用程式。
  3. test 階段執行測試案例,確保應用程式的功能正確性。
  4. deploy 階段將編譯好的 Docker 映像推播到遠端倉函式庫。

挑戰與解決方案

從手動佈署轉向高度自動化的 CI/CD 流程需要數月的時間。因此,公司需要逐步採用 CI/CD。首先自動化原始碼編譯的過程,然後優先進行功能測試,而不是 UI 測試。同時,需要有明確的產品路線圖和高品質的開發紀律。

CI/CD 工具的選擇

現代 CI 工具需要具備快速、使用者友好和靈活性的特點。主要的 CI 工具分為三類別:

  1. 雲端管理解決方案:如 AWS CodePipeline、Google Cloud Build 和 Microsoft Azure Pipelines。
  2. 開源解決方案:如 Jenkins、Spinnaker 和 GoCD。
  3. SaaS 解決方案:如 Travis CI、CircleCI 和 TeamCity。

本文將介紹如何為雲原生架構(如 Dockerized 微服務和 Lambda-based 無伺服器應用程式)構建 CI/CD 管道,並探討如何管理和擴充套件 CI 工具以提高佈署速度。

使用必要的CI/CD工具

選擇CI/CD工具

圖1.9展示了目前市場上最受歡迎的CI/CD工具。這些工具已經相當成熟,具備了專案所需的基本功能。

在眾多優秀的CI工具中,選擇最合適的工具需要考慮以下因素:

  • 團隊經驗和技能:雖然許多工具使用YAML檔案來宣告CI/CD流程,但它們可能需要一些系統管理技能來設定和提供所需的基礎設施來執行CI/CD平台。此外,維護基礎設施可能會帶來很多麻煩,並成為公司成長的瓶頸,尤其是當專案程式碼函式庫變得更大時(擴充套件能力)。因為需要在多個節點或伺服器上維護分散式的CI/CD複雜流程。
  • 目標平台:考慮應用程式或專案執行的作業系統(一些CI工具不支援macOS和ARM架構),以及是否使用自託管基礎設施或雲端供應商。
  • 程式語言和架構:大多數CI工具支援頂級的程式語言,如Java、Ruby、Python、PHP和JavaScript。然而,一些工具如TeamCity對Java和.NET專案提供了更好的整合和支援。同樣,Bamboo作為Atlassian的產品,對Jira和Bitbucket有原生支援。此外,佈署解決方案也可能是選擇正確CI工具的因素。例如Drone(www.drone.io)和GitLab CI(https://docs.gitlab.com/ee/ci/)提供了原生Docker支援和整合的Docker登入檔。

Jenkins介紹

儘管沒有任何一個工具可以滿足每個專案的需求,但在本文中,我們將大量依賴Jenkins。它被認為是目前市場上最受歡迎的CI工具之一,擁有超過一百萬使用者。它是用Java編寫的,使其成為跨平台(Windows、Linux和macOS)的持續整合工具。

Jenkins最初是Hudson專案的一部分,由於與Oracle在商標上的衝突,在Sun Microsystems被Oracle收購後,社群和程式碼函式庫分道揚鑣。Hudson最初於2005年發布,而Jenkins的第一個版本於2011年發布。

Jenkins的特點

  • 透過龐大的社群貢獻的外掛資源(超過1,400個外掛)進行擴充套件。
  • 免費且開源,同時CloudBees(www.cloudbees.com/jenkins)提供了付費的企業版,具有快速的客戶支援。
  • 擁有活躍的社群,幫助開發者減少建立可用的CI/CD工作流程所需的時間。
  • 可以在本地佈署或在雲端佈署,透過使用者介面或命令列進行簡單的組態。
  • 支援分散式構建,具有主從式架構和內建的平行處理機制。
  • 是一個強大且靈活的工具,對工作流程具有完全的控制,可以滿足每一個CI/CD需求。
  • 支援多種平台,並對多種工具和框架提供支援。
  • 支援將容器用作建置代理,適用於計劃使用Docker的團隊。
  • 與GitHub、GitLab、Bitbucket和大多數原始碼管理(SCM)系統以及Apache Subversion(SVN)無縫整合。

Jenkins Pipeline as Code

Jenkins的另一個關鍵特性是Pipeline as Code。我們將使用這種方法來建立Jenkins任務。使用這種方法的酷炫之處在於,我們的整個Jenkins任務組態可以與應用程式原始碼的其他部分一起建立、更新和版本控制。

值得注意的是,Jenkins必須託管在伺服器上,因此通常需要具備基礎設施技能的人員進行維護。不能只是設定它,然後期望它自己執行;系統需要頻繁的更新和維護。大多數團隊進入門檻是初始設定、拖延或以前設定失敗。人們傾向於知道它很好,但許多團隊因為更緊急的編碼工作而忽視它。也許團隊中的某個人曾經嘗試佈署Jenkins,但沒有成功維護它。也許浪費的努力給老闆留下了壞印象。

人們不實施Jenkins的原因通常是非常實際的。因此,在本文中,我們將使用基礎設施即程式碼的魔力,使用像Terraform和Packer這樣的開源工具,在大多數流行的公共雲供應商(如AWS、GCP和Microsoft Azure)上憑空設定我們的整個CI基礎設施。

另一個我們將在本文中解決的問題是如何編寫測試。編寫測試是大多數開發人員想要做的,但通常沒有時間去做。可以理解,編寫實際應用程式通常是業務的更高優先順序。此外,測試會中斷,這意味著當被測試的功能改變時,需要更新。如果功能不更新,它就會停止提供價值。我們將介紹如何在CI/CD流程中執行各種測試,以及如何整合外部程式碼分析工具。

總之,為雲原生架構實施CI/CD需要文化和思維方式的轉變,尤其是來自管理階層。管理者必須允許花時間在這件“非生產性”的事情上。

儘管短期內犧牲一些時間,但從長遠來看,這對整個公司有益。使用Jenkins,您的程式碼變得更容易維護,更少的錯誤進入生產環境。您的團隊變得更加整合,構建時間更短。您的業務可以更快地交付,並跟上客戶不斷變化的需求(透過更快地交付程式碼,組織可以快速回應變化,並保持產品在市場上的競爭力)。

以 Jenkins 實作 Pipeline as Code

在雲端運算的時代,企業開發、擴充套件和維護技術產品的方式已經發生了翻天覆地的變化。只需點選幾下按鈕就能組態機器、資料函式庫和其他基礎設施,這使得開發者的生產力達到前所未有的高度。然而,在組態複雜的雲端架構時,人為錯誤總是在所難免,特別是在使用雲端服務供應商的網頁控制檯時。

本章將探討如何利用 Jenkins 實作 Pipeline as Code,包括 Jenkinsfile 的結構和語法、Blue Ocean 的介紹、宣告式與指令碼式 Jenkins Pipeline 的比較,以及如何在 Jenkins 專案中整合 GitFlow 模型。

2.1 介紹 Jenkinsfile

Pipeline as Code(PaC)是一種允許 Jenkins 使用者透過程式碼定義 Pipeline 作業流程的功能,這些程式碼儲存在原始碼倉函式庫中並進行版本控制。Jenkins 可以自動發現、管理並執行多個原始碼倉函式庫和分支的作業,從而無需手動建立和管理作業。

要使用 PaC 功能,專案必須在原始碼倉函式庫的頂層資料夾中包含一個名為 Jenkinsfile 的檔案。這個範本檔案包含了將在 Jenkins 上執行的指令或步驟,稱為階段(stages)。每當開發團隊將新功能推播到原始碼倉函式庫時,Jenkins 就會執行這些階段。

Jenkinsfile 範例

以下是一個簡單的 Jenkinsfile 範例,對應於典型的 CI/CD 工作流程:

node('workers'){
    try {
        stage('Checkout'){
            checkout scm
        }
        stage('Quality Test'){
            echo "Running quality tests"
        }
        stage('Unit Test'){
            echo "Running unit tests"
        }
        stage('Security Test'){
            echo "Running security checks"
        }
        stage('Build'){
            echo "Building artifact"
        }
        stage('Push'){
            echo "Storing artifact"
        }
    }
}

內容解密:

  1. node('workers'):指定在名為 workers 的節點上執行 Pipeline。
  2. try:用於捕捉異常,確保 Pipeline 的穩定執行。
  3. stage:定義 CI/CD 工作流程中的不同階段,如程式碼簽出、品質測試、單元測試等。
  4. checkout scm:從原始碼管理系統(SCM)簽出程式碼。
  5. echo:輸出資訊到控制檯,用於除錯或記錄。

Pipeline as Code 的優勢

採用 PaC 可以帶來多方面的好處,包括:

  • 速度:可以快速為不同環境(如沙盒、預釋出和生產環境)編寫 CI/CD 工作流程,加速產品交付。
  • 一致性:標準化 CI/CD 的設定,減少人為錯誤或偏差。
  • 風險管理:對 CI/CD 工作流程的變更進行版本控制,就像應用程式碼一樣,可以追蹤、測試並在必要時回復到工作版本。
  • 效率:減少人為錯誤,使應用程式的佈署更加順暢。

圖表翻譯:

@startuml
skinparam backgroundColor #FEFEFE

title 雲原生微服務架構 CI/CD 實踐

|開發者|
start
:提交程式碼;
:推送到 Git;

|CI 系統|
:觸發建置;
:執行單元測試;
:程式碼品質檢查;

if (測試通過?) then (是)
    :建置容器映像;
    :推送到 Registry;
else (否)
    :通知開發者;
    stop
endif

|CD 系統|
:部署到測試環境;
:執行整合測試;

if (驗證通過?) then (是)
    :部署到生產環境;
    :健康檢查;
    :完成部署;
else (否)
    :回滾變更;
endif

stop

@enduml

圖表翻譯: 此圖示展示了一個典型的 CI/CD 工作流程。首先從原始碼倉函式庫簽出程式碼,然後進行品質測試、單元測試和安全測試。接著,構建應用程式並將生成的構件推播到指定的位置。