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


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 論壇交流下心得~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM