作者:vivo 網際網路伺服器團隊-Zhang Rong
Karmada作為開源的雲原生多雲容器編排專案,吸引了眾多企業共同參與專案開發,並執行於生產環境中。同時多雲也逐步成為資料中心建設的基礎架構,多區域容災與多活、大規模多叢集管理、跨雲彈性與遷移等場景推動雲原生多雲相關技術的快速發展。
隨著vivo業務不斷遷移到k8s上,叢集規模和叢集的數量快速增長,運維難度也急劇增加。為了構建多叢集技術,我們也自研了多叢集管理,但無法解決我們遇到的更多的問題。後來開始對社群相關專案做了細緻的調研和測試,我們最終選擇了Karmada。
主要原因如下:
在我們探索怎麼使用Karmada的同時,我們也遇到了Karmada自身運維的問題。
社群部署工具較多,需要使用者自己選擇。當前使用者部署方式如下:
Karmadactl
Karmada charts
二進位制部署
hack目錄下指令碼
對於上面的幾種工具,在Karmada的社群開展了問卷調研,並生成了統計報告。
主要總結如下:
社群部署工具較多,需要使用者自己選擇。
部署指令碼也存在缺陷,需要使用者自己解決,github上關於這方面的提問較多。
黑畫面化操作,沒有提供k8s api操作,使用者難以產品化,我們主要期望對接我們的容器平臺,實現視覺化安裝。
缺少CI測試和部署工具的釋出計劃。
etcd叢集缺少生產環境的關鍵功能點,如etcd的高可用、定期備份和恢復。
需要安裝很多依賴外掛,涉及到Karmada控制平面、Karmada的host叢集和member叢集。
缺少一鍵部署和設定繁瑣等痛點。
針對以上問題,本文將分享Karmada-Operator的vivo實踐,包括Operator的方案選擇、API、架構設計和CI構建等。
Operator Framework 是一個開源工具包,用於以有效、自動化且可延伸的方式管理 Kubernetes 原生應用程式,即 Operator。Operator 利用 Kubernetes 的可延伸性來展現雲服務的自動化優勢,如置備、擴充套件以及備份和恢復,同時能夠在 Kubernetes 可執行的任何地方執行。
Operator 有助於簡化對 Kubernetes 上的複雜、有狀態的應用程式的管理。然而,現在編寫 Operator 並不容易,會面臨一些挑戰,如使用低階別 API、編寫樣板檔案以及缺乏模組化功能(這會導致重複工作)。
Operator SDK 是一個框架,通過提供以下內容來降低 Operator 的編寫難度:
高階 API 和抽象,用於更直觀地編寫操作邏輯
支架和程式碼生成工具,用於快速引導新專案
擴充套件項,覆蓋常見的 Operator 用例
如上圖所示,operator sdk可以基於helm、ansilbe和go構建operator,我們需根據當前的情況選擇我們合適的operator框架。
方案一:golang 開發Operator
方案二:ansible開發Operator
方案三:golang和ansible混合開發Operator
根據Karmada的實際生產部署調研情況和vivo自身的實踐,可以總結如下:
要支援在K8s叢集和不依賴K8s叢集二進位制部署。
支援外部獨立的etcd叢集部署或者對接已有的etcd叢集。
Karmada叢集具備遷移能力,如機房裁撤和機器故障等,就需要etcd叢集管理有備份和恢復能力,如根據etcd備份資料快速在其它機房恢復叢集。
需要支援第三方的vip給Karmada-apiserver提供負載均衡,目前vivo都是基於外部vip,並提供了域名。沒有使用K8s的service給Karmada-apiserver提供負載均衡。
Karmada控制平面一鍵部署和member叢集的自動化註冊和登出。也需要獲取member叢集的kubeconfig,pull模式也需要在member叢集部署Karmada-agent。
Karmada叢集的addons外掛安裝,如istio、anp、第三方的crd等安裝,需要在Karmada的控制平面、host主機叢集,甚至需要在member叢集上進行設定。
提供api能力,實現視覺化部署。
針對Karmada單個元件的單獨升級和全量升級。
支援在offline和離線模式。
面對Karmada如此複雜的條件限制,我們再來分析下上面3個方案誰可能比較合適。
方案一,基於go開發的Operator,比較適合基於K8s叢集的有狀態服務管理,如etcd,資料庫等,比較成熟的有etcd-Operator。Karmada涉及到不依賴K8s叢集二進位制部署、外部etcd、member叢集的註冊、登出和外掛安裝,不能很好的支援或者需要增加開發量。
方案二,基於ansible開發的Operator,既可以基於K8s叢集的對狀態服務管理,也可以脫離K8s叢集對如不依賴K8s叢集二進位制部署、外部etcd、member叢集的註冊、登出和外掛安裝。這裡主要通過ansible 的ssh登入能力和K8s模組管理,通過調研我們也發現90%以上的使用者可以提供ssh登入。
方案三,基於go+ansible的混合的Operator,讀者可以閱讀vivo開發的Kubernetes-Operator,就是基於這種方案。方案三具備方案二的所有能力,因為底層都是通過ansible去執行。
首先我們排除了方案一,對於方案二和方案三,本人也糾結了很長是時間,最終我們選擇了方案二。主要原因如下:
Operator SDK ansible已具備了和Operator SDK go相等的能力,並提供K8s、K8s_status模組、相似的webhook功能去對k8s的資源管理,以及reconciliation的能力。
符合目前Karmada實際生產部署的需求。
簡單易學,只要知道ansbile的jinja模版、和K8s相同的yaml檔案。你只需要編寫ansible task,開箱即用,reconciliation由Operator SDK 解決。
對於常用ansible的人比較友好,不需要寫golang程式碼。
擴充套件能力強,使用者可自定義外掛。管理端也支援local、ssh、zeromq三種方式連線。local模式可以直接對接K8s介面,ssh模式可以登入執行指令碼。可以很好的混合使用,解決我們當前的需求。
Karmada運維操作相對K8s要簡單,不需要複雜的crd定義,ansible需要解析少量vars去執行playbook就行。golang+ansible模式比較適合複雜CRD定義和業務邏輯複雜的系統。
如上圖所示,我們只需要執行Operator-SDK create api命令,就可以建立 KarmadaDeployment的CRD,然後就可以定義KarmadaDeployment的API。在watches.yaml裡實現Reconcile的業務邏輯。
這裡主要定義KarmadaDeployment、EtcdBackup和EtcdRestore個資源,分別用於Karmada的部署,和etcd的資料備份和恢復。ansible Operator會根據spec裡定義解析成ansible的vars。status將通過 ansible runner 輸出為使用者自定義的狀態。也可以通過ansible的k8s_status更新KarmadaDeployment的狀態。當前主要考慮的是在K8s執行Karmada,後面會新增二進位制部署模式,當前的CR沒有涉及。
如圖所示Karmada Operator提供了容器化和二進位制叢集部署設計,其中Karmada的容器化部署不需要執行ssh登入,只需通過K8s和k8s_status就可以完成karmada控制面的管控。Karmada的二進位制部署主要通過ssh登入完成Karmada控制平面的管控。member叢集的join和unjoin需要提前提供member叢集的kubeconfig檔案,也可以設定member的登入許可權操作,需要在CR裡定義member叢集的使用者和金鑰。
執行流程如下。
使用者通過KarmadaDeployment定義Karmada操作
Karmada Operator感知KarmadaDeployment的CR變化,開始進入控制器邏輯
根據使用者的定義,選擇是容器化部署或者二進位制部署,開始執行安裝、擴所容和備份等操作
執行join/unjoin操作,將member叢集註冊到Karmada叢集或者登出member叢集
如上圖所示,主要是karmada控制平面生命週期管理,對比當前社群的部署工具我們如下優化:
標準化證書管理,主要是用openssl生成證書。其中etcd和Karmada證書單獨分開維護,和k8s叢集證書命名相同,方便接入我們的監控。
Karmada-apiserver支援外部負載均衡,不限於當前的k8s service提供的負載均衡。
更靈活的升級策略,支援單獨元件升級和全量升級。
更豐富的全域性變數定義,計劃支援元件設定變更等。
etcd叢集是Karmada的後設資料叢集,生產中需要保證etcd叢集高可用和故障恢復等。如上圖展示了etcd叢集必要的生產要素,如自動擴縮容、升級、備份和etcd叢集的故障恢復。自研了基於ansible的plugins和library, 實現etcd叢集管理能力如下:
新增member到存在的etcd叢集。
etcd叢集刪除member。
etcd叢集的備份,比如支援cephfs的資料備份。
etcd叢集故障恢復。
etcd叢集健康狀態查詢。
這裡定義了etcdBackup和etcdRestore的CR,沒有合併到KarmadaDeployment裡。主要考慮到etcd叢集本身操作的安全性和簡化KarmadaDeployment的ansible任務。其中etcdRestore功能,可以根據etcd叢集備份資料,實現匯入到新的etcd叢集,從而恢復Karmada叢集所有的業務狀態。當前主要場景如下:
Karmada叢集所在的機房裁撤,需要備份etcd資料,遷移到新的Karmada叢集。
期望通過Karmada-Operator管理Karmada叢集,只需備份etcd資料,實現etcdRestore功能即可。
Karmada叢集故障,可以通過etcd備份資料,結合etcdRestroe實現故障恢復。
member叢集的生命週期管理主要有註冊和登出,上圖是執行的流程。為了處理member叢集的註冊和登出,這裡會動態的生成inventory。Ansible Inventory 是包含靜態 Inventory 和動態 Inventory 兩部分的,靜態 Inventory 指的是在檔案中指定的主機和組,動態 Inventory 指通過外部指令碼獲取主機列表,並按照 ansible 所要求的格式返回給 ansilbe 命令的。
這裡Karmada-Operator基於k8s的CR實現了動態inventory plugins,主要通過解析KarmadaDeployment的members定義去動態的生成inventory。這裡新增了add-member和del-member 2個角色, add-member裡叢集會被註冊到Karmada控制平面,del-member裡的叢集會被從Karmada控制平面登出,這樣就可以並行的註冊和登出多個member叢集。同時也可以提供ssh登入模式,方便後期擴充套件。
為了更好的提高開發人員的體驗,計劃提供Karmada-Operator的CI構建能力。這裡在K8s叢集裡部署github的self-hosted Runner和kubevirt。
使用者在github上提交PR
觸發github Actions,我們在self-hosted裡定義的流程
執行語法和單元測試
通過kubevirt建立vm
在多個vm裡部署1個host和2個member叢集
部署Karmada和新增member叢集
執行Karmada e2e和bookfinfo案例測試
計劃新增的CI矩陣測試如下:
語法測試:
ansible-lint
shellcheck
yamllint
syntax-check
pep8
叢集部署測試:
Karmadactl、charts、yaml和二進位制部署和所有設定項安裝測試
join/ unjoin member 叢集
升級Karmada
etcd叢集的備份和恢復
功能測試:
Karmada e2e測試
建立bookinfo案例
效能測試:
我們主要通過kubemark元件模擬了多個2000節點的member叢集進行了效能測試,其中一個測試案例是叢集故障轉移,結論是4w個無狀態pod能夠在15分鐘完成故障遷移,有機會可以分享我們的效能測試。
通過社群的調研和vivo的實踐,最終確定了Karmada-Operator方案設計。Karmada-Operator具有高度可延伸性、可靠性、更直觀地編寫操作邏輯和開箱即用等特點,我們相信通過這種高度可延伸的宣告式、自我修復雲原生系統管理Karmada,為我們全面切換到Karmada去管理業務提供了強有力可靠保障。
基於ansible的operator也存在如下缺點。第一點沒有提供webhook的能力,需要自己新增或者在ansible的task新增相關的校驗;第二點是自動生成了通用的CRD模版,沒有詳細可定義的腳手架工具去自動生成CRD。
當前Karmada-operator還在初始階段,提供了方案和部分實踐,具體功能還需不斷的完善和改進。具體可以檢視vivo的Karmada-Operator倉庫,歡迎大家試用和提建議。當前程式碼提供的能力矩陣可以檢視專案規劃。