黃東旭DTCC2017演講實(shí)錄:When TiDB Meets Kubernetes
本文是我司 CTO 黃東旭同學(xué)在 DTCC2017 上的《When TiDB Meets Kubernetes》演講實(shí)錄,主要分享了關(guān)于 TiDB 與 Kubernetes 整合的一些工作。文章較長(zhǎng),且干貨滿(mǎn)滿(mǎn)。
以下為演講實(shí)錄:
今天給大家?guī)?lái)的分享是關(guān)于 TiDB 與 Kubernetes 整合的一些工作。在講之前,想了解一下,在場(chǎng)的各位有聽(tīng)說(shuō)過(guò) Kubernetes 的同學(xué)舉個(gè)手;聽(tīng)說(shuō)過(guò) TiDB 的舉個(gè)手,非常好。因?yàn)槲乙彩?DTCC 的??土?,前幾年來(lái)講的時(shí)候基本上沒(méi)有人聽(tīng)說(shuō)過(guò) TiDB ,隨著這個(gè)項(xiàng)目越來(lái)越成熟,很欣慰,有一些社區(qū)的小伙伴已經(jīng)用起來(lái)了。
我先簡(jiǎn)單介紹一下我自己。我是 PingCAP 的聯(lián)合創(chuàng)始人兼 CTO ,也是 TiDB 項(xiàng)目的碼農(nóng) ,之前一直也是在做 Infrastructure 和分布式系統(tǒng)相關(guān)的一些工作。同時(shí)也是特別喜歡開(kāi)源,基本上做的所有東西都是開(kāi)源,包括像 Codis 、TiDB 、 TiKV 這些項(xiàng)目。比較喜歡的編程語(yǔ)言有 GO 、Rust 、Python。
對(duì)于今天的話題,如果說(shuō)在 40 分鐘之內(nèi)要去完整的介紹怎么做一個(gè)數(shù)據(jù)庫(kù)或者說(shuō)怎么去做一個(gè)集成調(diào)度的系統(tǒng),我覺(jué)得是不太可能的。
所以今天這個(gè) Talk 我主要會(huì)分享 TiDB 作為一個(gè)分布式關(guān)系型數(shù)據(jù)庫(kù)與云整合的經(jīng)驗(yàn),以及我們遇到的一些問(wèn)題,來(lái)幫大家在遇到相似的問(wèn)題時(shí)提供一個(gè)解決思路。大家其實(shí)在存儲(chǔ)系統(tǒng)上可以把 TiDB 換成任何東西,然后對(duì)于在 Kubernetes 上的融合,我覺(jué)得都會(huì)有一些啟發(fā)的意義。
首先想強(qiáng)調(diào)的是,Cloud 才是未來(lái)?,F(xiàn)場(chǎng)做一個(gè)小調(diào)研:有在線上生產(chǎn)環(huán)境中,正使用 Kubernetes 或者 Mesos 這樣的容器化管理方案的同學(xué)嗎?好,一個(gè)兩個(gè)三個(gè)。
我相信,如果在三到五年以后,再去問(wèn)這個(gè)問(wèn)題,應(yīng)該是至少一半的同學(xué)會(huì)舉手。因?yàn)槠鋵?shí)在可見(jiàn)的未來(lái),數(shù)據(jù)量是一直在膨脹,業(yè)務(wù)會(huì)越來(lái)越復(fù)雜。包括現(xiàn)在很多微服務(wù)的這種思想,當(dāng)你的業(yè)務(wù)比較大的時(shí)候,會(huì)把整個(gè)服務(wù)拆成非常細(xì)的模塊,然后在眾多的模塊的拆分之下,怎么去高效的運(yùn)維你的分布式集群,其實(shí)靠 SRE 或者運(yùn)維人員手動(dòng)去管理各個(gè)微服務(wù)或者說(shuō)各個(gè)的系統(tǒng),其實(shí)是不太現(xiàn)實(shí)的。
但是大家也都知道,對(duì)于這種無(wú)狀態(tài)的業(yè)務(wù),比如像 Application 應(yīng)用層,其實(shí)它并不會(huì)真正的存儲(chǔ)數(shù)據(jù),狀態(tài)一般都持久化到數(shù)據(jù)庫(kù)或者緩存中,所以它基本是無(wú)狀態(tài)的。所以其實(shí)一直以來(lái)大家在使用容器化遇到的***個(gè)問(wèn)題就是,有狀態(tài)的服務(wù),特別是數(shù)據(jù)庫(kù)或者分布式存儲(chǔ)系統(tǒng),怎么去運(yùn)維。比如說(shuō)我在 Docker 里面寫(xiě)的數(shù)據(jù),這個(gè)容器銷(xiāo)毀它直接就掛了,它其實(shí)是很難去做這種數(shù)據(jù)層面上的東西。
然后另外一方面就是數(shù)據(jù)庫(kù)的運(yùn)維,不管是放在云上做還是 DBA 自己在物理機(jī)上做,一樣的痛苦,所以怎樣去設(shè)計(jì)一個(gè)面向云的環(huán)境下、或者說(shuō)在分布式系統(tǒng)上去做數(shù)據(jù)庫(kù)。其實(shí)這也是在做 TiDB 的過(guò)程中我一直在想的。TiDB 這個(gè)項(xiàng)目一開(kāi)始的設(shè)計(jì)就是:它一定會(huì)放在云上去運(yùn)轉(zhuǎn)。
上圖是 Amazon 在它的云上選擇創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)實(shí)例的一個(gè)界面,大家不用看具體的字是什么,只是給大家感受下:就是說(shuō)我作為一個(gè)業(yè)務(wù)的開(kāi)發(fā),我要去存儲(chǔ)一個(gè)數(shù)據(jù),啟用一個(gè) PG 或者 MySQL 的數(shù)據(jù)庫(kù),我還要去關(guān)心這么多個(gè)選項(xiàng),或者說(shuō)我一定要去關(guān)心我的這個(gè)物理機(jī)到底是什么樣的情況:磁盤(pán)有多大,什么機(jī)型,各式各樣的配置等。因?yàn)楫吘共皇撬腥硕际菍?zhuān)業(yè)的 DBA ,也不是所有人都是操作系統(tǒng)的專(zhuān)家,當(dāng)時(shí)看到這個(gè)頁(yè)面的時(shí)候,基本上業(yè)務(wù)開(kāi)發(fā)可能是一臉懵逼的狀態(tài)。
現(xiàn)在所有人都跟你說(shuō),我的系統(tǒng)是一個(gè)分布式系統(tǒng),在廣告里寫(xiě)的非常漂亮。現(xiàn)在哪一個(gè)數(shù)據(jù)庫(kù)說(shuō)自己不是分布式的,那基本上只能是落后于時(shí)代。但是,大家有沒(méi)有想過(guò),現(xiàn)在所有的這些分布式系統(tǒng)、分布式數(shù)據(jù)庫(kù),運(yùn)維起來(lái)都是非常痛苦,沒(méi)有辦法去很好的把它用好。
以 Hadoop 為例,現(xiàn)在 setup 一個(gè) Hadoop 的集群竟然能成為一個(gè)生意,這個(gè)生意還讓兩個(gè)創(chuàng)業(yè)公司都上市了,一個(gè)是 Cloudera,一個(gè)是 Hortonworks。其實(shí)嚴(yán)格來(lái)說(shuō),他們只是做 Hadoop 運(yùn)維的創(chuàng)業(yè)公司。然后還有無(wú)數(shù)的公司在做 Spark 的維護(hù)、Spark 的管理。各種各樣的數(shù)據(jù)庫(kù)運(yùn)維公司,靠這個(gè)都過(guò)的非常好。
這個(gè)其實(shí)在我看來(lái)是非常不正常的,因?yàn)榇蠹蚁耄绻闳ミ\(yùn)維一兩臺(tái)機(jī)器那沒(méi)有問(wèn)題,我寫(xiě)一個(gè)腳本,輕輕松松的就可以搞定;然后三五十臺(tái)機(jī)器,也還行,招一個(gè) OPs 或者說(shuō)招一個(gè) DBA ,還是可以人工的管理。
但是如果是在 100 臺(tái)、1000 臺(tái)甚至 10000 臺(tái)規(guī)模之上,機(jī)器的故障會(huì)是每天每夜無(wú)時(shí)無(wú)刻都發(fā)生的,網(wǎng)絡(luò)的抖動(dòng),磁盤(pán) IO 的異常,一直都在發(fā)生,靠人是沒(méi)有辦法做的??偟膩?lái)說(shuō)就是,當(dāng)你去運(yùn)維一個(gè) single node 的系統(tǒng)時(shí),基本上沒(méi)有什么難度;但是如果要去運(yùn)維一個(gè)特別大的 P2P 的 distributed system,尤其是節(jié)點(diǎn)數(shù)特別多的時(shí)候,你的狀態(tài)和維護(hù)的成本就變得非常高。
之前我做過(guò)一個(gè)項(xiàng)目叫 Codis ,可能有很多同學(xué)聽(tīng)說(shuō)過(guò),也可能很多同學(xué)已經(jīng)用在生產(chǎn)環(huán)境之中。還有另外一個(gè)不是我做的項(xiàng)目,就是官方的 Redis Cluster。當(dāng)時(shí)很多社區(qū)里面的 Redis Cluster 的粉絲一直噴我,說(shuō) Codis 的配置怎么這么復(fù)雜,一點(diǎn)都不好用,組件怎么這么多?,F(xiàn)在這個(gè)事情又在重演。
很多系統(tǒng)做成了 P2P 的模型了以后,組件很少部署很方便,但是真正在去運(yùn)維它的時(shí)候,比如說(shuō)要去做一個(gè)滾動(dòng)升級(jí)或者我想清楚的知道整個(gè)集群的數(shù)據(jù)分布和各個(gè)組件的狀態(tài),又或者說(shuō)是我的分布式邏輯出了個(gè)bug,但是我的存儲(chǔ)層沒(méi)事,需要做個(gè)熱更新這個(gè)時(shí)候,p2p 系統(tǒng)的運(yùn)維復(fù)雜度就凸顯了。Codis 它其實(shí)有一個(gè) Proxy,一個(gè)存儲(chǔ)層,這兩層在邏輯上其實(shí)是分離的;但是 Redis Cluster ,每一個(gè)節(jié)點(diǎn)既是它的分布式調(diào)度模塊,同時(shí)又是它的數(shù)據(jù)存儲(chǔ)模塊,這時(shí)候整個(gè)系統(tǒng)架構(gòu)是混在一起的,對(duì)于運(yùn)維的同學(xué)來(lái)說(shuō)這就是一個(gè)惡夢(mèng)。
如果我想清楚的知道我的數(shù)據(jù)到底是在哪幾臺(tái)機(jī)器上,比如說(shuō)這塊數(shù)據(jù)特別熱我想把它挪走,這時(shí)候像在 Redis Cluster 這種純 P2P 的系統(tǒng)里面是很難得到它的當(dāng)前狀態(tài)。所以這也是影響了我后來(lái)一系列的系統(tǒng)設(shè)計(jì)的想法,所以 operation 是一個(gè)非常困難的事情,在一個(gè)特別大的分布式系統(tǒng)里,是一個(gè)非常困難的事情。
因?yàn)槟愕姆?wù)和組件特別多,不同的組件,不同的模塊,然后再加上一個(gè)分布式系統(tǒng)里邊特別不穩(wěn)定的網(wǎng)絡(luò)狀態(tài),使得各種各樣的異常情況,人是沒(méi)有辦法去掌控的。
還好,Google 是一個(gè)非常偉大的公司,像 TiDB 整個(gè)模型大家也知道是參考了Google Spanner/F1。Kubernetes 背后的系統(tǒng)的前身就是 Google 的 Borg。
Borg 其實(shí)是 Google 內(nèi)部一直在用著的大規(guī)模的集群調(diào)度器。Borg 這個(gè)單詞就是星際迷航里面的一個(gè)角色,相當(dāng)于它作為整個(gè)集群的一個(gè)大腦來(lái)去控制集群的業(yè)務(wù)的分布跟數(shù)據(jù)的均衡,所以 Google 給我們帶來(lái)了 Kubernetes 這個(gè)項(xiàng)目。
Kubernetes 主要的工作就是一個(gè)面向 Container 的集群管理的服務(wù)。它同時(shí)會(huì)去做服務(wù)編排,Auto deployment、 Auto scaling、Auto healing ,你的整個(gè)集群的這些服務(wù)的生命周期的管理,然后故障的轉(zhuǎn)移、擴(kuò)容...你可以認(rèn)為它是一個(gè)集群的操作系統(tǒng)。大家可能認(rèn)為操作系統(tǒng)就是單機(jī)上的一個(gè)概念,但是如果放到一個(gè)大規(guī)模的分布式系統(tǒng)里面,你有無(wú)數(shù)的 CPU 資源,無(wú)數(shù)的內(nèi)存,無(wú)數(shù)的磁盤(pán)資源,怎么高效的去把你的服務(wù)在這些海量的資源上進(jìn)行合理的分配,這個(gè)就是 Kubernetes 干的事情。
TiDB 大家也都非常熟悉了,我簡(jiǎn)單介紹一下吧。
我們做 TiDB 的目標(biāo)就是,希望構(gòu)建一個(gè)完全彈性的,用戶(hù)不需要去知道數(shù)據(jù)的分布信息,也不需要去做手工的數(shù)據(jù)分片,可以把它當(dāng)做一個(gè)單機(jī)的數(shù)據(jù)庫(kù)、 MySQL 的數(shù)據(jù)庫(kù)在用,但是它背后是一個(gè)高度彈性和智能的分布式的數(shù)據(jù)庫(kù)。對(duì)業(yè)務(wù)層你不需要再去想分庫(kù)分表,也不需要再去想熱點(diǎn)的 balance 這種事情。它支持***的 OLTP 的功能,可以支持跨行事務(wù),像 MySQL 一樣:我開(kāi)始一個(gè) transaction,然后寫(xiě)寫(xiě)寫(xiě),*** commit,全成功或者全失敗,沒(méi)有第三種可能 。支持事務(wù)的前提之下還支持 80% 的 OLAP 。
所以 TiDB 是非常適合去做這種一邊有實(shí)時(shí)寫(xiě)入,一邊有復(fù)雜 Join 和實(shí)時(shí)分析的場(chǎng)景,它的 SQL 優(yōu)化器其實(shí)也有從 Spark SQL 里面學(xué)到了很多東西。
當(dāng)然對(duì)外的接口是完整的 MySQL 的接口,你可以直接用 MySQL 的客戶(hù)端就連上了。另外,背后它支持高可用。因?yàn)榈讓拥膹?fù)制協(xié)議并不是通過(guò)像這種主從模型去做數(shù)據(jù)冗余的,而是用 Raft,Raft 跟 multi-paxos 是比較接近的,都是基于選舉的算法。
在遇到 MySQL 的擴(kuò)展性問(wèn)題的時(shí)候,大家過(guò)去只能一臉懵逼,然后反回來(lái)去拆庫(kù)拆表,或者去用 MyCat 或者依托 MySQL 的中間件去做 sharding 。其實(shí)這對(duì)于業(yè)務(wù)層來(lái)說(shuō),侵入性非常大,所以 TiDB 的初衷就是解決這個(gè)問(wèn)題,但是它沒(méi)有用任何一行 MySQL 的代碼。
TiDB 大概是這樣一個(gè)架構(gòu):
TiDB 其實(shí)也是由很多的組件組成,它并不是一個(gè)純粹的 P2P 系統(tǒng),如果看這個(gè)架構(gòu)其實(shí)非常像 Codis 。
今天的主題是說(shuō)我們?cè)趺丛?Kubernetes 上去做 cluster 的 setup、rolling update,怎么去解決 Kubernetes 對(duì)于本地磁盤(pán)存儲(chǔ)的綁定問(wèn)題。
所以面臨著一個(gè)與大家之前在 Kubernetes 上去部署帶狀態(tài)的服務(wù)非常接近的問(wèn)題。因?yàn)?TiDB 本身是一個(gè)帶狀態(tài)的數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)沒(méi)有狀態(tài)那不可能。Kubernetes 的調(diào)度其實(shí)是對(duì)這種 stateless applications 非常友好的,但是如果你是一個(gè)帶狀態(tài)的,比如像 MySQL、PG、TiDB,或者 Etcd、Zookeeper 等等,怎么去做?真正的困難并不是 Kubernetes 做不了,而是每一個(gè)不同的系統(tǒng)都有自己的數(shù)據(jù)分布模型,同時(shí)每一個(gè)不同的系統(tǒng)它的運(yùn)維方式也不太一樣。所以作為 Kubernetes 的平臺(tái)來(lái)說(shuō),沒(méi)有辦法去針對(duì)每一個(gè)不同的存儲(chǔ)系統(tǒng)去設(shè)計(jì)一套自己的調(diào)度策略。這是 Kubernetes 沒(méi)有辦法去做的一個(gè)事情。
舉個(gè)例子,比如說(shuō)你想去運(yùn)維好一個(gè) Redis Cluster ,那你必須得了解 Redis Cluster 一些原理,還有必須得去知道它怎么運(yùn)維;如果你想要去運(yùn)維 Codis ,你必須得知道 Codis 的一些原理方法才能把它運(yùn)維好。但這些領(lǐng)域知識(shí)怎么去告訴 Kubernetes 說(shuō)你幫我按照這個(gè)方法來(lái)去運(yùn)維這個(gè)系統(tǒng)?
這時(shí)候有一個(gè)公司,叫做 CoreOS ,相信大家可能也都熟悉,就是 Etcd 背后的那個(gè)公司,也是我們 PingCAP 的好伙伴。CoreOS 也是社區(qū)里面***的 Kubernetes 的運(yùn)營(yíng)的公司,他們引入了一個(gè)新的 Kubernetes 的組件,叫做 Operator 。Operator的意義在于它其實(shí)是相當(dāng)于使用了 Kubernetes 的 TPR(third party resources)的 API,去把你的系統(tǒng)運(yùn)維的一些領(lǐng)域知識(shí),封裝到 Operator 里面,然后把 Operator 這個(gè)模塊注入到 Kubernetes 上面,整個(gè)這些集群是通過(guò) Operator 這個(gè)模塊來(lái)去做調(diào)度。
CoreOS 官方還提供了一個(gè) Etcd 的 Operator 的實(shí)現(xiàn)。其實(shí)這思路也很簡(jiǎn)單,就是說(shuō)把這個(gè)集群的創(chuàng)建滾動(dòng)更新,然后各種運(yùn)維的一些領(lǐng)域知識(shí)放到這個(gè) Operator 里面,然后在 Operator 里面去調(diào)用 Kubernetes 原生的 API,來(lái)做集群的管理,相當(dāng)于是 Kubernetes 的一個(gè) Hook 。
一般來(lái)說(shuō)一個(gè) Operator 它其實(shí)有這樣一些對(duì)外暴露的接口或者是能力。它做的事情的就是:比如我想要讓 Kubernetes 去建立一個(gè) TiDB 的集群,比如說(shuō) deployment;比如我加入新的物理節(jié)點(diǎn)以后,我要想對(duì)現(xiàn)有的這個(gè)集群做擴(kuò)容,然后 rebalance;比如說(shuō)我的集群的 TiDB 本身的這些 binary需要升級(jí),我要去做業(yè)務(wù)透明的滾動(dòng)更新,比如說(shuō)我有 100 個(gè)節(jié)點(diǎn),要在上面去做升級(jí),不可能手動(dòng)去做,這個(gè)其實(shí)都是封裝在我們的 Operator 里面,然后包括自動(dòng)化的 backup 跟 restore 這些功能。
本質(zhì)上來(lái)說(shuō)你可以認(rèn)為 Operator 是一個(gè) Kubernetes 的批處理方案。我剛才也簡(jiǎn)單提到了一下,Kubernetes 可以作為一個(gè)集群的操作系統(tǒng),但是這個(gè)操作系統(tǒng)總應(yīng)該能讓運(yùn)維去寫(xiě)腳本的,這個(gè)腳本就是 Operator 機(jī)制。
其實(shí)它的原理很簡(jiǎn)單,就是它注入到 Kubernetes 里面,會(huì)實(shí)時(shí)不停的去觀察集群的狀態(tài),去 Hook Kubernetes 的一些集群的狀態(tài),一些 API,然后得到整個(gè)集群的狀態(tài)。把一些分析的東西放在 Operator 里面,它可能會(huì)有一些地方被觸發(fā),比如說(shuō)我該擴(kuò)容了或者我該去做 Failover ,然后去反饋。
然后 TiDB 的 Operator 目前來(lái)說(shuō)有這么幾個(gè)功能:創(chuàng)建集群、滾動(dòng)更新、Scale out, Failover、Backup/Restore。
因?yàn)槠鋵?shí)今天的這個(gè)話題是說(shuō)怎么去跟云做結(jié)合。我們現(xiàn)在在跟一些公有云的提供方在做合作。但是不可能說(shuō)每一個(gè)公有云都自己去接入它的資源管理的 API,因?yàn)槊總€(gè)公有云可能都用的是不一樣的 API database,所以我們相當(dāng)于做的一個(gè)方案就是說(shuō),不管你是公有云也好還是私有云也好,你給我一堆物理的機(jī)器,然后在這一堆物理的機(jī)器上面去部署 Kubernetes ,在這個(gè) Kubernetes 上面,我相當(dāng)于把我的 TiDB Operator 給放進(jìn)去,當(dāng)某個(gè)公有云客戶(hù)要它去創(chuàng)建一個(gè)集群的時(shí)候,會(huì)通知 Operator 去創(chuàng)建,比如說(shuō)劃出一些機(jī)器,去做物理隔離。
這在私有云里邊也是一個(gè)比較常見(jiàn)的場(chǎng)景了。用戶(hù)他其實(shí)想要去做這種業(yè)務(wù)之間的租戶(hù)隔離,TiDB Operator 是做一個(gè)比較簡(jiǎn)單的物理隔離。
但是做這個(gè) Operator 最難的一個(gè)部分其實(shí)剛才也簡(jiǎn)單講了一下,就是存儲(chǔ)的問(wèn)題。如果大家關(guān)注 Kubernetes 社區(qū)的話,一般都會(huì)注意到 persistend local storage 的這個(gè)方案一直在社區(qū)里邊扯皮和吵架?,F(xiàn)在大家認(rèn)為 Kubernetes 本地的磁盤(pán)是沒(méi)法用的,或者說(shuō)沒(méi)有辦法直接當(dāng)做一個(gè)資源來(lái)使用的。
上圖是放在 Kubernetes 的 issues 里面的一個(gè)問(wèn)題,就是 persistent local storage ,這個(gè)看上去非常不可思議,這么簡(jiǎn)單的功能為什么一直到現(xiàn)在沒(méi)有支持。
我個(gè)人感覺(jué) Google 之所以遲遲不去做這個(gè)功能,它背后有一個(gè)原因可能是在 Google 內(nèi)部,它的網(wǎng)絡(luò)存儲(chǔ)是非常強(qiáng)的,它有自己非常好的網(wǎng)絡(luò)設(shè)備。你在同一個(gè)數(shù)據(jù)中心里,去換一塊網(wǎng)絡(luò)盤(pán),它的這個(gè) latency 基本上很多業(yè)務(wù)可以接受的,所以這樣的話,持久化存儲(chǔ)的問(wèn)題基本上是靠網(wǎng)絡(luò)的磁盤(pán)來(lái)解決。
想像你跑一個(gè) MySQL 的業(yè)務(wù),MySQL 的業(yè)務(wù)本身它寫(xiě)入的磁盤(pán)并不是你的物理機(jī)的本地盤(pán),而是一塊網(wǎng)絡(luò)盤(pán),這個(gè)網(wǎng)絡(luò)盤(pán)我能給你保證它的 IOPS 跟 latency 都是非常好的狀態(tài),這個(gè)時(shí)候你的業(yè)務(wù)掛掉了,我再重新啟一個(gè)容器把這個(gè)網(wǎng)絡(luò)盤(pán)再掛到那個(gè) pod 的后邊,這時(shí)候你的業(yè)務(wù)是幾乎無(wú)感知的。這也是 Google 比較推崇的使用存儲(chǔ)的一個(gè)模式,所以這就是 Kubernetes 背后的那個(gè) persistent volumes 的這個(gè)方案。
它現(xiàn)在是有這個(gè)方案的,但是對(duì)于像我們這樣的分布式數(shù)據(jù)庫(kù)或者說(shuō)對(duì)這種本地磁盤(pán)有特別強(qiáng)要求的( TiDB 底層的存儲(chǔ)引擎對(duì)單機(jī)的 SSD 做了非常多的優(yōu)化),并沒(méi)有辦法去容忍我底下寫(xiě)入的一個(gè)磁盤(pán)是網(wǎng)絡(luò)盤(pán)。因?yàn)楸旧肀热缯f(shuō) TiDB 這一層,已經(jīng)做了三個(gè)副本,甚至五個(gè)副本的復(fù)制,但是在底下網(wǎng)絡(luò)盤(pán)又要去做這個(gè)復(fù)制其實(shí)是沒(méi)有太多必要的,所以 Google 一直遲遲沒(méi)有推 Local Storage Resource。如果在 Google Cloud 上它能更好的去賣(mài)它的云盤(pán),或者說(shuō)對(duì)于這些公有云廠商來(lái)說(shuō),這是更友好的。
當(dāng)然它也不是沒(méi)做,它是要在 1.9 里面才會(huì)去做這個(gè)支持,但以 Kubernetes社區(qū)的迭代速度,我估計(jì) 1.9 可能還要等個(gè)兩三年,所以這是完全不能忍的一個(gè)狀態(tài)。那既然我們又需要這個(gè)本地磁盤(pán)的支持,但是官方又沒(méi)有,那該怎么辦呢?這時(shí)我們就發(fā)揮主觀能動(dòng)性了。
我們給 Kubernetes 做了一個(gè) patch。這個(gè) patch 也是通過(guò) Kubernetes resource 的方案去做的一個(gè)本地磁盤(pán)資源的管理模塊,這個(gè)怎么做的呢?也比較簡(jiǎn)單。這部分內(nèi)容就比較干了,需要大家對(duì) Kubernetes 整個(gè)架構(gòu)有一點(diǎn)點(diǎn)了解。
***步,先會(huì)去創(chuàng)建一個(gè) Kubernetes 的 Configuration map,我們稱(chēng)之為 TiDB 的 storage ,就是針對(duì) storage 的物理資源寫(xiě)在配置的文件里邊。比如說(shuō)機(jī)器的 IP,它的不同盤(pán)對(duì)應(yīng)的文件夾在哪兒,相當(dāng)于是一個(gè)配置階段的東西。
第二步,創(chuàng)建一個(gè)利用 Kubernetes 的 Third Party Resources(TPR) 的 API,去創(chuàng)建一個(gè)叫 tidb-volume 的第三方資源,然后這個(gè)資源去剛才 Configuration map 里面去讀它去注冊(cè)的那些物理磁盤(pán)分布的狀態(tài)資源,相當(dāng)于 TPR 會(huì)把那個(gè)配置里面的磁盤(pán)資源 load 出來(lái),變成在 Kubernetes 里的一個(gè)第三方 resource,這個(gè)對(duì)象大概是這樣一個(gè)狀態(tài)。
第三步,我們?cè)谶@邊會(huì)去寫(xiě)一個(gè) controller,我們寫(xiě)這個(gè) controller 是干嘛呢?叫 volume-controller 。比如說(shuō)我們的一個(gè)磁盤(pán)的資源分配給了一個(gè) pod,然后這個(gè) pod 現(xiàn)在在占用著這個(gè)資源,我需要有一個(gè) controller 的模塊來(lái)標(biāo)記這個(gè)資源的使用情況,不能說(shuō)我新的業(yè)務(wù)在起來(lái)的時(shí)候,我把資源分配給了兩個(gè)正在用的業(yè)務(wù),這是不行的。這里的對(duì)應(yīng)關(guān)系其實(shí)是由 volume controller 去維護(hù)的。然后另外一方面它還實(shí)時(shí)的監(jiān)盯著剛才 Configuration map 里面的物理資源,我可以動(dòng)態(tài)的添加物理的磁盤(pán)資源的一些狀態(tài)。
第四步,剛才我們說(shuō)到 opreator 其實(shí)是一個(gè)運(yùn)維的工具,去做創(chuàng)建集群還有滾動(dòng)升級(jí),相當(dāng)于總的入口。在這里面在去創(chuàng)建集群,在啟動(dòng)進(jìn)程的時(shí)候,把剛才我們創(chuàng)建的本地磁盤(pán)資源啟動(dòng)實(shí)例綁定在一起,讓它能夠成功的創(chuàng)建這個(gè)資源。
第五步,就是創(chuàng)建一個(gè) DaemonSet。DaemonSet 在 Kubernetes 里就是在每一個(gè)物理節(jié)點(diǎn)上每一個(gè)長(zhǎng)度的進(jìn)程,這個(gè)進(jìn)程是用來(lái)去維護(hù)磁盤(pán)上資源的使用狀況。比如說(shuō)一個(gè) TiKV 的節(jié)點(diǎn)下線了,這個(gè)物理的磁盤(pán)資源就要被回收?;厥樟艘院竽阋プ鰟h除數(shù)據(jù)、清空數(shù)據(jù)的操作,或者這個(gè)物理機(jī)就宕機(jī)了,你需要有一個(gè)東西來(lái)去通知 controllor 把這個(gè)資源給下線掉,這個(gè)是 DaemonSet 在干的事情。
這一整套加起來(lái)就是相當(dāng)于只通過(guò) Third Party Resources 來(lái)嵌入 Kubernetes,整體來(lái)說(shuō)在旁路卻實(shí)現(xiàn)了一種本地的 local 磁盤(pán)的管理方案。
因?yàn)檫@個(gè)代碼其實(shí)還蠻多的,現(xiàn)在還沒(méi)有辦法直接 push 回 Kubernetes 社區(qū)。雖然現(xiàn)在這還是一個(gè) private 的項(xiàng)目,但是在后續(xù)把代碼整理以后我們還是會(huì)開(kāi)源出來(lái)。所以這其實(shí)也是為大家以后在 Kubernetes 去調(diào)度這種單雙向服務(wù)的方案,提供了一套可行的路,至少我們用這個(gè)還挺爽的。
然后,想稍微展望一下未來(lái)的數(shù)據(jù)庫(kù)應(yīng)該是什么樣的。
在我看來(lái),未來(lái)的數(shù)據(jù)庫(kù)不會(huì)再需要 DBA ,或者說(shuō)未來(lái)你在寫(xiě)業(yè)務(wù)的時(shí)候,并不需要去關(guān)心底下數(shù)據(jù)該去怎么分片,怎么去 sharding,一切都應(yīng)該是在后面的云服務(wù)本身或者基礎(chǔ)設(shè)施去提供的。所有的東西都應(yīng)該是 self-driving,相當(dāng)于自動(dòng)駕駛。就像在未來(lái)大家覺(jué)得自動(dòng)駕駛應(yīng)該是一個(gè)方向,在基礎(chǔ)軟件里我覺(jué)得也是越來(lái)越多的自動(dòng)化導(dǎo)致大家對(duì)運(yùn)維的依賴(lài)變得越來(lái)越輕。但是在很多的極端的情況下,circuit-breaker(斷路器)還是要有的。比如說(shuō)我的業(yè)務(wù)產(chǎn)品現(xiàn)在突然出現(xiàn)了一個(gè)特別熱的熱點(diǎn),我需要業(yè)務(wù)這邊去緊急的做手動(dòng)的數(shù)據(jù)切分、移動(dòng),把負(fù)載手動(dòng)的均衡出來(lái),所以手動(dòng)模式還是仍然要有的。類(lèi)似于你自動(dòng)駕駛的汽車(chē),突然來(lái)一個(gè)人加塞,大家還是非常希望能保證自己的安全,那就必須得有一個(gè)手動(dòng)的模式。
第二點(diǎn)是 database as a service ,前面也說(shuō)到了,serverless 可能會(huì)在 database 里面,有一種新的形態(tài)的數(shù)據(jù)的數(shù)據(jù)庫(kù)。大家如果關(guān)注數(shù)據(jù)庫(kù)領(lǐng)域的話,最近出了一個(gè)新的數(shù)據(jù)庫(kù)叫 FaunaDB 。FaunaDB 非常有意思,它其實(shí)是跟公有云綁定在一起對(duì)外提供服務(wù)的,你看不見(jiàn)它實(shí)際的進(jìn)程和部署,也看不見(jiàn)它物理的進(jìn)程在什么地方,整個(gè)數(shù)據(jù)庫(kù)對(duì)外的展現(xiàn)形式就是你去買(mǎi)我的服務(wù),我給你多少的 QPS。比如說(shuō)你買(mǎi)一萬(wàn)個(gè) QPS,這個(gè)服務(wù)就能保證一萬(wàn)個(gè) QPS,你買(mǎi)十萬(wàn)就是十萬(wàn),按這個(gè)價(jià)格來(lái)去付費(fèi),至于你的容量全都是在背后隱藏著,所有業(yè)務(wù)的開(kāi)發(fā)者實(shí)際上是看不見(jiàn)。
第三點(diǎn)就是 Local storage isn’t necessary。為什么 Google 它一直沒(méi)有在 Kubernetes 里面去做 Local storage,其實(shí)仔細(xì)想一下也是有道理的,就是說(shuō)隨著未來(lái)硬件的發(fā)展,當(dāng)網(wǎng)絡(luò)社會(huì)的速度和分布跟你的磁盤(pán)的存儲(chǔ)差不多的時(shí)候,那它到底是不是網(wǎng)絡(luò)的,已經(jīng)對(duì)業(yè)務(wù)層沒(méi)有什么意義了,所以這可能是一個(gè)未來(lái)的趨勢(shì)。
這條是一個(gè)比較極端的路,就是把整個(gè)磁盤(pán)放到網(wǎng)絡(luò)上,用網(wǎng)絡(luò)盤(pán)。還有另外一條反向的特別極端的路,也是我現(xiàn)在正在嘗試的一個(gè)東西,就是更加去對(duì)硬件做定制。比如說(shuō)我現(xiàn)在嘗試把一些 TiDB 的數(shù)據(jù)庫(kù)的一些邏輯放到 FPGA 上面,或者是放在 SSD 的控制芯片里面,這其實(shí)是更深的定制,在未來(lái)我覺(jué)得兩者可能會(huì)融合。就是說(shuō)我雖然可能是掛了一個(gè)網(wǎng)絡(luò)盤(pán),但是對(duì)于數(shù)據(jù)庫(kù)來(lái)說(shuō)我有了這個(gè)計(jì)算邏輯可能直接的去操作硬件,而不需要去例如通過(guò)標(biāo)準(zhǔn)的 POSIX API 來(lái)轉(zhuǎn)換內(nèi)核走 本地 IO 的接口。
總結(jié)一下,分布式系統(tǒng)的運(yùn)維特別的痛苦,然后 Kubernetes 是一個(gè)未來(lái)集群調(diào)度必然的趨勢(shì),但是在存儲(chǔ)層它現(xiàn)在還沒(méi)有太多的好辦法。目前來(lái)說(shuō)我們?cè)谧龅囊粋€(gè)事情就是 Operator,把整個(gè)存儲(chǔ)層的運(yùn)維的領(lǐng)域知識(shí)放在 Operator 里邊,然后讓 Kubernetes 能去調(diào)度我們的東西。這個(gè)有點(diǎn)像 DCOS 的 batch script。
TiDB-Operator,其實(shí)是把運(yùn)維干的事情,全都通過(guò) Operator 的形式來(lái)封裝在程序里邊,然后自動(dòng)的去運(yùn)維。
Local Storage 的問(wèn)題我們是解決了。雖然 Kubernetes 沒(méi)有辦法去提供這個(gè)能力,但是我們暫時(shí)解決了。
【本文是51CTO專(zhuān)欄機(jī)構(gòu)“PingCAP”的原創(chuàng)文章,轉(zhuǎn)載請(qǐng)聯(lián)系作者本人獲取授權(quán)】