TiDB Operator,讓 TiDB 成為真正的 Cloud-Native 資料庫

PingCAP發表於2018-08-23

TiDB Operator 是 TiDB 在 Kubernetes 平臺上的自動化部署運維工具。目前,TiDB Operator 已正式開源(pingcap/tidb-operator)。藉助 TiDB Operator,TiDB 可以無縫執行在公有云廠商提供的 Kubernetes 平臺上,讓 TiDB 成為真正的 Cloud-Native 資料庫。

要了解 TiDB Operator,首先需要對 TiDB 和 Kubernetes 有一定了解,相信長期以來一直關注 TiDB 的同學可能對 TiDB 已經比較熟悉了。本文將首先簡單介紹一下 TiDB 和 Kubernetes,聊一聊為什麼我們要做 TiDB Operator,然後講講如何快速體驗 TiDB Operator,以及如何參與到 TiDB Operator 專案中來成為 Contributor。

TiDB 和 Kubernetes 簡介

TiDB 作為一個開源的分散式資料庫產品,具有多副本強一致性的同時能夠根據業務需求非常方便的進行彈性伸縮,並且擴縮容期間對上層業務無感知。TiDB 包括三大核心元件:TiDB/TiKV/PD。

  • TiDB Server:主要負責 SQL 的解析器和優化器,它相當於計算執行層,同時也負責客戶端接入和互動。

  • TiKV Server:是一套分散式的 Key-Value 儲存引擎,它承擔整個資料庫的儲存層,資料的水平擴充套件和多副本高可用特性都是在這一層實現。

  • PD Server:相當於分散式資料庫的大腦,一方面負責收集和維護資料在各個 TiKV 節點的分佈情況,另一方面 PD 承擔排程器的角色,根據資料分佈狀況以及各個儲存節點的負載來採取合適的排程策略,維持整個系統的平衡與穩定。

上面的這三個元件,每個角色都是一個多節點組成的叢集,所以最終 TiDB 的架構看起來是這樣的。

TiDB-架構.png

Kubernetes 最早是作為一個純粹的容器編排系統而誕生的,使用者部署好 Kubernetes 叢集之後,直接使用其內建的各種功能部署應用服務。

由於這個 PaaS 平臺使用起來非常便利,吸引了很多使用者,不同使用者也提出了各種不同的需求。有些特性需求 Kubernetes 直接在其核心程式碼裡面實現了,但是有些特性並不適合合併到主幹分支。

為滿足這類需求,Kubernetes 開放出一些 API 供使用者自己擴充套件,實現自己的需求。當前 Kubernetes 內部的 API 變得越來越開放,使其更像是一個跑在雲上的作業系統。使用者可以把它當作一套雲的 SDK 或 Framework 來使用,而且可以很方便地開發元件來擴充套件滿足自己的業務需求。對有狀態服務的支援就是一個很有代表性的例子。

為什麼我們要做 TiDB Operator

第一,使用傳統的自動化工具帶來了很高的部署和運維成本。TiDB 的分層架構對於分散式系統是比較常見的,各個元件都可以根據業務需求獨立水平伸縮,並且 TiKV 和 TiDB 都可以獨立使用。比如,在 TiKV 之上可以構建相容 Redis 協議的 KV 資料庫,而 TiDB 也可以對接 LevelDB 這樣的 KV 儲存引擎。

但是,這種多元件的分散式系統增加了手工部署和運維的成本。一些傳統的自動化部署和運維工具如 Puppet/Chef/SaltStack/Ansible,由於缺乏全域性狀態管理,不能及時對各種異常情況做自動故障轉移,並且很難發揮分散式系統的彈性伸縮能力。其中有些還需要寫大量的 DSL 甚至與 Shell 指令碼一起混合使用,可移植性較差,維護成本比較高。

第二,在雲時代,容器成為應用分發部署的基本單位,而谷歌基於內部使用數十年的容器編排系統 Borg 經驗推出的開源容器編排系統 Kubernetes 成為當前容器編排技術事實上的標準。如今各大雲廠商都開始提供託管的 Kubernetes 叢集,部署在 Kubernetes 平臺的應用可以不用繫結在特定雲平臺,輕鬆實現在各種雲平臺之間的遷移,其容器化打包和釋出方式也解決了對作業系統環境的依賴。

Kubernetes 專案最早期只支援無狀態服務(Stateless Service)的管理。無狀態服務通過 ReplicationController 定義多個副本,由 Kubernetes 排程器來決定在不同節點上啟動多個 Pod,實現負載均衡和故障轉移。對於無狀態服務,多個副本對應的 Pod 是等價的,所以在節點出現故障時,在新節點上啟動一個 Pod 與失效的 Pod 是等價的,不會涉及狀態遷移問題,因而管理非常簡單。

但是對於有狀態服務(Stateful Service),由於需要將資料持久化到磁碟,使得不同 Pod 之間不能再認為成等價,也就不能再像無狀態服務那樣隨意進行排程遷移。

Kubernetes v1.3 版本提出 PetSet 的概念,用來管理有狀態服務並於 v1.5 將其更名為 StatefulSet。StatefulSet 明確定義一組 Pod 中每個的身份,啟動和升級都按特定順序來操作。另外使用持久化卷儲存(PersistentVolume)來作為儲存資料的載體,當節點失效 Pod 需要遷移時,對應的 PV 也會重新掛載,而 PV 的底層依託於分散式檔案系統,所以 Pod 仍然能訪問到之前的資料。同時 Pod 在發生遷移時,其網路身份例如 IP 地址是會發生變化的,很多分散式系統不能接受這種情況。所以 StatefulSet 在遷移 Pod 時可以通過繫結域名的方式來保證 Pod 在叢集中網路身份不發生變化。

但是由於有狀態服務的特殊性,當節點出現異常時,出於資料安全性考慮,Kubernetes 並不會像無狀態服務那樣自動做故障轉移。儘管網路儲存能掛載到不同的節點上供其上的 Pod 使用,但是如果出現節點故障時,簡單粗暴地將網路 PV 掛載到其它節點上是比較危險的。

Kubernetes 判斷節點故障是基於部署在每個節點上的 Kubelet 服務是否能正常上報節點狀態,Kubelet 能否正常工作與使用者應用並沒有必然聯絡,在一些特殊情況下,Kubelet 服務程式可能無法正常啟動,但是節點上的業務容器還在執行,將 PV 再掛載到其它節點可能會出現雙寫問題。

為了在 Kubernetes 上部署和管理 TiDB 這種有狀態的服務,我們需要擴充套件 StatefulSet 的功能。TiDB Operator 正是基於 Kubernetes 內建的 StatefulSet 開發的 TiDB 叢集管理和運維工具。

Kubernetes 直到 v1.7 才試驗性引入本地 PV,在這之前只有網路 PV,TiKV 自身在儲存資料時就是多副本的,網路 PV 的多副本會增加資料冗餘,降低 TiDB 的效能。在這之前我們基於 Kubernetes 內建的 hostPath volume 實現了本地 PV 滿足 TiKV 對磁碟 IO 的要求。官方本地 PV 方案直到最近的 Kubernetes v1.10 才相對穩定地支援排程功能,滿足使用者對本地 PV 的需求。為了降低使用者的使用和管理成本並且擁抱 Kubernetes 開源社群,我們又重新基於官方的本地 PV 方案實現了對資料的管理。

TiDB Operator 原理解析

Operator 本質上是 Kubernetes 的控制器(Controller),其核心思想是使用者給定一個 Spec 描述檔案,Controller 根據 Spec 的變化,在 Kubernetes 叢集中建立對應資源,並且不斷調整資源使其狀態滿足使用者預期的 Spec。

TiDB-Operator.png

上圖是 TiDB Operator 工作流程原理圖,其中 TidbCluster 是通過 CRD(Custom Resource Definition)擴充套件的內建資源型別:

  1. 使用者通過 Helm 往 Kubernetes API Server 建立或更新 TidbCluster 物件。

  2. TiDB Operator 通過 watch API Server 中的 TidbCluster 物件建立更新或刪除,維護 PD/TiKV/TiDB StatefulSet, Service 和 Deployment 物件更新。

  3. Kubernetes 根據 StatefulSet, Service 和 Deployment 物件建立更新或刪除對應的容器和服務。

在第 2 步中,TiDB Operator 在更新 StatefulSet 等物件時會參考 PD API 給出的叢集狀態來做出 TiDB 叢集的運維處理。通過 TiDB Operator 和 Kubernetes 的動態排程處理,建立出符合使用者預期的 TiDB 叢集。

快速體驗 TiDB Operator

TiDB Operator 需要執行在 Kubernetes v1.10 及以上版本。TiDB Operator 和 TiDB 叢集的部署和管理是通過 Kubernetes 平臺上的包管理工具 Helm 實現的。執行 TiDB Operator 前請確保 Helm 已經正確安裝在 Kubernetes 叢集裡。

如果沒有 Kubernetes 叢集,可以通過 TiDB Operator 提供的指令碼快速在本地啟動一個多節點的 Kubernetes 叢集:

git clone https://github.com/pingcap/tidb-operator
cd tidb-operator
NUM_NODES=3    # the default node number is 2
KUBE_REPO_PREFIX=uhub.ucloud.cn/pingcap manifests/local-dind/dind-cluster-v1.10.sh up
複製程式碼

等 Kubernetes 叢集準備好,就可以通過 Helm 和 Kubectl 安裝部署 TiDB Operator 和 TiDB 叢集了。

  1. 安裝 TiDB Operator

    kubectl apply -f manifests/crd.yaml
    helm install charts/tidb-operator --name=tidb-operator --namespace=tidb-	admin
    複製程式碼
  2. 部署 TiDB 叢集

    helm install charts/tidb-cluster --name=demo-tidb --namespace=tidb --set clusterName=demo
    複製程式碼

叢集預設使用 local-storage 作為 PD 和 TiKV 的資料儲存,如果想使用其它持久化儲存,需要修改 charts/tidb-cluster/values.yaml 裡面的 storageClassName。

參與 TiDB Operator

TiDB Operator 讓 TiDB 成為真正意義上的 Cloud-Native 資料庫,開源只是一個起點,需要 TiDB 社群和 Kubernetes 社群的共同參與。

大家在使用過程發現 bug 或缺失什麼功能,都可以直接在 GitHub 上面提 issue 或 PR,一起參與討論。要想成為 Contributor 具體可以參考 這個文件

作者:鄧栓

相關文章