K8s 的最后一片拼圖:dbPaaS
共 9395字,需瀏覽 19分鐘
·
2024-07-17 11:41
來源:infoQ公眾號(hào),作者:曹偉,云猿生數(shù)據(jù)創(chuàng)始人 & CEO
K8s 的發(fā)展使得私有云跟公共云之間的技術(shù)差不斷的縮小,不管是在私有云還是公共云,大家今天都在基于 K8s 去開發(fā) PaaS 系統(tǒng)。而 K8s 作為構(gòu)建 PaaS 的基礎(chǔ),其全景圖里還缺最后一塊“拼圖”——dbPaaS。作為一個(gè)云數(shù)據(jù)庫(kù)行業(yè)干了十幾年的資深從業(yè)者,以及一個(gè)云數(shù)據(jù)庫(kù)初創(chuàng)公司的創(chuàng)始人,在本文中,我將結(jié)合近年來數(shù)據(jù)庫(kù)和云計(jì)算的發(fā)展方向,以及我們?cè)诩夹g(shù)和工程上的實(shí)踐,分享一些看法。
近年來, 數(shù)據(jù)庫(kù)整個(gè)領(lǐng)域主要在以下三個(gè)方向上發(fā)展: 公共云全托管,Serverless 和私有化部署。
公共云全托管,包括各家云廠商的 RDS,以及每家云廠商自研的數(shù)據(jù)庫(kù),如 PolarDB、Aurora 等等,都屬于這個(gè)板塊。大部分公共云用戶都是用這個(gè)服務(wù),這個(gè)板塊比較成熟穩(wěn)定,跟著公共云的規(guī)模一起緩慢增長(zhǎng)。公共云的主要的優(yōu)勢(shì)是彈性,有更多彈性需求的用戶都在被吸引到公有云的 Serverless 產(chǎn)品上。而海外很多初創(chuàng)的公司,像 CockroachDB、Neon、 PlanetScale,包括中國(guó)的初創(chuàng)公司 TiDB 都在往 Serverless,無服務(wù)器數(shù)據(jù)庫(kù)這個(gè)方向發(fā)展。
另外一個(gè)方向就是私有化部署。有報(bào)告說中國(guó)公共云的服務(wù)器大概只占服務(wù)器總數(shù)的 5% ,線下部署的比例是非常高的。大型的互聯(lián)網(wǎng)公司、央國(guó)企、銀行都是用私有云。國(guó)內(nèi)的信創(chuàng)數(shù)據(jù)庫(kù)基本上都是在做這個(gè)方向。本質(zhì)上來講,企業(yè)選擇什么數(shù)據(jù)庫(kù)是由企業(yè)的業(yè)務(wù)場(chǎng)景來決定的,很少會(huì)因?yàn)檫x擇一個(gè)數(shù)據(jù)庫(kù)而倒推上面的云和架構(gòu)。
企業(yè)對(duì)云的選擇和使用是一直在變化的。選擇私有云有很多原因,內(nèi)因比如說合規(guī)、成本控制、自主可控,外因主要是 K8s。
第一個(gè)變化是中國(guó)的私有云正在從 OpenStack 全面進(jìn)化到 K8s。過去的私有云,是用 OpenStack 管理物理機(jī)生產(chǎn)虛擬機(jī)。如果客戶要用容器和 K8s 再在虛擬機(jī)上去搭上面的容器。但是最近,大家都開始用 K8s 去管理物理機(jī),業(yè)務(wù)最好是能夠全部容器化、云原生化。如果你要用虛擬機(jī),可以在 K8s 上管理,例如用 kubevirt 這樣的技術(shù)在 Pod 里面跑虛擬機(jī),底層是 K8s,VM 在上層,這是一個(gè)挺大的變化。
第二個(gè)變化是 K8s 的發(fā)展使得私有云跟公共云之間的技術(shù)差逐步變窄。公共云和私有云上的 K8s 技術(shù)差別并不大。過去云廠商主要的技術(shù)壁壘都在于我怎么把幾百萬臺(tái)虛擬機(jī)運(yùn)維好,用規(guī)模優(yōu)勢(shì)來降低成本,但是這樣的技術(shù)在 K8s 面前就像馬奇諾防線一樣被繞過了。公共云和私有云今天都得站在怎么把容器做好,怎么把 K8s 生態(tài)做好這同一條起跑線上。
第三個(gè)趨勢(shì)是,不管運(yùn)行在私有云還是公共云,大家都在基于 K8s 去開發(fā) PaaS 系統(tǒng)。K8s 作為一個(gè)多云的,可以一統(tǒng)公共云、私有云的容器操作系統(tǒng),可以屏蔽底層 IaaS 的差異,讓上層通過 Pod、Service、PVC 等抽象來操作 IaaS 資源。調(diào)度器、服務(wù)發(fā)現(xiàn)、配置管理、API Server 等等這些開發(fā)一個(gè) PaaS 所需要依賴的基礎(chǔ)能力,K8s 都提供了,不僅可以節(jié)約很多開發(fā)成本,而且 K8s 在設(shè)計(jì)和工程上都做的更好。比如說,K8s 的 API 是聲明式 API,這個(gè)就是個(gè)挺先進(jìn)的設(shè)計(jì)。公共云廠商做的比較早,在設(shè)計(jì) API 的時(shí)候還沒有這個(gè)理念,所以 API 都是過程式的。但后來的系統(tǒng),比方說 Terraform,就用的聲明式 API,所以開發(fā)者使用起來更簡(jiǎn)單,書寫起來更容易理解,也更不容易出錯(cuò)。在 K8s 上做 PaaS 就可以利用好這些后發(fā)優(yōu)勢(shì)。
K8s 作為構(gòu)建 PaaS 的基礎(chǔ),其全景圖里還缺最后一塊“拼圖”——dbPaaS。在 K8s 上構(gòu)建 dbPaaS 是大勢(shì)所趨。所有的 PaaS 都在用 K8s 做自己的底座,dbPaaS,就是數(shù)據(jù)庫(kù)的 PaaS 也不例外。如果企業(yè)的私有云都用 K8s 來構(gòu)建,再搞一套虛擬機(jī)或者物理機(jī)的管理平臺(tái),然后在這個(gè)基礎(chǔ)上發(fā)明一套 K8s 已經(jīng)有了的能力,再做數(shù)據(jù)庫(kù)的管理,其實(shí)是一個(gè)重復(fù)建設(shè),不是特別合理。
dbPaaS 有哪些挑戰(zhàn)?我過去在阿里云做 RDS,最深有體會(huì)的一件事情是數(shù)據(jù)庫(kù)的類目太多了,版本也太多了。大家使用的組合里面至少幾十種數(shù)據(jù)庫(kù)的不同版本。
每一種數(shù)據(jù)庫(kù)的運(yùn)維操作都也很復(fù)雜,因?yàn)閿?shù)據(jù)庫(kù)是存儲(chǔ)企業(yè)關(guān)鍵數(shù)據(jù)的基礎(chǔ)設(shè)施,運(yùn)維操作精細(xì)而復(fù)雜。與之對(duì)應(yīng)的就是人不夠,與之對(duì)應(yīng)的痛苦就是人手不夠,挺多事情都是可以靠堆人去做的,但是作為云廠商,要考慮向做一件事情投入人力的 ROI(投資回報(bào)率),也就是人效。
說到人效,這里就要說到煙囪式架構(gòu)這個(gè)陷阱。企業(yè)在構(gòu)建 dbPaaS 的時(shí)候,方法通常是對(duì)于每一種要支持的數(shù)據(jù)庫(kù),就搞一個(gè)獨(dú)立的小團(tuán)隊(duì),然后寫一套獨(dú)立的代碼,甚至有的時(shí)候連運(yùn)維人員都是獨(dú)立的。這種做法人效低,因?yàn)橹蚊扛鶡焽璧娜肆Χ际且粋€(gè)小池子,人員很難在煙囪之間流動(dòng),因此用煙囪式架構(gòu)去支持 dbPaaS 這種長(zhǎng)尾市場(chǎng)的業(yè)務(wù),是一個(gè)錯(cuò)誤的選擇。拉長(zhǎng)時(shí)間看,人員變動(dòng)引起故障的概率在煙囪式架構(gòu)里更高。還有更多的問題,比如資源不能做到跨引擎共享和混部,會(huì)增加部署一套 dbPaaS 的起步成本。
用一種新的方法去實(shí)現(xiàn) dbPaaS。今天各種各樣的數(shù)據(jù)庫(kù)都會(huì)發(fā)布自己的容器,容器本身就是一個(gè)標(biāo)準(zhǔn)的東西,那我們能不能像搭積木一樣的,在 K8s 上把它們給組裝起來部署提供服務(wù),然后把它們的運(yùn)維操作,也以一種標(biāo)準(zhǔn)地去組裝?
樂高積木能夠拼搭成各種各樣的藍(lán)圖,其本質(zhì)在于樂高是高度標(biāo)準(zhǔn)化的。它的凸起凹槽、厚度,都是有標(biāo)準(zhǔn)的。如果想讓數(shù)據(jù)庫(kù)像樂高積木一樣的能夠搭起來,也要解決一個(gè)標(biāo)準(zhǔn)問題,然后把各種各樣的數(shù)據(jù)庫(kù)容器適配到這個(gè)標(biāo)準(zhǔn)上。
在計(jì)算機(jī)科學(xué)當(dāng)中,有幾個(gè)比較著名的標(biāo)準(zhǔn),比如說 POSIX,POSIX 是對(duì)文件系統(tǒng)操作接口的抽象。K8s 里面有容器運(yùn)行時(shí)標(biāo)準(zhǔn) CRI,容器存儲(chǔ)標(biāo)準(zhǔn) CSI,容器網(wǎng)絡(luò)標(biāo)準(zhǔn) CNI,等等。通過這些標(biāo)準(zhǔn),各種各樣的容器網(wǎng)絡(luò)、存儲(chǔ)、分布式存儲(chǔ)的項(xiàng)目都可以對(duì)接到 K8s 生態(tài)中去。除了標(biāo)準(zhǔn)和抽象之外,還有一個(gè)我們值得借鑒的方法叫分層,比如說 OSI 的 7 層網(wǎng)絡(luò)協(xié)議和 TCP/IP 4 層協(xié)議。通過分層,各家廠商的網(wǎng)絡(luò)產(chǎn)品軟硬件、各種協(xié)議,都能找到合適的一個(gè)層次,通過層與層之間的標(biāo)準(zhǔn)接口,適配起來組成一個(gè)完整的系統(tǒng)。
我們通過抽象和分層這兩種方法來定義容器化數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn),設(shè)計(jì)了 API,本質(zhì)上它類似于 POSIX API,是一個(gè)標(biāo)準(zhǔn)。我們先看下 POSIX API,有了 POSIX API 之后,上層的應(yīng)用就可以用一個(gè)很標(biāo)準(zhǔn)的 API 去操作各種文件,不用管底層的文件系統(tǒng)是什么,是 ext4,xfs 還是 nfs。類似的,我們?cè)O(shè)計(jì)的 API 是一個(gè)描述多個(gè)數(shù)據(jù)庫(kù)容器之間的關(guān)系和拓?fù)浣Y(jié)構(gòu),以及每個(gè)數(shù)據(jù)庫(kù)容器的組成、可以提供的服務(wù)以及如何響應(yīng)各種事件的行為的一個(gè)描繪,它是抽象的,跟任何一種具體的數(shù)據(jù)庫(kù)是無關(guān)的,能夠表達(dá)各種各樣的數(shù)據(jù)庫(kù)。此外,在設(shè)計(jì)這個(gè) API 的時(shí)候我們也做了分層。我們分了五層,最底下一層是 K8s 的 API,它代表的 IaaS 的對(duì)象,倒數(shù)第二層是 Instance,描繪怎么把 IaaS 資源組裝起來,構(gòu)成一個(gè)單節(jié)點(diǎn)的數(shù)據(jù)庫(kù)的副本。InstanceSet 就是把多個(gè) Instance 組裝成了一個(gè)多副本的數(shù)據(jù)庫(kù)。Component 在多副本的基礎(chǔ)上,加了更多數(shù)據(jù)庫(kù)的行為,比如說成員管理,備份恢復(fù)等等。再之上是組裝成 Cluster, Cluster 就是一個(gè)完整的數(shù)據(jù)庫(kù)集群,包含多個(gè)組件。我們把不同數(shù)據(jù)庫(kù)的能力、特性都映射到這個(gè) 5 層當(dāng)中去,通過抽象和分層提出了一個(gè)數(shù)據(jù)庫(kù)容器組運(yùn)行在 K8s 上的標(biāo)準(zhǔn)。
dbPaaS Operator 的核心實(shí)現(xiàn)就是通過這個(gè)抽象的 API 來管理數(shù)據(jù)庫(kù)的生命周期,它不知道操作的數(shù)據(jù)庫(kù)是 MySQL 還是 PostgreSQL 還是 Redis,它只知道操作的是一個(gè) Cluster 對(duì)象,一個(gè) Component 對(duì)象,操作的是抽象的對(duì)象。通過這種方法就能做到 DBPaaS 最核心的控制軟件,跟被操作的數(shù)據(jù)庫(kù)引擎無關(guān)。它能做到一套代碼適配到多種的數(shù)據(jù)庫(kù)引擎上去,這是我們最核心的創(chuàng)新,是吸收了阿里云 RDS 設(shè)計(jì)、開發(fā)、維護(hù)經(jīng)驗(yàn)教訓(xùn)后的創(chuàng)新,全世界范圍目前沒有第二個(gè) dbPaaS 采用了這種設(shè)計(jì)。用戶去操作數(shù)據(jù)庫(kù)也會(huì)通過 Cluster,Component 這種標(biāo)準(zhǔn) API,不管對(duì)數(shù)據(jù)庫(kù)做任何運(yùn)維操作,體驗(yàn)會(huì)非常的接近,學(xué)習(xí)成本會(huì)比較低。
再比如 Redis 高可用部署。Redis 主從架構(gòu)會(huì)包含 Redis Server 和 Sentinel,其中 Redis Server 是一主一從兩個(gè)副本,而 Sentinel 是三節(jié)點(diǎn)。Redis 官方原生的集群架構(gòu) Redis Cluster 則是一個(gè)水平分片的集群架構(gòu),比如說有 5 個(gè)分片,可以用 5 個(gè) Component 來表達(dá),每個(gè) Component 又是一主一從兩個(gè)節(jié)點(diǎn)。
接下來一個(gè)問題是我們?cè)趺窗?30 多種數(shù)據(jù)庫(kù)給集成到一套 dbPaaS Operator 代碼里。我們?cè)倩仡櫹?POSIX API,如果一個(gè)文件系統(tǒng)想兼容 POSIX 標(biāo)準(zhǔn),讓使用 POSIX API 訪問文件系統(tǒng)的應(yīng)用程序都能操作它,就得先實(shí)現(xiàn) POSIX 接口。類似的,一個(gè)數(shù)據(jù)庫(kù)要想接入這個(gè) dbPaaS Operator,就得讓這個(gè)引擎也實(shí)現(xiàn)一組 dbPaaS Addon API。
給大家舉個(gè)例子,Redis 是怎么接入到 dbPaaS 當(dāng)中?Redis 有很多種部署形態(tài),單節(jié)點(diǎn)、主從、Sharding、還有 Redis cluster,形態(tài)有很多種。按照煙囪式的做法,每種部署形態(tài)都會(huì)是一個(gè)煙囪,一套獨(dú)立的代碼去管理。而在我們的 dbPaaS 里,不同的部署形態(tài)可以像積木一樣去組裝,不同的部署形態(tài)就是幾行 YAML 的區(qū)別。
首先我們要實(shí)現(xiàn)一個(gè)個(gè)“積木塊”?!胺e木塊”要把 Redis,Sentinel、Redis proxy 這些數(shù)據(jù)庫(kù)鏡像進(jìn)行一次包裝。對(duì)這些 Docker 鏡像,我們用 dbPaaS 的 API,用 YAML 給它們?cè)黾右恍U(kuò)展信息,里面會(huì)包含配置文件模板、服務(wù)和網(wǎng)絡(luò)的配置、以及存儲(chǔ)的配置等,還會(huì)擴(kuò)展一些被事件觸發(fā)時(shí)會(huì)執(zhí)行的腳本(Action),以及版本鏡像列表以及不同版本兼容性的描述信息等等。寫完 Redis Server 的定義,我們就可以它看作是一個(gè)“積木塊”。Redis Sentinel 和 Redis proxy 也是類似的,我們用 YAML 把它們都定義成 dbPaaS 的“積木塊”。
定義好這些“積木塊”之后,我們?cè)诹硪粋€(gè) YAML 當(dāng)中定義它的拓?fù)浣Y(jié)構(gòu),告訴 KubeBlocks 系統(tǒng)剛才那些“積木塊”該怎么組裝,就能組裝成一個(gè)集群結(jié)構(gòu)。開發(fā)一個(gè) Addon 的成本就是 寫 YAML 加上一些腳本,配置文件的模板,以及監(jiān)控的模板等等,不需要寫 Go 代碼、Java 代碼,大概就是寫幾千行的非代碼文件就能接進(jìn)來,比從頭寫一個(gè)管控?zé)焽璧拈_發(fā)成本要低多了。
關(guān)于數(shù)據(jù)庫(kù)的容器化,我常常遇到兩個(gè)問題。第一個(gè)就是容器化會(huì)不會(huì)影響數(shù)據(jù)庫(kù)的性能?第二個(gè)是 K8s 適不適合管理有狀態(tài)服務(wù)?
首先回答第一個(gè)問題。容器化不會(huì)影響數(shù)據(jù)庫(kù)的性能。容器本身其實(shí)就是 Linux 操作系統(tǒng)當(dāng)中的一個(gè)普通的進(jìn)程,只是這個(gè)進(jìn)程設(shè)置了 namespace,設(shè)置了 group,使得它能夠完成一些叫做“隔離”的障眼法。重要的事情說三遍,容器不是虛擬化,容器不是虛擬化,容器不是虛擬化。
上圖大概畫了 4 種常見的隔離方案,有虛擬化的,有 gVisor、有容器,在這四種虛擬化的方案當(dāng)中,前面三種 VM、 microVM、gVisor 都有一層虛擬化層,這層虛擬化層有的放在 hypervisor 里面,有的放在用戶態(tài),唯獨(dú)容器 runC 是沒有虛擬化這層的,它就是一個(gè)普通的進(jìn)程。所以性能上來說,在容器基礎(chǔ)上做優(yōu)化,它的底子其實(shí)是最好的。為什么要隔離呢?因?yàn)楝F(xiàn)在 CPU 的核數(shù)太多了。前兩天有一個(gè)新聞?wù)f明年 AMD、英特爾還有 ARM 的核數(shù)都要達(dá)到 200 核了,大家都在往一個(gè)服務(wù)器上塞更多的核,這樣密度更高能效更好,但這么多核數(shù)單體應(yīng)用和單體數(shù)據(jù)庫(kù)都無法消費(fèi),大家用的最多的數(shù)據(jù)庫(kù)一般都是 8C、16C,這時(shí)候一定是要用隔離技術(shù),而在隔離技術(shù)里容器的性能是最好的。
基于容器,我們做了一些優(yōu)化,把容器做到跟物理機(jī)上面的性能一樣。最顯著的,我們優(yōu)化容器存儲(chǔ)、容器網(wǎng)絡(luò)、以及數(shù)據(jù)庫(kù)的一些參數(shù),可以達(dá)到在物理機(jī)上同樣的甚至更好的性能。比如說 PostgreSQL 的吞吐,我們對(duì) PG 容器做了一些優(yōu)化之后,吞吐的峰值和公共云上 RDS 一個(gè)水平,而且在低并發(fā)量下比 RDS 的吞吐更高,在高并發(fā)量下吞吐會(huì)更穩(wěn)。用容器跑 Redis 的用戶經(jīng)常擔(dān)心,延遲會(huì)不會(huì)增長(zhǎng),如果不優(yōu)化肯定有影響,所以我們把容器網(wǎng)絡(luò)換成 eBPF 之后,就跟物理網(wǎng)絡(luò)的延遲一樣低了。
第二個(gè)問題是 K8s 適不適合管理有狀態(tài)的服務(wù)?首先 K8s 原生用來管理有狀態(tài)服務(wù)的控制器,叫 StatefulSet。StatefulSet 確實(shí)不太好用,它有挺多限制,比如不支持 PVC 存儲(chǔ)在線擴(kuò)容的,另外變更 Pod 的時(shí)候,必須要嚴(yán)格按順序去變更,這使得我沒辦法去指定一個(gè) Pod 下線,它也不支持異構(gòu)的各種各樣的 Pod 配置。所以我們?cè)?KubeBlocks 當(dāng)中把 StatefulSet 換成了我們自己寫的 InstanceSet,解決掉了 StatefulSet 的各種問題。
另一方面,很多人誤以為 在 K8s 里面必須要依賴 Pod 的遷移以及 PVC 跨機(jī)重新掛載這些 K8s 原生的機(jī)制去解決高可用、高可靠的問題,而在線下環(huán)境往往沒有分布式存儲(chǔ),如果 Node 掛了,PVC 沒辦法遷移,會(huì)導(dǎo)致在線下部署的時(shí)候數(shù)據(jù)庫(kù)的可用性、可靠性受損。所以我們?cè)?KubeBlocks 里面的做法是不依賴于 K8s 的檢測(cè)和重調(diào)度,而是使用數(shù)據(jù)庫(kù)本身的高可用和多副本技術(shù)去解決一個(gè)節(jié)點(diǎn)掛掉之后服務(wù)怎么恢復(fù)的問題,把數(shù)據(jù)庫(kù)的穩(wěn)定性和 K8s 的穩(wěn)定性解耦開。
我們接觸到了很多的企業(yè),發(fā)現(xiàn)在 K8s 上去構(gòu)建 dbPaaS 是業(yè)界正在進(jìn)行的趨勢(shì)。公共云廠商,如阿里云的 RDS 全線產(chǎn)品都是跑在 K8s 上的,騰訊云的 TDSQL 是跑在 K8s 上的,移動(dòng)云電子云的 RDS 跑在 K8s 上…… 海外的數(shù)據(jù)庫(kù)的初創(chuàng)公司,像 TiDB,Cockroach、Neon、PlanteScale 也都是把自己的數(shù)據(jù)庫(kù)的 dBPaaS 架在 K8s 上。
總之,在 K8s 上建數(shù)據(jù)庫(kù)已經(jīng)成為趨勢(shì)。越來越多的企業(yè)選擇將自己的數(shù)據(jù)庫(kù)部署在 K8s 之上, 這種方式可以充分發(fā)揮容器技術(shù)的優(yōu)勢(shì), 提高數(shù)據(jù)庫(kù)的敏捷性、可靠性和可運(yùn)維性。這種趨勢(shì)在未來幾年內(nèi)有望進(jìn)一步擴(kuò)大和深化。
往期推薦
點(diǎn)亮,服務(wù)器三年不宕機(jī)
