作者|周培,新東方架構部容器組專家
有狀態服務建設一直以來都是 K8s 中非常具有挑戰性的作業,新東方在有狀態服務云化程序中,采用定制化 Operator 與自研本地存盤服務結合的模式,增強了 K8s 原生本地存盤方案的能力,在摸索中穩步推進企業的容器化建設,
新東方有狀態服務 In K8s 的現狀

如上圖所示,上層 Pod 由自定義的 Operator 和 StatefulSet 控制器來托管,Pod 關聯 PVC,PVC 系結 PV,最下層是存盤服務,
最下層的存盤服務包含本地存盤和遠端存盤兩類,對于一般的存盤需求,首選是遠端存盤服務;而對于高性能 IO 的存盤需求,那就要選擇本地存盤服務,目前,本地存盤服務包含 K8s 原生 local 存盤服務和自研的 xlss 存盤服務 2 種,
原生 K8s 支撐有狀態服務的能力
原生 K8s 支撐有狀態服務的能力是有狀態服務建設的基礎,其管理模式是:StatefulSet 控制器 + 存盤服務,
1. StatefulSet 控制器
StatefulSet 控制器:
用來管理有狀態應用的作業負載 API 物件的控制器,管理某 Pod 集合的部署和擴縮,并為這些 Pod 提供持久存盤和持久識別符號,
StatefulSet 資源的特點:
- 穩定的、唯一的網路標識
- 穩定的、持久的存盤
- 有序的、優雅的部署和縮放
- 有序的、自動的滾動更新
StatefulSet 資源的局限:
- 關于存盤,StatefulSet 控制器是不提供存盤供給的,
- 洗掉或者縮容時,StatefulSet 控制器只負責 Pod,
- 人工要建一個無頭服務,提供每個 Pod 創建唯一的名稱,
- 優雅洗掉 StatefulSet,建議先縮放至 0 再洗掉,
- 有序性也導致依賴性,比如編號大的 pod 依賴前面 pod 的運行情況,前面 pod 無法啟動,后面 pod 就不會啟動,
這 5 點局限可進一步概括為:StatefulSet 控制器管理 Pod 和部分存盤服務(比如擴容時 pvc 的創建),其它的就無能為力,有序性引起的依賴性也會帶來負面影響的,需要人工干預治愈,
2. 存盤服務
Cloud Native Storage

這是 CNCF 官網關于云原生存盤的一副截圖,截圖時間是 2021 年 7 月初,有 50 多種存盤產品,接近半數屬于商業產品,開源產品多數都是遠端存盤型別,有支持檔案系統的、有支持物件存盤的、還有支持塊存盤的,
K8s PV 型別

資料來源于官網,原生 K8s 支持的 PV 型別,有常用的 rbd、hostpath、local 等型別,
如何選擇?
控制器只有 StatefulSet 控制器可使用,存盤產品很多,PV 型別也不少,該怎么選擇呢?

選擇存盤產品,需要考慮哪些因素呢?新東方在選擇存盤產品時考慮了以下一些因素:
- 開源 VS 商業
- 本地 VS 遠端
- 動態供給 VS 靜態供給
- 資料高可用方案
做選擇是令人頭疼的事情,比如選擇開源,好處是不用花錢,但穩定性就很難保證,甚至提供的能力也有限;商業產品能力和穩定性有保證,但要付費,在這里先不下結論,最侄訓是要看需求,
自研存盤產品 XLSS
1. 關鍵需求
新東方有狀態服務建設的關鍵需求:良好的性能,支持 IO 密集型應用;資料可用性,具有一定的容災能力;動態供給,實作有狀態服務的完全自動化管理,
2. XLSS 介紹

XLSS(XDF Local Storage Service)中文全稱:新東方本地存盤服務產品,是一種基于本地存盤的高性能、高可用存盤方案,可以解決 K8s 中本地存盤方案的不足之處:localpv 只能靜態供給;使用 localpv 時,pod 與 node 的親和性系結造成的可用性降低;本地存盤存在資料丟失的風險,
應用場景
- 高性能應用,IO 密集型的應用軟體,比如 Kafka
- 本地存盤的動態化管理
- 資料安全,應用資料定期備份,備份資料加密保護
- 存盤資源監控告警,比如 K8s Pv 資源的使用量監控告警
3. XLSS In K8s

如上圖所示,XLSS 在 K8s 中的運行狀態是 Xlss 的 3 個組件以容器形式運行在 K8s 集群中,使用本地存盤為有狀態服務提供存盤服務,并定期執行資料的備份作業,Xlss 會提供有關存盤和相關作業的 metrics 資料,
4. XLSS 核心組件介紹
Xlss 主要組件包含:
- xlss-scheduler
- 基于 kube-scheduler 的自定義調度器
- 對于有狀態服務的 pod 的調度,自動識別 xlss localpv 的使用身份,智能干預 pod 調度,消除 pod 與 node 的親和性系結造成的可用性降低
- xlss-rescuer
- 以 DaemonSet 資源型別運行在 k8s 集群中
- 按照資料備份策略,執行資料備份作業
- 監視資料恢復請求,執行資料恢復作業
- 提供 metrics 資料
- xlss-localpv-provisioner
- 動態供給本地存盤
5. xlss-scheduler 關鍵邏輯實作思路

如上圖,這是 K8s 調度器的調度框架模型,在調度流程中包含了許多擴展點,xlss-scheduler 就是基于該調度框架模型,通過撰寫自定義的插件實作,主要在 3 個擴展點上做了增強:
- Prefilter:依據 Pod 的節點親和性,分析親和性節點的健康狀態,若節點例外,對 Pod 設定特殊標記,
- Filter:針對設定特殊標記的 Pod,解除節點親和性,
- Prebind:對設定特殊標記的 Pod,洗掉特殊標記,根據調度結果,發送資料恢復請求,
6. xlss-rescuer 資料備份作業實作邏輯

圖中 3 個部分,左右各一個回圈邏輯,中間通過一個快取佇列實作通信,左邊的回圈實作的功能:收集備份作業策略,并更新到快取佇列中,主要 3 步:
- watch pod 事件
- 從 pod 注解當中獲取備份策略,備份作業的配置資訊是通過 pod 注解實作的
- 同步備份策略到快取佇列
右邊的回圈實作的功能:執行備份作業,也是 3 步:
- 對快取佇列元素排序,排序按照下次備份作業的執行時間點進行升序排列
- 休眠等待,若當前時間還沒有到最近的一個備份作業執行時間,就會進行休眠等待
- 執行備份作業
7. xlss-rescuer 資料恢復作業實作邏輯

資料恢復作業流程和資料備份作業流程實作思路是類似的,但在具體實作邏輯上有所不同,
左邊的回圈實作的功能:監視恢復作業請求,并更新到快取佇列中,主要 3 步:
- watch CRD,監視資料恢復請求,接收 xlss-scheduler 發出的資料恢復請求(資料恢復請求以 CRD 方式實作)
- 分析 CRD 狀態,避免重復處理
- 同步恢復請求到快取佇列
右邊的回圈實作的功能:執行恢復作業,這里是 4 步:
- 更新 CRD 實體狀態
- 恢復快照資料到指定目錄
- 更新 PV 與 PVC
- 洗掉 CRD 實體
8. xlss-localpv-provisioner 存盤創建實作思路

xlss-localpv-provisioner 組件,其功能比較專一,實作本地存盤的動態創建,其作業流程當 provisioner pod 獲取到創建存盤的請求時,首先會創建一個臨時的 helper pod,這個 helper pod 會被調度到指定的 node 上面,創建檔案目錄作為本地存盤使用,這就完成了 pv 實際后端存盤的創建,當存盤創建完畢,provisioner pod 會將這個 helper pod 洗掉,至此,一次本地存盤的動態創建完成,
9. xlss 自動災難恢復作業流程

完整的自動災難恢復作業流程要經歷 6 個階段:
- 資料備份:以 pod 為粒度,對 pv 資料進行備份,
- 節點例外:此時集群出現例外情況,某一節點發生例外,比如服務器損壞,引起在其上面的 pod 作業例外,最后有狀態服務的 pod 就會一直處于 Terminating 狀態,
- 例外 pod 處理:當有狀態服務的 pod 處于 Terminating 狀態時,要清理掉這些 pod,可以手動洗掉,也可借助工具,讓這些有狀態的 pod 有重新創建的機會,
- 智能調度 :解除親和性,將新 pod 調度到健康的節點上,
- 資料恢復:拉取該 pod 對應的最新的快照資料進行資料恢復,
- 服務恢復:啟動應用,對外提供服務,
至此,一個完整的自動災難恢復作業流程結束,最后又回到起點,
大規模存盤型中間件服務
存盤問題基本解決了,那該怎么落地呢?答案就是建設存盤型中間件服務,
1. Kafka Cluster In K8s

以 kafka 集群為例,通過定制化的 kafka operator 來部署 kafka 集群,指定存盤服務使用 xlss 存盤,采取定制化 Operator + xlss 模式去建設存盤型中間件服務,
2. 有狀態中間件服務 In K8s

有狀態中間件服務在 K8s 中的運行狀態如上圖所示,這些存盤型中間件服務集群托管于對應的 Operator,底層存盤根據業務需要適配各類存盤,隨著中間件服務集群規模的日益擴大,我們建設了 PaaS 控制面,用戶可以通過該控制面來管理運行在 K8s 中的各類中間件服務集群,控制面可以直接和 apiserver 互動,用戶通過控制面增刪改 CRD 資源,Operator 根據 CRD 資源的最新狀態,調和中間件服務集群的狀態,
3. 用戶申請中間件服務示例

這是用戶申請中間件服務的示例:用戶通過管理臺申請服務,填寫相關的配置資訊后,申請通過后,就可以在 K8s 集群里面創建相應的服務了,
基于 KubeSphere 部署 XLSS
如果希望使用 xlss 存盤,那該怎么部署呢?
若是首次部署,首先要做好本地磁盤的規劃,創建好提供給 xlss 使用的存盤空間,然后,就是將 xlss 的各個組件運行到 K8s 集群中,將 xlss 組件部署到 K8s 集群中,我們借助了 KubeSphere 的 CI/CD 流水線,自定義流水線一共 5 步,實作將 xlss 組件從靜態代碼到運行在 K8s 中的容器的轉換,高度自動化維護,
CI/CD 流水線如下圖所示:

Road Map

目前,新東方的有狀態服務容器化建設大致可分成 4 階段,
第一階段:“云前時代”
有狀態服務容器化的起點,確定了容器化的目標,這個階段有狀態服務主要特征是 VM+PaaS 組合的模式管理有狀態服務,實作的主要功能:資源管理、白屏運維、簡單調度策略、運行時管理,
第二階段:“初上云端”
從這個階段開始,嘗試將有狀態服務從 VM 中解脫出來,遷移到 K8s 平臺,這個階段有狀態服務主要特征是 K8s+Operator 組合的模式管理有狀態服務,
這時,運行時被托管到 K8s,有狀態服務由 Opeartor 接管,自動化程度顯著提高,此時也暴露出一些不足:比如遠端存盤的性能不夠好,本地存盤的可用性不能保證,
第三階段:“自研之路”
主要是新東方自研 xlss 的實踐階段,前面章節已有涉及,此階段有狀態服務建設的典型特征:Scheduler + Logical Backup 組合模式,這基本達到了我們期望的:本地存盤 + 動態供給 + 資料可用性保證,但事情永遠都不會那么完美,那還有那些瑕疵呢?
- 資料恢復時長取決于資料量大小,如果資料量很大,恢復時間也會增大,在 node 例外發生的情況下,這就增大了有狀態服務的不可用時間,
- 現在 PV 資料還沒能做到存盤隔離,無法約束應用對存盤的使用量,會存在一定的風險,
瑕不掩瑜,在小規模存盤場景:如 redis、kafka 等還是有用武之地的,但是對于大資料量的服務,目前 xlss 的能力還有些勉強,
第四階段:“追求卓越”
在這個階段,有狀態服務建設的典型特征:Isolation + Physical Backup 組合模式,重點會解決第三階段發現的瑕疵,大致的解決思路是:利用 LVM 技術實作存盤的隔離;利用 DRBD 技術,增加 DRBD 同步物理備份能力,實作應用資料的同步實時備份,解決由于資料量大導致恢復時間增長的問題,
在使用 DRBD 技術時,有一個需要權衡的地方,那就是副本數量的設定,若副本數量設定多些,則會增大存盤資源使用量;若副本數量設定少些,在 K8s 集群 node 例外情況下,有狀態服務 Pod 漂移可選擇的 node 數量就會減少,最終需要根據業務場景做出合理選擇,
本文由博客一文多發平臺 OpenWrite 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301175.html
標籤:其他
上一篇:最小堆、勝者樹和敗者樹
下一篇:Linux 常用指令與常識
