玩轉 Ceph 的正確姿勢

玩轉 Ceph 的正確姿勢
本文先介紹 Ceph, 然後會聊到一些正確使用 Ceph 的姿勢;在集羣規模小的時候,Ceph 怎麼玩都沒問題;但集羣大了(到PB級別),這些準則可是保證集羣健康運行的不二法門;

Ceph 最初的目標是做一個分佈式文件系統,直到現在這個目標也不能算完美實現;目前官網上對它的文件系統還是謹慎推薦的態度(不建議對線上核心業務部署);

業界使用 Ceph ,大多是用它的對象存儲;

Ceph 客戶端

Ceph 支持三種存儲接口:對象存儲 RGW(rados gateway)、塊存儲 RBD(rados block device) 和文件存儲 CephFS;

這三個接口只是在客戶端的封裝庫不同,到服務端了都是對象存儲;
90573-20170204210556245-591968819.jpg

對象存儲(RGW:RADOS gateway)

Ceph 對象存儲服務提供了 REST 風格的 API ,它有與 Amazon S3 和 OpenStack Swift 兼容的接口。也就是通常意義的鍵值存儲,其接口就是簡單的GET、PUT、DEL和其他擴展;

塊存儲(RBD:RADOS block device)

RBD 是通過librbd庫對應用提供塊存儲,主要面向雲平臺的虛擬機提供虛擬磁盤;RBD類似傳統的SAN存儲,提供數據塊級別的訪問;

目前 RBD 提供了兩個接口,一種是直接在用戶態實現, 通過 QEMU Driver 供 KVM 虛擬機使用。 另一種是在操作系統內核態實現了一個內核模塊。通過該模塊可以把塊設備映射給物理主機,由物理主機直接訪問。

文件存儲

Ceph 文件系統服務提供了兼容 POSIX 的文件系統,可以直接掛載爲用戶空間文件系統。它跟傳統的文件系統如Ext4是一個類型,區別在於分佈式存儲提供了並行化的能力;

原生接口

除了以上3種存儲接口, 還可以直接使用 librados 的原生接口,直接和RADOS通信;

原生接口的優點是是它直接和和應用代碼集成,操作文件很方便;但它的問題是它不會主動爲上傳的數據分片;一個1G的大對象上傳,落到 Ceph 的存儲磁盤上就是1G的文件;

而以上三個接口是具有分片功能(即:條帶化 file-striping)

PS:兩個對象的區分

需要說明下,這裏提到兩個對象的概念:一個是 RGW中的對象存儲,一個是 Ceph 的後端存儲的對象;這兩個需要區分:

  • 第一個對象面向用戶,是用戶接口能訪問到的對象;

  • 第二個對象是ceph 服務端操作的對象;

eg:使用RGW接口,存放一個1G的文件,在用戶接口看到的就是存放了一個對象(1);而通過RGW 分片成多個對象(2)後最終存儲到磁盤上;

Ceph 服務端

90573-20170204210612886-2129622012.png

服務端 RADOS 集羣主要由兩種節點組成:一種是爲數衆多的、負責完成數據存儲和維護功能的OSD(Object Storage Device),另一種則是若干個負責完成系統狀態檢測和維護的monitor。

Monitor

Monitor 集羣提供了整個存儲系統的節點信息等全局的配置信息,通過 Paxos 算法保持數據的一致性。

Pool 、PG和OSD

Pool是存儲對象的邏輯分區,它規定了數據冗餘的類型和對應的副本分佈策略;支持兩種類型:副本(replicated)和 糾刪碼( Erasure Code);目前我們公司內部使用的Pool都是副本類型(3副本);

PG( placement group)是一個放置策略組,它是對象的集合,該集合裏的所有對象都具有相同的放置策略;簡單點說就是相同PG內的對象都會放到相同的硬盤上; PG是 ceph的核心概念, 服務端數據均衡和恢復的最小粒度就是PG;

OSD是負責物理存儲的進程,一般配置成和磁盤一一對應,一塊磁盤啓動一個OSD進程;

下面這張圖形象的描繪了它們之間的關係:

  • 一個Pool裏有很多PG,

  • 一個PG裏包含一堆對象;一個對象只能屬於一個PG;

  • PG有主從之分,一個PG分佈在不同的OSD上(針對三副本類型)

90573-20170204210624729-1766568078.jpg

講究的PG

一個Pool裏設置的PG數量是預先設置的,PG的數量不是隨意設置,需要根據OSD的個數及副本策略來確定:

Total PGs = ((Total_number_of_OSD * 100) / max_replication_count) / pool_count

線上儘量不要更改PG的數量,PG的數量的變更將導致整個集羣動起來(各個OSD之間copy數據),大量數據均衡期間讀寫性能下降嚴重;

良好的工程實踐建議(掉坑後的教訓)
預先規劃Pool的規模,設置PG數量;一旦設置之後就不再變更;後續需要擴容就以 Pool 爲維度爲擴容,通過新增Pool來實現(Pool通過 crushmap實現故障域隔離);

對象的尋址過程

查找對象在集羣中的存儲的位置,具體分爲兩步:
第一步,對象到PG的映射;將對象的id 通過hash映射,然後用PG總數對hash值取模得到pg id:

pg_ id = hash( object_ id ) % pg_num

第二步,PG到osd列表映射; 通過crush算法計算PG 上的對象分佈到哪些OSD硬盤上;

CRUSH(PG_ID) = OSD

CRUSH算法是 ceph的精華所在;

crush的目標

先看看crush算法的希望達成的目標:

  1. 數據均勻的分佈到集羣中;

  2. 需要考慮各個OSD權重的不同(根據讀寫性能的差異,磁盤的容量的大小差異等設置不同的權重)

  3. 當有OSD損壞需要數據遷移時,數據的遷移量儘可能的少;

crush算法

簡單說下crush算法的過程:
第一步輸入PG id、可供選擇的OSD id 列表,和一個常量,通過一個僞隨機算法,得到一個隨機數,僞隨機算法保證了同一個key總是得到相同的隨機數,從而保證每次計算的存儲位置不會改變;

CRUSH_HASH( PG_ID, OSD_ID, r ) = draw

第二步將上面得到的隨機數和每個OSD的權重相乘,然後挑出乘積最大的那個OSD;

 ( draw &0xffff ) * osd_weight = osd_straw

在樣本容量足夠大之後,這個隨機數對挑中的結果不再有影響,起決定性影響的是OSD的權重,也就是說,OSD的權重越大,被挑中的概率越大。
到這裏了我們再看看crush算法如何達成的目標:
通過隨機算法讓數據均衡分佈,乘以權重讓挑選的結果考慮了權重;而如果出現故障OSD,只需要恢復這個OSD上的數據,不在這個節點上的數據不需移動;

crush優缺點

聊到這裏,crush算法的優缺點就明顯了:
優點如下:

  • 輸入元數據( cluster map、 placement rule) 較少, 可以應對大規模集羣。

  • 可以應對集羣的擴容和縮容。

  • 採用以概率爲基礎的統計上的均衡,在大規模集羣中可以實現數據均衡。

缺點呢:

  • 在小規模集羣中, 會有一定的數據不均衡現象(權重的影響低,主要起作用的是僞隨機算法)。

看清楚了尋址的過程,就明白爲啥PG不能輕易變更了;PG是尋址第一步中的取模參數,變更PG會導致對象的PG id 都發生變化,從而導致整個集羣的數據遷移;

這裏只是做個引子,關於crush算法,這篇文章講的通俗直白,有興趣的移步:大話Ceph--CRUSH那點事兒

Ceph 是Sega本人的博士論文作品, 其博士論文被整理成三篇短論文,其中一篇就是 CRUSH,
CRUSH論文標題爲《CRUSH: Controlled, Scalable, Decentralized Placement of Replicated Data》,介紹了CRUSH的設計與實現細節。
(PS:另外兩篇是 RADOS和 CephFS, 分別講 Ceph 的服務器實現和 Ceph 文件系統的細節實現)

故障域的劃分

剛開始接觸 Ceph,通常會忽略 crushmap,因爲即使對它不做任何設置,也不影響我們的正常使用;
一旦集羣大了,沒有它集羣就處於一個危險的運行狀態中;
沒有故障域的劃分,整個集羣就處於一個未隔離的資源池中;
一個對象存過去,可能落在 500個OSD硬盤的任意三個上;
如果一塊硬盤壞了,可能帶來的是全局影響(副本copy,這個硬盤上丟失的PG副本可能分佈在全局各個硬盤上);

使用crushmap 將整個集羣的OSD 劃分爲一個個故障域,類似將一個集羣按業務劃分成爲了多個小集羣;每個Pool 只會用到特定的 OSD,這樣,一旦某個OSD 損壞,影響的只是某個業務的某個Pool,將故障的範圍控制在一個很小的範圍內。

良好的工程實踐建議
使用crushmap 劃分故障域,將pool限制在特定的osd list上,osd的損壞只會引起這個pool內的數據均衡,不會造成全局影響;

服務端對象的存儲

對象是數據存儲的基本單元, 一般默認 4MB 大小(這裏指的是RADOS的底層存儲的對象,非RGW接口的對象)。

對象的組成分爲3部分:key 、value、元數據;

  • 元數據可直接存在文件的擴展屬性中(必須是標準的文件屬性),也可存到levelDb中;

  • value 就是對象數據,在本地文件系統中用一個文件存儲;

對於大文件的存儲,Ceph 提供的客戶端接口會對大文件分片(條帶化)後存儲到服務端;這個條帶化操作是在客戶端接口程序完成的,在 Ceph 存儲集羣內存儲的那些對象是沒條帶化的。客戶端通過 librados 直接寫入 Ceph 存儲的數據不會分片。

良好的工程實踐建議
對於對象存儲,只使用 Ceph 提供的 RGW 接口, 不使用 librados原生接口;不僅有分片功能,擴展也更容易(RGW是無狀態的,可水平擴展);大量大對象直接存放到 Ceph中會影響 Ceph 穩定性(存儲容量達到60%後);

總結

上線 Ceph 前,先規劃未來一年的預期使用量,爲每個 pool 一次性設置 PG之後不再變更; 使用crushmap 設置故障域隔離,將磁盤故障後帶來的數據平衡控制在一個小的範圍之內。接口方面推薦只使用Ceph 提供的RGW 接口,不使用 librados原生接口。做好這些, 你的 Ceph 用起來會省心很多。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章