微服務架構的 CI/CD

Azure

更快速的發行週期是微服務架構的主要優點之一。 但是,如果沒有良好的 CI/CD 程式,您將無法達到微服務承諾的靈活度。 本文說明挑戰,並建議一些問題的方法。

什麼是 CI/CD?

當我們討論 CI/CD 時,我們真的討論數個相關程式:持續整合、持續傳遞和持續部署。

  • 持續整合。 程式碼變更經常合併到 main 分支中。 自動化建置和測試程式可確保主要分支中的程式碼一律是生產品質。

  • 持續傳遞。 傳遞 CI 程式的任何程式碼變更都會自動發佈至類似生產環境的環境。 部署至即時生產環境可能需要手動核准,除此之外皆是自動化作業。 這麼做的目的是,您的程式碼應該總是「準備好」部署到生產環境。

  • 持續部署。 通過上述兩個步驟的程式碼變更會自動部署到 生產環境

針對微服務架構,以下是強固 CI/CD 程序的一些目標:

  • 每個小組都可建置並部署獨立擁有的服務,而不會影響或干擾其他小組。

  • 將新版服務部署到生產環境之前,可先部署到開發/測試/QA 環境來進行驗證。 在每個階段上強制執行品質閘門 (Quality Gate)。

  • 新版本的服務可以與舊版並存部署。

  • 有足夠的存取控制原則。

  • 針對容器化工作負載,您可以信任部署至生產環境的容器映射。

為什麼強固的 CI/CD 管線很重要

在傳統的整合型應用程式中,有一個建置管線,其輸出是應用程式可執行檔。 所有開發工作都會饋送到此管線中。 如果發現高優先順序的錯誤 (bug),則必須整合、測試及發行修正程式,這可能會延遲新功能的發行。 您可以藉由擁有妥善要素的模組和使用功能分支,將程式碼變更的影響降到最低,以減輕這些問題。 但隨著應用程式日益複雜,並新增了更多功能,單體的發行程序就變得更加脆弱並可能中斷。

根據微服務的原理,絕不會有每個小組都必須排隊的冗長發行序列。 建立服務 "A" 的小組可以隨時發行更新,而不需等待服務 "B" 的變更來進行合併、測試和部署。

CI/CD 整合型的圖表

若要達到高發行速度,您的發行管線必須自動化且高度可靠,才能將風險降至最低。 如果您每天發行至生產環境一或多次,回歸或服務中斷必須很少見。 同時,如果部署了錯誤的更新,您必須有可靠的方法能快速復原或向前復原至舊版的服務。

挑戰

  • 許多小型獨立的程式碼基底。 每個小組需利用自己的建置管線,負責建立自己的服務。 在某些組織中,小組可以使用不同的程式碼存放庫。 個別存放庫可能會導致瞭解如何建置系統分散到小組的情況,且組織中沒有人知道如何部署整個應用程式。 例如,如果您需要快速部署到新的叢集,災害復原案例會發生什麼情況?

    風險降低:具有統一且自動化的管線來建置和部署服務,讓每個小組內不會「隱藏」此知識。

  • 多個語言和架構。 如果每個小組都使用自己的各項技術,則可能很難建立適用於整個組織的單一建置程序。 建置程序必須有足夠的彈性,每個小組才能針對其選擇的語言或架構進行調整。

    風險降低:將每個服務的建置程式容器化。 如此一來,建置系統就只需要能夠執行容器。

  • 整合及負載測試。 如果小組依照自己的步調發行更新,則要設計強固的端對端測試可能具有挑戰性,特別是在服務相依於其他服務時。 此外,執行完整生產叢集的成本可能很高,因此,每個小組不太可能在生產規模上執行自己的完整叢集,只是為了進行測試。

  • 發行管理。 每個小組都應該能夠將更新部署到生產環境。 但這不表示每個小組成員都有權限這麼做。 不過,擁有集中的發行管理員角色可能會降低部署的速度。

    風險降低:CI/CD 程式自動化且可靠越少,中央授權單位的需求就越少。 儘管如此,您可能使用不同的原則來發行主要功能更新和次要錯誤修正。 非集中式並不表示零控管。

  • 服務更新。 當您將服務更新為新版本時,其不得中斷與其相依的其他服務。

    風險降低:針對非中斷性變更使用部署技術,例如藍綠或 Canary 版本。 如需重大 API 變更,請與舊版並存部署新版本。 如此一來,取用先前 API 的服務就可以針對新的 API 進行更新和測試。 請參閱下方 的更新服務

Monorepo 與多重存放庫

建立 CI/CD 工作流程之前,您必須知道如何結構化和管理程式碼基底。

  • 小組是否在個別的存放庫或單一存放庫 (單一存放庫) ?
  • 您的分支策略是什麼?
  • 誰可以將程式碼推送至生產環境? 有版本管理員角色嗎?

雖然 monorepo 方法較受青睞,但這兩者都有優點和缺點。

  Monorepo 多個存放庫
優點 程式碼共用
可更輕鬆地將程式碼及工具標準化
可更輕鬆地重構程式碼
可搜尋性 - 程式碼的單一檢視
每個小組有明確擁有權
可能可減少合併衝突
有助於強制分離微服務
挑戰 共用程式碼的變更可能會影響多個微服務
很可能會有合併衝突
工具必須擴充為大型程式碼基底
存取控制
更複雜的部署程序
難以共用程式碼
難以強制執行編碼標準
相依性管理
擴散的程式碼基底、不佳的探索能力
缺少共用的基礎結構

更新服務

有各種策略可用來更新已在生產環境中的服務。 我們在此討論三個常見的選項:輪流更新、藍綠色部署和 Canary 版本。

輪流更新

在輪流更新中,您會部署新的服務執行個體,而新的執行個體會立刻開始接收要求。 隨著新執行個體的出現,系統會移除先前的執行個體。

例如: 在 Kubernetes 中,當您更新 部署的 Pod 規格時,滾動更新是預設行為。 部署控制器會為已更新的 pod 建立新的 ReplicaSet。 然後它會相應增加新的 ReplicaSet,同時相應減少舊的 ReplicaSet,以維持所需的複本計數。 在新的 pod 備妥之前,舊的 pod 不會遭到刪除。 Kubernetes 會保留更新的歷程記錄,因此您可以視需要復原更新。

例如: Azure Service Fabric 預設會使用滾動更新策略。 此策略最適合用來部署具有新功能的服務版本,而不需要變更現有的 API。 Service Fabric 會藉由將應用程式類型更新為節點或更新網域的子集,來啟動升級部署。 然後,它會向前復原到下一個更新網域,直到所有網域都升級為止。 如果升級網域無法更新,應用程式類型會復原到所有網域的舊版。 請注意,具有多個服務的應用程式類型 (,而且所有服務都會更新為一個升級部署的一部分,) 很容易失敗。 如果某個服務無法更新,則會將整個應用程式復原至舊版,而其他服務則不會更新。

輪流更新的其中一項挑戰就是在更新過程中,新舊版本會混合執行及接收流量。 在這段期間,所有要求會路由傳送至任一個版本。

針對重大 API 變更,最好同時支援這兩個版本,直到更新舊版的所有用戶端為止。 請參閱 API 版本控制

藍綠部署

在藍綠色部署中,您可以一起部署新版本與前一個版本。 在您驗證新版本之後,立刻將所有流量從前一個版本切換到新版本。 切換之後,您可監視應用程式是否有任何問題。 如果發生錯誤,您可以換回舊版本。 假設沒有任何問題,您可以刪除舊版本。

使用更傳統的單體式或多層式架構應用程式,藍綠部署通常是指佈建兩個相同的環境。 您會將新版本部署到預備環境,然後藉由交換 VIP 位址,將用戶端流量重新導向至預備環境。 在微服務架構中,更新會在微服務層級發生,因此您通常會將更新部署到相同的環境,並使用服務探索機制來交換。

範例。 在 Kubernetes 中,您不需佈建個別的叢集來進行藍綠部署。 您反而可以利用選取器。 使用新的 Pod 規格和一組不同的標籤,建立新的 部署 資源。 建立此部署,而不需刪除先前的部署,或修改指向它的服務。 當新的 pod 執行時,您可以更新服務的選取器,以符合新的部署。

藍綠部署的其中一個缺點是,在更新期間,您執行的服務 Pod 數目 (目前和下一個) 的兩倍。 如果 pod 需要大量 CPU 或記憶體資源,您可能需要暫時相應放大叢集,以處理資源耗用。

Canary 發行

在 Canary 版本中,您會向少數用戶端推出更新的版本。 然後您會先監視新服務的行為,然後再向所有的用戶端推出該服務。 這可讓您以控制方式進行緩慢推出、觀察實際資料,以及在所有客戶受影響之前找出問題。

Canary 版本的管理比藍綠或輪流更新更複雜,因為您必須動態將要求路由傳送到不同的服務版本。

範例。 在 Kubernetes 中,您可以將 服務 設定為跨兩個複本集, (每個版本各一個) ,並手動調整複本計數。 不過,此方法會因為 Kubernetes 在 pod 間進行平衡負載的方式而顯得相當粗糙。 例如,如果您總共有 10 個複本,則只能以 10% 遞增的方式轉移流量。 如果您使用服務網格,則可以使用服務網格路由規則,實作更精緻的 Canary 版本策略。

下一步