新東方在有狀態服務 In K8s 的實踐

KubeSphere 2021-09-18 16:22:35 阅读数:588

在有 k8s
作者|周培,新東方架構部容器組專家

有狀態服務建設一直以來都是 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

CNS Of CNCF

這是 CNCF 官網關於雲原生存儲的一副截圖。截圖時間是 2021 年 7 月初,有 50 多種存儲產品,接近半數屬於商業產品,開源產品多數都是遠端存儲類型,有支持文件系統的、有支持對象存儲的、還有支持塊存儲的。

K8s PV 類型

PV Type Defined by K8s

數據來源於官網,原生 K8s 支持的 PV 類型,有常用的 rbd、hostpath、local 等類型。

如何選擇?

控制器只有 StatefulSet 控制器可使用,存儲產品很多,PV 類型也不少,該怎麼選擇呢?

存儲服務考慮因素示意圖

選擇存儲產品,需要考慮哪些因素呢?新東方在選擇存儲產品時考慮了以下一些因素:

  • 開源 VS 商業
  • 本地 VS 遠端
  • 動態供給 VS 靜態供給
  • 數據高可用方案

做選擇是令人頭疼的事情,比如選擇開源,好處是不用花錢,但穩定性就很難保證,甚至提供的能力也有限;商業產品能力和穩定性有保證,但要付費。在這裏先不下結論,最終還是要看需求。

自研存儲產品 XLSS

1. 關鍵需求

新東方有狀態服務建設的關鍵需求:良好的性能,支持 IO 密集型應用;數據可用性,具有一定的容灾能力;動態供給,實現有狀態服務的完全自動化管理。

2. XLSS 介紹

XLSS

XLSS(XDF Local Storage Service)中文全稱:新東方本地存儲服務產品,是一種基於本地存儲的高性能、高可用存儲方案。可以解决 K8s 中本地存儲方案的不足之處:localpv 只能靜態供給;使用 localpv 時,pod 與 node 的親和性綁定造成的可用性降低;本地存儲存在數據丟失的風險。

應用場景

  • 高性能應用,IO 密集型的應用軟件,比如 Kafka
  • 本地存儲的動態化管理
  • 數據安全,應用數據定期備份,備份數據加密保護
  • 存儲資源監控告警,比如 K8s Pv 資源的使用量監控告警

3. XLSS In K8s

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 調度框架模型

如上圖,這是 K8s 調度器的調度框架模型,在調度流程中包含了許多擴展點。xlss-scheduler 就是基於該調度框架模型,通過編寫自定義的插件實現,主要在 3 個擴展點上做了增强:

  • Prefilter:依據 Pod 的節點親和性,分析親和性節點的健康狀態,若節點异常,對 Pod 設置特殊標記。
  • Filter:針對設置特殊標記的 Pod,解除節點親和性。
  • Prebind:對設置特殊標記的 Pod,删除特殊標記,根據調度結果,發送數據恢複請求。

6. xlss-rescuer 數據備份作業實現邏輯

數據備份作業實現邏輯

圖中 3 個部分,左右各一個循環邏輯,中間通過一個緩存隊列實現通信。左邊的循環實現的功能:收集備份作業策略,並更新到緩存隊列中。主要 3 步:

  1. watch pod 事件
  2. 從 pod 注解當中獲取備份策略,備份作業的配置信息是通過 pod 注解實現的
  3. 同步備份策略到緩存隊列

右邊的循環實現的功能:執行備份作業。也是 3 步:

  1. 對緩存隊列元素排序,排序按照下次備份作業的執行時間點進行昇序排列
  2. 休眠等待,若當前時間還沒有到最近的一個備份作業執行時間,就會進行休眠等待
  3. 執行備份作業

7. xlss-rescuer 數據恢複作業實現邏輯

 title=

數據恢複作業流程和數據備份作業流程實現思路是類似的,但在具體實現邏輯上有所不同。

左邊的循環實現的功能:監視恢複作業請求,並更新到緩存隊列中。主要 3 步:

  1. watch CRD,監視數據恢複請求,接收 xlss-scheduler 發出的數據恢複請求(數據恢複請求以 CRD 方式實現)
  2. 分析 CRD 狀態,避免重複處理
  3. 同步恢複請求到緩存隊列

右邊的循環實現的功能:執行恢複作業。這裏是 4 步:

  1. 更新 CRD 實例狀態
  2. 恢複快照數據到指定目錄
  3. 更新 PV 與 PVC
  4. 删除 CRD 實例

8. xlss-localpv-provisioner 存儲創建實現思路

本地存儲動態創建示意圖

xlss-localpv-provisioner 組件,其功能比較專一,實現本地存儲的動態創建。其工作流程當 provisioner pod 獲取到創建存儲的請求時,首先會創建一個臨時的 helper pod,這個 helper pod 會被調度到指定的 node 上面,創建文件目錄作為本地存儲使用,這就完成了 pv 實際後端存儲的創建,當存儲創建完畢,provisioner pod 會將這個 helper pod 删除。至此,一次本地存儲的動態創建完成。

9. xlss 自動灾難恢複工作流程

xlss 自動灾難恢複工作流程

完整的自動灾難恢複工作流程要經曆 6 個階段:

  • 數據備份:以 pod 為粒度,對 pv 數據進行備份。
  • 節點异常:此時集群出現异常情况,某一節點發生异常,比如服務器損壞,引起在其上面的 pod 工作异常,最後有狀態服務的 pod 就會一直處於 Terminating 狀態。
  • 异常 pod 處理:當有狀態服務的 pod 處於 Terminating 狀態時,要清理掉這些 pod,可以手動删除,也可借助工具,讓這些有狀態的 pod 有重新創建的機會。
  • 智能調度 :解除親和性,將新 pod 調度到健康的節點上。
  • 數據恢複:拉取該 pod 對應的最新的快照數據進行數據恢複。
  • 服務恢複:啟動應用,對外提供服務。

至此,一個完整的自動灾難恢複工作流程結束,最後又回到起點。

大規模存儲型中間件服務

存儲問題基本解决了,那該怎麼落地呢?答案就是建設存儲型中間件服務。

1. Kafka Cluster In K8s

Kafka Cluster In K8s

以 kafka 集群為例,通過定制化的 kafka operator 來部署 kafka 集群,指定存儲服務使用 xlss 存儲。采取定制化 Operator + xlss 模式去建設存儲型中間件服務。

2. 有狀態中間件服務 In K8s

Stateful Apps 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 流水線如下圖所示:

CI/CD 流水線

Road Map

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 發布!
版权声明:本文为[KubeSphere]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210918162234908H.html