Categories
程式開發

MySQL雲原生方案在攜程開發測試場景中的實踐


一、背景與使用場景

隨著Kubernetes平台在容器雲計算領域的一統天下,雲原生 (Cloud Native) 一詞也被提的越來越頻繁。各類應用紛紛走上了容器化、雲原生化的道路,無狀態服務應用在Kubernetes平台上的運行,已經得到了大規模生產級別的實踐認可。

相比之下,有狀態應用就沒有那麼順利了,特別是那些十分重要卻又”歷史悠久”、不是按照分佈式架構理念設計的有狀態服務,尤其困難。 MySQL就是其中的代表,為此我們做了諸多嘗試,從一開始的MySQL單實例容器化使用本地存儲,到計算存儲分離的方案,走了一些彎路。最終在開發測試場景下找了一個合適的切入點,實現了一套計算和存儲分離,以Kubernetes Operator為核心,以CEPH RBD為後端存儲,以數據庫版本化管理為特性的可行方案。

我們典型的使用場景是這樣的:測試人員需要構造一個生產環境批量訂單數據異常的測試場景, 他使用安全工具從生產環境拉取大量脫敏後的數據寫入測試數據庫,但只運行一次測試用例, 數據庫就”髒了”。特別是每次上新功能還要回歸測試一次這種場景,又要重複耗時在構造新數據庫,真的是“構造2小時,運行5分鐘”。

而有了這一套完整的MySQL實例服務後,可以快速啟動任意版本的數據庫實例,前面所述的痛點就徹底消失了。同時有了MySQL實例服務,對CPU 內存資源的使用也可以節省一大筆,畢竟大量的測試數據庫都只要以快照的形式存儲在集群中即可,實際使用時可以在一兩分鐘內快速啟動。

MySQL雲原生方案在攜程開發測試場景中的實踐 1

二、可行性方案分析和性能評估

首先要解決的是計算和存儲分離的問題,如果使用容器宿主機本地磁盤存儲的話,MySQL實例必須和宿主機綁定,這就喪失了資源的靈活性,而且使用本地存儲, 對於磁盤容量的規劃會是個不小的問題。

我們團隊早在2015就開始使用CEPH存儲服務,主要是對象存儲和塊存儲,運維經驗和集群穩定性方面相對有保證。結合這一實際情況,我們選擇使用了CEPH塊存儲服務作為MySQL容器實例的存儲。

另一個考量則是受益於Kubernetes這個強大的平台基座,社區已經定義好了容器存儲接口 (CSI),且實現了CSI driver for CEPH (https://github.com/ceph/ceph-csi),其中RBD 部分早已GA,還有提供了snapshot,resize等功能,完全滿足我們的使用場景。

為了驗證MySQL實例後端掛載CEPH塊存儲服務能否滿足開發測試環境的數據庫基本使用需求,我們基於已有的硬件情況, 做了兩個場景的性能壓測。主要是對比使用本地SAS磁盤存儲的MySQL實例和使用CEPHRBD的MySQL實例,在性能方面是否有明顯差異。其次則是測試MySQL實例後端掛載CEPH RDB存儲的性能上限。

基本硬件信息如下 :

使用本地磁盤的容器宿主機 CEPH 集群所用物理機
CPU 2Socket / 32Core / 64Thread Intel® Xeon® CPU E5-2650 v3 @ 2。30GHz 2Socket / 32Core / 64Thread Intel® Xeon® Gold 6130 CPU @ 2。10GHz
Memory 188GB 256GB
Disk 2*300G,10K(1)
8*900G,10K(10)
2*240G,SSD(10)
12*8T,7。2K(JBOD)

構造了兩個測試場景,使用sysbench執行壓測:

sysbench參數如下:

參數名 參數值 備註
oltp-tables-count 64 測試表的個數64張
oltp-table-size 1000000 單表數據量100W
num-threads [8,16,32,64,128,256] 測試線程數
times of test 3 每個線程下的測試次數
warmup time 120 預熱時間,避免冷數據對測試結果的影響
max-time 120 每次壓測耗時120s,重複3次

測試場景A:分別壓測MySQL docker with CEPH RBD 和MySQL docker with local disk,並發數threads從低到高,8→256,對比QPS。

測試場景B:同時壓測五個MySQL docker with CEPH RBD,保持並發數恆定在256,觀察CEPH集群IOPS和最終MySQL QPS。

MySQL雲原生方案在攜程開發測試場景中的實踐 2

測試場景A結果:

OLTP模式壓測MySQL,對於磁盤主要是隨機讀寫操作,CEPH RBD使用了SSD作為緩存盤,隨機寫速度約110MB/s,而本地機械磁盤隨機寫速度只有48.6MB/s,所以最終性能指標QPS ,使用了CEPH RBD的容器實例反而更好。

測試場景B結果:

壓測CEPH RBD集群的磁盤IO上限,約算測試環境的集群能提供的QPS上限為80K。

結論是在開發測試環境使用CEPH RBD為後端存儲的MySQL實例服務,不會比使用本地磁盤更差,可以滿足應用功能測試的性能需求。

三、MySQL容器化實例方案及實現細節

介紹一下這套方案的簡單架構設計和基本工作原理,如下圖:

MySQL雲原生方案在攜程開發測試場景中的實踐 3

所有相關服務都部署在Kubernetes集群上,這裡只重點描述我們開發的MySQL-Operator和自定義資源CRD。關於CSI driver 以及provisioner,attacher, snapshotter等組件都是使用原生官方鏡像,在這裡不做詳細表述,可以參考文檔(https://kubernetes-csi.github.io/docs/)。

MySQL-Operator作為自定義的控制器,管理兩種自定義資源(CRD),通過Kube-api為上層的PAAS平台和CI等系統提供MySQL實例服務。兩個CRD分別是MySQLInstance和DatabaseSnapshot。其中MySQLInstance是基於StatefulSet的一層封裝,添加了一些metadata,MySQL-Operator只需要根據MySQLInstance的聲明來創建對應的StatefulSet和PVC即可, 所以MySQLInstance暴露出來的spec並不多,大致如下:

MySQL雲原生方案在攜程開發測試場景中的實踐 4

根據spec.init的類型,MySQLInstance既可以是基於生產數據庫Schema生成的空數據庫實例,也可以是基於已有的DatabaseSnapshot生成的帶有基準數據的實例。

在創建的過程中,MySQL-Operator會為這個MySQLInstance申請域名,同步賬戶密碼以及Schema等。一個MySQLInstance的整個生命週期在有限的七個狀態之間跳轉。需要特別提一下Paused狀態,當基於該實例的DatabaseSnapshot創建時,MySQLInstance會進入Paused狀態。狀態機如下:

MySQL雲原生方案在攜程開發測試場景中的實踐 5

另一個CRD,DatabaseSnapshot則是基於VolumeSnapshot的封裝,其中VolumeSnapshot是Kubernetes官方定義的持久卷快照聲明(https://kubernetes.io/zh/docs/concepts/storage/volume-snapshots/)。 MySQL-Operator根據它的聲明來關聯MySQLInstance和PVC即可。

MySQL雲原生方案在攜程開發測試場景中的實踐 6

由於CEPH RBD 的讀寫獨占模式 RWO(read write once), 我們為DatabaseSnapshot定義了兩個常態InUse和Ready。簡單來講就是一個數據庫快照同一時間只允許一個數據庫實例使用,並且DatabaseSnapshot在創建過程中需要暫停對應的MySQLInstance,狀態機如下:

MySQL雲原生方案在攜程開發測試場景中的實踐 7

四、小結與展望

在有了MySQLIntance服務之後,數據庫的版本管理變得和代碼版本管理一樣靈活。特別是重複構造測試數據的場景,節省了大量的時間和管理成本。另外用戶也不再需要長期佔用計算資源,僅在有使用需求時即可快速創建 MySQLInstance,有效提高了整體容器宿主機資源的使用率。除此之外,上層CI/CD平台服務也可以通過Kube API調用的方式來管理這兩種CRD,進一步提升測試自動化程度。

一般來說,應用雲原生化完成後最重要的是獲得兩個能力:彈性和分佈式,目前我們的這套方案落地於Kubernetes平台,釋放出了一部分平台計算和存儲的彈性,讓用戶對於數據庫實例有了更多的選擇和靈活管理的能力。

何謂雲原生(Cloud Native), 字面上早已經有了明確的定義(https://github.com/cncf/toc/blob/master/DEFINITION.md),但是在工程實踐中,基於Kubernetes這個巨大的平台,仍然有大量的寶藏等著我們去持續探索挖掘。

作者介紹

Alex,專注於雲計算領域數年,目前主要從事容器雲平台的建設,推進各類基礎設施服務的雲原生化。

小石川,目前主要從事容器雲平台監控系統建設,對分佈式、性能以及優化感興趣。

本文轉載自公眾號攜程技術(ID:ctriptech)。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MjM5MDI3MjA5MQ==&mid=2697269592&idx=2&sn=2ebc6e51909422ae573fafcf943500c7&chksm=8376ee6cb401677a803bd57cb8e3859ee0a635ce965449d7cf3b81b6a2b7cb1f14b973580da2&scene=27#wechat_redirect