基於 Nebula Operator 的 K8s 自動化部署運維

NebulaGraph發表於2020-11-18

Nebula Operator

摘要:Nebula Operator 是 Nebula Graph 在 Kubernetes 系統上的自動化部署運維外掛。在本文,你將瞭解到 Nebula Operator 的特性及它的工作原理。

從 Nebula Graph 的架構談起

Nebula Graph 架構圖

Nebula Graph 是一個高效能的分散式開源圖資料庫,從架構上可以看出,一個完整的 Nebula Graph 叢集由三類服務組成,即 Meta Service, Query Service(Computation Layer)和 Storage Service(Storage Layer)。

每類服務都是一個由多副本元件組成的叢集,在 Nebula Operator 中,我們分別稱這三類元件為: Metad / Graphd / Storaged。

  • Metad:主要負責提供和儲存圖資料庫的後設資料,並承擔叢集中排程器的角色,指揮儲存擴容和資料遷移,leader 變更等運維操作。
  • Graphd:主要負責處理 Nebula 查詢語言語句(nGQL),每個 Graphd 都執行著一個無狀態的查詢計算引擎,且彼此間無任何通訊關係。計算引擎僅從 Metad 叢集中讀取元資訊,並和 Storaged 叢集進行互動。同時,它也負責不同客戶端的接入和互動。
  • Storaged:主要負責 Graph 資料儲存。圖資料被切分成很多的分片 Partition,相同 ID 的 Partition 組成一個 Raft Group,實現多副本一致性。Nebula Graph 預設的儲存引擎是 RocksDB 的 Key-Value 儲存。

在瞭解了 Nebula Graph 核心元件的功能後,我們可以得出一些結論:

  1. Nebula Graph 在設計上採用了儲存計算分離的架構,元件間分層清晰,職責明確,這意味著各個元件都可以根據自身的業務需求進行獨立地彈性擴容、縮容,非常適合部署在 Kubernetes 這類容器編排系統上,充分發揮 Nebula Graph 叢集的彈性擴縮能力。
  2. Nebula Graph 是一個較為複雜的分散式系統,它的部署和運維操作需要比較深入的領域知識,這帶來了頗高的學習成本和負擔。即使是部署執行在 Kubernetes 系統之上,有狀態應用的狀態管理、異常處理等需求,原生的Kubernetes 控制器也不能很好的滿足,導致 Nebula Graph 叢集不能發揮出它最大的能力。

因此,為了充分發揮 Nebula Graph 原生具備的彈性擴縮、故障轉移等能力,也為了降低對 Nebula Graph 叢集的運維管理門檻,我們開發了 Nebula Operator。

Nebula Operator 是 Nebula Graph 在 Kubernetes 系統上的自動化部署運維外掛,依託於 Kubernetes 自身優秀的擴充套件機制,我們把 Nebula Graph 運維領域的知識,以 CRD + Controller 的形式全面注入到 Kubernetes 系統中,讓 Nebula Graph 成為真正的雲原生圖資料庫。

為了能夠更好的理解 Nebula Operator 的工作原理,讓我們先回顧一下什麼是 Operator

什麼是 Nebula Operator

Operator 並不是什麼很新的概念,早在 2017 年,就有 CoreOS 公司推出了 Etcd Operator。Operator 的初衷是為了擴充套件 Kubernetes 功能,以更好的管理有狀態應用,這得益於 Kubernetes 的兩大核心概念:宣告式 API 和控制迴圈(Control Loop)。

我們可以用一段虛擬碼來描述這一過程。

在叢集中宣告物件X的期望狀態並建立X
for {
  實際狀態 := 獲取叢集中物件 X 的實際狀態
  期望狀態 := 獲取叢集中物件 X 的期望狀態
  if 實際狀態 == 期望狀態 {
    什麼都不做
  } else {
    執行事先規定好的編排動作,將實際狀態調協為期望狀態
  }
}

在 Kubernetes 系統內,每一種內建資源物件,都執行著一個特定的控制迴圈,將它的實際狀態通過事先規定好的編排動作,逐步調整為最終的期望狀態。

對於 Kubernetes 系統內不存在的資源型別,我們可以通過新增自定義 API 物件的方式註冊。常見的方法是使用 CustomResourceDefinition(CRD)和 Aggregation ApiServer(AA)。Nebula Operator 就使用 CRD 註冊了一個 "Nebula Cluster" 資源,和一個 "Advanced Statefulset" 資源。

在註冊了上述自定義資源之後,我們就可以通過編寫自定義控制器的方式來感知自定義資源的狀態變化,並按照我們編寫的策略和邏輯去自動地運維 Nebula Graph,讓叢集的實際狀態朝著期望狀態趨近。這也是 Nebula Operator 降低使用者運維門檻的核心原理。

apiVersion: nebula.com/v1alpha1
kind: NebulaCluster
metadata:
  name: nebulaclusters
  namespace: default
spec:
  graphd:
    replicas: 1
    baseImage: vesoft/nebula-graphd
    imageVersion: v2-preview-nightly
    service:
      type: NodePort
      externalTrafficPolicy: Cluster
    storageClaim:
      storageClassName: fast-disks
  metad:
    replicas: 3
    baseImage: vesoft/nebula-metad
    imageVersion: v2-preview-nightly
    storageClaim:
      storageClassName: fast-disks
  storaged:
    replicas: 3
    baseImage: vesoft/nebula-storaged
    imageVersion: v2-preview-nightly
    storageClaim:
      storageClassName: fast-disks
  schedulerName: nebula-scheduler
  imagePullPolicy: Always

我們在這裡展示了一個簡單的 Nebula Cluster 例項,如果你想要擴充套件 Storaged 的副本數量至 10,你只需要簡單修改 .spec.storaged.replicas 引數為 10,剩下的運維操作則由 Nebula Operator 通過控制迴圈來完成。

至此,想必你已經對 Nebula Graph 和 Operator 有了一個初步的認知,接下來,讓我們來列舉目前 Nebula Operator 已經具備了哪些能力,讓你能更加深刻的體會到使用 Nebula Operator 帶來的一些實際好處。

  • 部署、解除安裝:我們將一整個 Nebula Graph 叢集描述成一個 CRD 註冊進 ApiServer 中,使用者只需提供對應的 CR 檔案,Operator 就能快速拉起或者刪除一個對應的 Nebula Graph 叢集,簡化了使用者部署、解除安裝叢集的過程。
  • 擴容、縮容:通過在控制迴圈中呼叫 Nebula Graph 原生提供的擴縮容介面,我們為 Nebula Operator 封裝實現了擴縮容的邏輯,可以通過 yaml 配置進行簡單的擴容,縮容,且保證資料的穩定性。
  • 原地升級:我們在 Kubernetes 原生提供的 StatefulSet 基礎上為其擴充套件了映象原地替換的能力,它節省了 Pod 排程的耗時,並且在升級時,Pod 的位置、資源都不發生變化,極大提高了升級時叢集的穩定性和確定性。
  • 故障遷移:Nebula Operator 會內部呼叫 Nebula Graph 叢集提供的介面,動態的感知服務是否正常執行,一旦發現異常,會自動的去做故障遷移操作,並根據錯誤型別配有對應的容錯機制。
  • WebHook:一個標準的 Nebula Graph 最少需要三個 Metad 副本,如果使用者錯誤地修改了此引數,可能會導致叢集不可用,我們會通過 WebHook 的准入控制來檢查一些必要引數是否設定正確,並通過變更控制來強制修改一些錯誤的宣告,使叢集始終能夠穩定執行。

參考資料

作者有話說:Hi,我是劉鑫超,圖資料庫 Nebula Graph 的研發工程師,如果你對此文有疑問,歡迎來我們的 Nebula Graph 論壇交流下心得~~

相關文章