容器雲多叢集環境下如何實踐 DevOps

danny_2018發表於2022-10-17

從容器、Kubernetes 和 DevOps 等技術問世,業界一遍遍地質疑它們是否能夠禁得住生產級別考驗,到今天許多大型企業大規模採用 Kubernetes 已成事實。

而隨著雲原生技術的普及和落地,越來越多的雲原生應用需要差異化的部署到不同的環境或不同的資料中心中,不同應用不同元件在不同的環境或叢集會存在多個差異化配置,傳統透過流水線進行持續交付的模式不再適合Kubernetes宣告式和控制迴圈的模式,在這種情況下,應用的釋出管理越複雜,業務系統將面臨巨大的風險。以 ArgoCD 和 FluxCD 等持續交付為代表的 GitOps 為管理基礎設施和應用程式提供了一種方法,以宣告式描述整個系統並進行版本控制,提供了一個自動化的過程來確保部署的環境和儲存庫中期望的狀態相匹配。

本文討論了企業容器雲在多叢集情況下如何實踐 DevOps。首先分析瞭如今容器雲出現多叢集的原因,然後介紹了雲原生 DevOps 的落地方式——GitOps,並推薦了一種多叢集 GitOps 工作流作為落地參考,最後部分介紹了在持續整合和持續交付中具體實踐 GitOps 的主流方式,能有效地幫助讀者瞭解和落地容器雲多叢集 DevOps 實踐,幫助讀者比較和選擇眾多 DevOps 工具和方法,少走彎路。

1 為什麼需要多叢集 Kubernetes

雖然 Kubernetes 成為容器編排領域的事實標準,解決了大多數容器編排領域的問題,但 Kubernetes 原生的管理能力仍然停留在但單叢集級別。每一個叢集可以穩定地自治執行,但是卻缺乏橫貫多個叢集的統籌管理能力。企業內部出現多叢集 Kubernetes 主要有以下幾個原因。

1.1 Kubernetes 單個叢集規模問題

單個 Kubernetes 叢集存在規模性限制,並且在擴容的過程中,etcd、API Server、排程器以及控制器都有可能出現效能瓶頸。以 v1.23 版本 Kubernetes 為例,官方社群給出的單叢集規模資料如下:

單個叢集節點數不超過 5000;

每個節點的 Pod 數量不超過 110;

Pod 總數不超過 150000;

容器總數不超過 300000。

社群中也有一些開發者試圖突破該規模上限,例如在節點上增加快取降低 API Server 的負載。但其缺乏官方社群支援,暫時沒有被業界廣泛接受。

1.2 高可用架構

為了提高業務應用的可用性,避免單個叢集或單個資料中心故障導致業務應用暫時不可用,影響使用者正常使用,大型企業通常會對業務應用進行災備甚至多資料中心多活部署,這也會導致業務應用被部署在多個不同的 Kubernetes 叢集中。

除此之外,企業內外部也常有開發、測試和 QA 等多個不同環境,一個企業可能存在有以下環境:

(1)開發測試環境

(2)QA 環境

(3)預發環境

(4)生產環境

同時,按照高可用架構,生產環境還會部署在三個資料中心或雲上環境,這樣算下來至少有 6 個不同的叢集環境——這還只是一個部門或一個應用的情況。

1.3 混合雲架構

如今企業還會採用內部基礎架構、私有云和公有云的混合雲基礎架構,自然也會引入多叢集 Kubernetes。

2 容器雲多叢集管理

容器雲多叢集管理就是透過統一的控制平臺納管多個 Kubernetes 叢集。透過容器雲平臺,平臺管理人員能夠獲知多叢集節點健康狀態、資源使用情況和叢集使用情況等資訊;業務應用負責人和開發能夠決策如何調配應用服務在各個叢集中的部署分佈;應用的運維人員能夠獲知服務狀態。因此,多叢集管理涉及資源管理、跨叢集資源訪問和排程以及運維和管理三大塊。

多叢集管理暫無統一成熟的事實標準,開源社群和各大廠商都已對這一方向進行了長時間探索,社群中的多叢集興趣小組(SIG Multi-Cluster)和,以及 RedHat、螞蟻、華為和騰訊等廠商都提出自己的方案。

多叢集管理專案眾多,但我們可以從叢集聯邦和非叢集聯邦來歸類,我們來簡單對比下兩種方案。

2.1 基於 KubeFed 的多叢集管理

(1) RedHat 和 Kubernetes 社群牽頭的 KubeFed

KubeFed 是最早的 Kubernetes 叢集聯邦專案,主要支援:跨叢集的資源同步與伸縮、跨叢集的服務發現。KubeFed 能夠根據負載情況,排程並調節各叢集的資源分佈,同時能夠提供跨叢集的應用故障轉移,以及跨叢集的服務發現。實現了方便的跨地區、跨服務商配置並管理多個 Kubernetes 叢集,以及多叢集資源的統一管理。但是,其 API 複雜、CRD 編寫不規範等缺點,也成為掣肘其推廣的關鍵。

Kubefed 專案今天基本處於停止維護的狀態,專案也鮮有更新。

(2) RedHat、螞蟻和阿里雲共同發起並開源的 OCM(Open Cluster Management)

OCM 旨在解決多叢集、混合環境下資源、應用、配置、策略等物件的生命週期管理問題。OCM 基於 KubeFed 最佳化而來,它將管理開銷從中樞叢集下放到每個被管理叢集上的代理(Agent)上,讓它在整個基礎設施中分散式自治並維護穩定。這使得 OCM 理論上能管理的叢集數量至少比 KubeFed 多一個數量級。到目前為止,官方宣稱可同時管理多達 1000 個叢集。

(3) 此外,同樣繼承自 KubeFed 的還有華為雲開源的 Karmada,騰訊也開源了兼具多叢集管理和跨叢集應用編排的雲原生專案 ClusterNet。

2.2 非叢集聯邦的多叢集管理

另外一類非叢集聯邦的多叢集管理相對就簡單很多,這類管理系統主要是為了進行資源管理、運維管理和使用者管理,提供匯入叢集功能,並透過統一 Web 介面進行檢視和管理。

這類工具不引入額外叢集聯邦的複雜性(自然在跨叢集排程方面就弱一些),保持每個叢集的獨立性,同時透過統一的 Web 介面來檢視多個叢集的資源使用情況,支援透過 Web 介面建立 Deployment、Service 和負載均衡等,並且會整合持續整合、持續交付和監控告警等功能。由於叢集聯邦技術還在發展,大多數企業傾向於使用這種方式來運維和管理多叢集 Kubernetes 環境。

3 多叢集 DevOps 工作流

透過上述分析,既然企業內部多套 Kubernetes 叢集已成不可避免的事實,那麼容器雲多叢集 DevOps 實踐就成了關注的焦點,如何在多叢集 Kubernetes 環境下讓構建和部署流程自動化,確保部署任務的可重複性,減少部署出錯的可能性,也減少開發和運維人員無營養無價值的重複勞動,成為 DevOps 團隊或研發效能團隊的主要目標。

3.1 DevOps 簡介

DevOps(Development 和 Operations 的組合詞)是一種重視“軟體開發人員(Dev)”和“運維技術人員(Ops)”之間溝通合作的文化、運動或慣例。透過自動化“軟體交付”和“架構變更”的流程,來使得構建、測試、釋出軟體能夠更加地快捷、頻繁和可靠。

如果說單體架構尚可以透過幾個開發或運維直接手動部署,微服務架構興起後,其架構更復雜,涉及元件更多,變更次數也更多,手動部署變得費時費力,還伴隨著許多不為人知的隱患。

隨著虛擬化和雲端計算基礎設施(可能來自內部或外部供應商)日益普遍,自動化技術和工具的普及,微服務架構的盛行,DevOps 的重要性日益顯著。

3.2 多叢集下的 DevOps

如前文所述,由於企業內部可能存在多叢集 Kubernetes,那麼 DevOps 就必須涉及多叢集 Kubernetes 環境下的使用場景。我們如何去實現這樣的目標呢?不妨先回過頭思考下“雲原生”下部署方式演進的過程。

隨著以“雲原生”為基礎的基礎架構和應用框架爆炸性增長,基於 Kubernetes 所衍生的現代化基礎平臺可謂應有盡有,原本系統管理員用來部署、配置、管理這些平臺的指令碼開始力不從心,自此也演變成出了叫做“基礎架構即程式碼”(Infrastructure as Code, IaC) 的新模式。

基礎架構即程式碼,意味著應用程式的基礎架構、部署、狀態和配置等資訊都被顯示描述,並且儲存在 Git 倉庫中。IaC 採用宣告式方法來管理基礎架構,定義系統的期望狀態,並跟蹤系統的實際狀態,這樣做的好處有:

可重複性(Repeatability):應用程式可以快速、可重複地部署到多個資料中心的多個環境;

可靠性(Reliability):自動化 IaC 可以大大減少人為錯誤的機會;

高效(Efficiency):透過 CI/CD 高效提高團隊生產力;

視覺化(Visibility):開發人員很容易看到應用程式的基礎架構、部署方式等,不需要一遍遍去口述,更透明也更利於協作。

回想在沒有 IaC 的時候,運維 A 透過某種方式部署了應用,但是運維 B 並不知道 A 是如何部署的,那此時運維 B 要麼透過文件學習部署應用的方式,要麼找運維 A 請教如何部署——無論哪種方式,既無法保證應用重複部署的成功率,也不利於團隊之間進行協作。

更進一步,雖然傳統的 Chef、Ansible 和 Puppet 等自動化工具,也可以透過配置模板或指令碼,將基礎架構或應用程式推到目標伺服器上,實現自動化部署。但這仍達不到理想的效果,主要是因為在一臺伺服器的生命週期中,可能會發生很多次更新,有時還會存在運維人員手工修改某些配置,久而久之,部分伺服器可能與其他伺服器略有不同。而透過 Terraform 或 Kubernetes Yaml 等方式,每次會透過映象建立新伺服器、新基礎設施或新應用。如果需要更新伺服器,就要用新伺服器替換它們——這一理念即“不可變基礎設施”,是應用向雲原生轉型非常重要的一步,能夠構建容錯性好、易於管理和便於觀察的松耦合系統。

綜上,為了實現“基礎架構即程式碼”和“不可變基礎設施”,雲原生應用部署清單和基礎架構往往以程式碼的方式儲存在 Git 倉庫中,並透過 CI/CD 去獲取這些程式碼進行相應的處理,漸漸地,一種新的 DevOps 模式也誕生了——GitOps。

Kubernetes 在設計之初就採用宣告式物件管理,簡單來說,Kubernetes 透過 Yaml 來定義系統的最終狀態應該是什麼樣子的,包括應用的副本數、配置、映象和策略等等部署資訊都一目瞭然,可以說 Kubernetes 契合 GitOps。

多叢集 Kubernetes 下的 DevOps 通常透過 GitOps 來實現。GitOps 依賴宣告式管理的基礎架構,與 Kubernetes 的宣告式程式設計的清單檔案不謀而合,兩者相結合能發揮出巨大的潛力。GitOps 透過 Git 來實現協作、CI/CD 和版本控制,並將其應用於基礎架構自動化和應用部署中,最後生成的部署檔案交由 Kubernetes 進行部署工作。

因此,在多叢集 Kubernetes 下透過 GitOps 來實現 DevOps 成為首選。在開始介紹如何實施容器雲多叢集 DevOps 之前,需要設計規劃一套行之有效的多叢集 Git 工作流。

3.3 GitOps 工作流參考

多叢集 GitOps 推薦使用基於主幹(trunk based)的工作流,而非每個分支一個環境的模式。

可能在直覺上,不同叢集、不同環境採用不同分支是很自然的,例如生產環境是 master 分支,而開發測試、預發和 QA 又是各自不同的分支,看起來很適合。

可是,這樣做的弊端很多,包括:

轉生產容易出錯。假如開發測試、QA 和預發各自做了互相沖突的變更,這時候想簡單合併到生產是比較困難的,我們希望部署清單儘量少產生衝突;

容易造成配置漂移。預發環境和生產環境的配置一般不同,如果預發上的業務程式碼改動想合併到主幹,此時正好連帶配置一起進行合併,那麼可能會把預發環境的配置帶到生產。你可能會說,合併程式碼時為什麼不仔細地 Code Review。實際上,合併可能會有大量的應用和大量的配置,我們不可能每一項都依賴於人工檢查。

一旦環境增多,分支管理維護會更加複雜,合併也更為複雜,如果互相沖突的變更難以合併處理,這時只能透過頻繁的 cherry-pick 進行選擇合併,費時費力。

與 Kubernetes 生態相違背。以 Kubernetes 最常見的兩種編排釋出工具 Helm 和 Kustomize 為例,Helm 透過 values.yaml 指定配置引數,如果是不同的環境,則使用不同的 values.yaml 檔案;Kustomize 則是先建立一個 base 配置,然後再將每個環境建模為一個 overlay 去覆蓋變更的配置項。

可見,無論是 Helm 還是 Kustomize 的配置檔案設計模式都與 Git 分支無關,而是直接在不同環境使用不同的配置檔案,拋棄掉 Git 分支的複雜性(越簡單越不容易出錯),直接透過不同的檔案進行環境隔離,例如:直接建立幾個不同的資料夾來代表不同的環境,各個環境單獨管理。

主幹開發模式最理想狀態的是“主幹開發,主幹釋出”,但目前部分企業的開發實踐還無法達到這樣的要求,所以有的企業退而求其次使用“分支開發,主幹釋出”,當分支生命週期很短時,基本不會產生程式碼合併衝突,就基本等同於主幹開發。在主幹分支出現 Bug 影響釋出的時候也會臨時採用分支釋出的策略——但也要注意,控制分支環境的數量和作用。

基於主幹模式的多分支多環境的 Git 工作流如下圖所示:

軟體工程沒有銀彈,如何實踐 GitOps 只有一個參考,並無一個標準答案,因此,企業內應根據自身實際情況進行調整。

雲原生 GitOps 通常分為持續整合(CI)和持續交付(CD)兩部分,持續整合部分主要負責編譯出映象、部署清單和配置檔案等最終部署產物,持續交付部分負責將持續整合的產物以適合的方式部署到對應的叢集或環境中。接下來我們將分別來討論持續整合和持續交付部分的實踐。

4 持續整合:流水線構建

開發人員完成功能開發並提交程式碼後,持續整合來處理剩下的工作,目前主流的持續工具有 Jenkins、Gitlab CI 和 Tekton 等,基本流程如下圖所示:

當開發人員提交程式碼後,會觸發持續整合工具開始執行流水線,比較典型的雲原生 GitOps 中的流水線常分為以下幾個階段:

階段 1:從程式碼倉庫檢出原始碼,切換到對應分支;

階段 2:執行單元測試,失敗則報錯;測試透過後才能進行下一階段;

階段 3:SonarQube 程式碼質量分析;

階段 4:編譯程式碼,構建映象,根據一定策略規則來設定映象 tag,並推送新映象;

階段 5:更新程式碼倉庫的部署清單,例如更新新的映象 tag 和配置等資訊。

流水線正常執行結束後,不僅構建出新映象,還一併將 Yaml/Kustomize/Helm 等部署清單一併更新,構建出新版本的部署清單,而無需手動介入修改。

值得一提的是,以上流程簡化了一些細節,GitOps 實施的細節繁多,包括還需要考慮 Git 憑證管理、映象倉庫憑證管理、構建映象方式(DinD、kaniko 還是 Podman 等)、映象 tag 設定規則等等,DevOps 團隊統一配置成模板再暴露給開發人員使用,否則配置流水線可能依然會花費大量精力。

前文提到,雲原生 GitOps 的持續整合部分只負責產出映象、部署清單和配置檔案等最終部署產物,而非像以前一樣,直接把部署產物推到叢集完成應用更新,接下來我們的持續交付部分將討論為何如此拆分。

5 持續交付:多叢集應用分發

多叢集應用分發是持續交付工具關注的核心點,歸結下來主要有兩種模式:Push 模式和 Pull 模式。

Push 模式出現在傳統的持續整合(CI)工具 Jenkins 和 Gitlab CI 中,這類工具直接將部署檔案直接推到 Kubernetes 叢集進行部署,相當於直接做環境更新。Push 模式基本原理如下圖所示:

Pull 模式則出現在一些持續交付(CD)工具例如 ArgoCD 和 FluxCD 中,這類工具會去檢查叢集中現在的狀態是否和 git 倉庫中檔案指定的狀態匹配,如果發現差異,則會將 git 倉庫中的部署檔案拉下來進行部署,將應用更新到期望狀態。Pull 模式基本原理如下圖所示:

通常 ArgoCD 和 FluxCD 自身也執行在 Kubernetes 叢集中。

另外,不建議透過 Kubectl 直接部署的行為,這讓安全許可權管控非常難做。

綜合對比一下 Push 模式和 Pull 模式。Push 模式是在程式碼變更後觸發更新,如果有人手動修改了叢集中的配置,叢集中的配置就會和程式碼庫中的配置有差異,這與“不可變基礎設施”的理念相違背;而 Pull 模式則是檢測叢集和程式碼庫中的配置,當發現不一致時,自動/手動觸發更新,這相當於在程式碼倉庫和 Kubernetes 叢集狀態之間多個一個控制器,不斷讓 Kubernetes 叢集中的實際狀態和程式碼庫中部署清單的期望狀態保持一致。

這裡筆者更推薦使用 Pull 模式進行分發部署,因為 Pull 模式的工具功能更為純粹,可以利用許可權鑑權等資訊做安全性及合規性保障,尤其是當你需要回滾時,只需要使用 git 將部署檔案回滾到上個版本,部署檔案被 ArgoCD 或 FluxCD 等工具檢測到發現變化,應用又會回滾到之前的狀態,而不需要流水線工具重新跑一邊,由 GitOps 驅動的系統可以透過宣告式表達其所需狀態,這符合 Kubernetes 的宣告式模式,更為推薦。

到了這一步,我們才真正開始思考,如果將部署清單分發、部署到對應的叢集,多叢集應用釋出主要分為“集中式應用釋出模式”和“分散式應用釋出模式”,主要區別是統一使用一套持續交付工具統一分發,還是每個叢集各一套持續交付工具分散式分發,如下圖所示:

綜合比較兩種方式,採用集中式的優點是架構簡單,易於統一管理;但缺點是可能存在單點故障,並且各個叢集的認證鑑權比較複雜,並且不適用於叢集之間存在網路隔離的場景。

分散式應用釋出模式的優點是可用性高,適用網路隔離場景;缺點是架構較為複雜,且目標叢集需要部署持續交付元件。

企業需要根據自身網路架構和其他實際情況,若無網路隔離推薦採用集中式應用釋出模式;若網路較為複雜,安全性有較高要求,推薦採用分散式應用釋出模式。

6 總結

本文綜述瞭如何透過 GitOps 來實現多叢集 DevOps,並對流程中一些關鍵節點進行了分析,總結了容器雲多叢集 DevOps 常見的模式,以及一些實踐。

此外,也有一些開源軟體試圖統一解決 GitOps 整個流程中的問題,包括 KubeSphere 在其 3.3 版本中加入 GitOps 支援,kubevela 也提出了一種新的 GitOps 方式。

雖然 DevOps 看上去很美好,但實際落地過程中則充滿了細節上的挑戰,步驟繁多,每個步驟都可能存在卡點,例如:多叢集 Kubernetes 網路隔離或連通問題,多叢集 Kubernetes 建立、管理和運維問題,應用流水線編寫如何簡單化,應用配置和環境配置如何拆分和管理,等等。這些問題在企業實施容器雲多叢集 DevOps 前都需要認真仔細地考慮,也歡迎讀者多多交流!

【執筆專家】

唐偉志 容器雲自動化運維使用者委員會委員

twt社群雲原生應用創新實踐聯盟——容器雲自動化運維方向課題組專家。擔任國信證券容器雲平臺負責人,目前負責國信證券容器、kubernetes等雲原生相關技術架構和開發工作,專注於分散式系統、雲原生、多叢集管理和微服務治理等方向。曾在電子工業出版社出版技術書籍《深入理解分散式系統》。

【顧問專家】

孫洪軒 容器雲自動化運維方向專家

twt社群雲原生應用創新實踐聯盟——容器雲自動化運維方向課題組特邀外部專家。多年IT研發經驗,近幾年一直深耕區塊鏈,雲原生等前沿技術領域。作為光大科技的自動化專家,先後為集團設計並建設了區塊鏈雲服務平臺,容器雲PaaS平臺等中大型專案。具備豐富的軟體架構設計,專案落地經驗。

毛天明 容器雲自動化運維使用者委員會委員

twt社群雲原生應用創新實踐聯盟——容器雲自動化運維方向課題組專家。10年金融行業工作。太平洋保險容器工作前負責人,領導容器雲平臺的專案建設5年。電信翼支付容器工作負責人,領導容器雲平臺的專案建設3年。主要從事雲原生架構建設、應用容器化改造、CICD工具鏈設計。2020 容器雲職業技能大賽百位專家委員會成員。

來自 “ twt企業IT社群 ”, 原文作者:twt企業IT社群;原文連結:https://mp.weixin.qq.com/s/MW67DhLzUWXm0xHd5LH0Tw,如有侵權,請聯絡管理員刪除。

相關文章