更快的發行週期是微服務架構的主要優點之一。 但是,如果沒有良好的 CI/CD 程式,您就無法達到微服務所承諾的靈活度。 本文說明挑戰,並建議一些解決問題的方法。
什麼是 CI/CD?
當我們談論 CI/CD 時,我們確實談論了數個相關程式:持續整合、持續傳遞和持續部署。
持續整合。 程式代碼變更經常合併至主要分支。 自動化建置和測試程式可確保主要分支中的程式代碼一律是生產品質。
持續傳遞。 傳遞 CI 程式的任何程式代碼變更都會自動發佈至類似生產環境的環境。 部署到實時生產環境可能需要手動核准,但否則為自動化。 目標是您的程式代碼應該一律 準備好, 部署至生產環境。
持續部署。 通過上述兩個步驟的程式代碼變更會自動部署到生產 。
以下是微服務架構強固 CI/CD 程式的一些目標:
每個小組都可以獨立建置及部署其擁有的服務,而不會影響或中斷其他小組。
將新版本的服務部署到生產環境之前,它會部署到開發/測試/QA 環境以進行驗證。 每個階段都會強制執行質量大門。
新版本的服務可以與舊版並存部署。
已備妥足夠的訪問控制原則。
針對容器化工作負載,您可以信任部署到生產環境的容器映像。
為什麼強固的 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 中,您可以設定 Service,以跨越兩個副本集(每個版本各一個),並手動調整複本計數。 不過,這種方法相當粗略,因為 Kubernetes 跨 Pod 進行負載平衡的方式。 例如,如果您總共有10個複本,則只能以10% 遞增來轉移流量。 如果您使用服務網格,您可以使用服務網路由規則來實作更複雜的 Canary 發行策略。