Ceph 分佈式存儲原理 - 架構圖詳解

ceph 介紹


ceph 是一個統一的、分佈式的存儲系統,設計初衷式提供較好的性能 (io)、可靠性 (沒有單點故障) 和可擴展性 (未來可以理論上無限擴展集羣規模),這三點也是集羣架構所追求的。

統一性 :

意味着我們可以僅憑 ceph 這一套存儲系統,同時提供塊存儲和文件系統存儲、對象存儲。這三種功能,這極大地簡化了不同應用需求下地部署和運維工作。

分佈式 :

傳統集羣架構: 集羣規模增大,mysql 數據的集羣規模必然也要隨之增大,這完全是集中分佈是思想帶來的弊端。

ceph 內部集羣的數據共享完全通過算法算出來,根本不需要數據庫這個組件,完全分佈式的。

ceph 分佈式的缺點: 耗費 cpu。

什麼是塊存儲、文件存儲、對象存儲


塊級與文件級概念

  1. 塊級

磁盤的最小讀寫單位爲扇區,1 個或多個連續的扇區組成一個 block 塊,也稱之爲物理塊,是操作系統的讀寫單位。

一個邏輯文件對應一個物理塊。

blockdev --getbsz /dev/sda1					查看block塊大小(一個block塊默認512字節)
# 512
  1. 文件級

文件是文件系統提供的功能,單個文件可能由一個或者多個邏輯塊組成,且邏輯塊之間是不連續分佈的,邏輯塊大於或等於物理塊整數倍。

物理塊與文件系統之間的映射關係爲: 扇區–> 物理塊–> 文件系統

注意 : 這麼多層的轉換,是需要耗費效率。

塊存儲 : 存儲設備共享給客戶端的是一塊裸盤,那麼該存儲設備提供的就是塊存儲

客戶端可定製性強,可以自己製作文件系統,然後掛載使用,或者直接把操作系統安裝在塊存儲裏面。

適用於給 vm(虛擬機) 的本地硬盤。虛擬機是用軟件模擬出來的,存在不穩定因素,如果虛擬機出現 down 機了,可能會導致數據丟失,使用塊存儲有利於保護虛擬機數據的安全。

文件存儲 : 存儲設備共享給客戶端的是文件夾,那麼該存儲設備提供的就是文件存儲

  1. 客戶端主要操作的是文件和文件夾,客戶端無法格式化製作自己的文件系統,使用的是現成文件系統,定製性差。

  2. 文件檢索與存儲過程都是在存儲設備中完成的,意味着隨着客戶端數目的增多,存儲設備的壓力會越來越大,所以文件存儲會限制集羣的擴展規模。

適用於中小型規模集羣的多服務器之間數據共享,並且保證一致。

對象存儲 : 數據的存儲分爲兩部分: inode(元數據) + block(真實數據) ( 數據存儲的形式爲 key:value 的形式 )。

  1. 基於多服務器之間的數據共享,保證數據一致,並且沒有文件系統的概念,

  2. 沒有文件系統的概念,服務端不會隨着客戶端數目的增多而壓力成倍增大。

適用於分佈式存儲,雲存儲。

爲何要用 ceph


- 高性能 : 
1. 摒棄了傳統的集中式存儲元數據尋址的方案,採用CRUSH算法,數據分佈均衡,並行度高。
2. 考慮了容災的隔離,能夠實現各類負載的副本放置規則,例如跨機房、機架感知等。
3. 能夠支持上千個存儲節點的規模,支持TB到PB級的數據。

- 高可用 : 
1. 副本數可以靈活控制
2. 支持故障域分隔,數據強一直性
3. 多故障場景自動進行修復自愈
4. 沒有單點故障,自動管理,高可擴展性

- 去中心化 : 
1. 擴展靈活
2. 隨着節點增加而線性增長

- 特性豐富 : 
1. 支持三種存儲接口 : 塊存儲、文件存儲、對象存儲
2. 支持自定義接口,支持多種語言驅動。

Ceph 系統的層次結構


自下而上,可以將 Ceph 系統分爲四個層次

  1. 對象存儲接口 (RADOS GW)

  2. 塊存儲接口 (RBD)

  3. 文件存儲接口 (Ceph FS)

基礎存儲系統 RADOS


ceph 集羣架構類似於一個網絡版本的 raid10 模式

單臺機器可插硬盤的總數是有限的,如果能通過網絡通信,那麼就可以打破單臺機器的限制:一堆硬盤 + 軟件控制起來

做成硬盤的集羣,相當於一個大的網絡 raid,這就是分佈式存儲,比如 ceph。

ceph 集羣的子集羣


  1. OSD(osd daemon) 集羣

一個 osd daemon 就是一個套接字應用程序,一個 osd daemon 唯一對應一塊數據盤 (數據盤的組成可以是一塊機械硬盤 + 一塊固態盤的兩個分區)。

綜合算下來,OSD 集羣由一定數目的 osd daemon 組成 (osd daemon 數量從幾十個到幾十萬個不等,也有可能會更多)。

ceph 的不同版本 osd daemon 與 disk(數據盤) 之間的對應關係

hammer(老版本): osd daemon --> xfs文件系統 --> disk
- xfs文件系統叫日誌文件系統,先寫入日誌,再寫入數據內容。一個disk = 一個機械盤 + 一個固態盤
- 性能優化 : 固態盤負責存文件系統日誌,機械盤負責寫入數據內容。

luminous(新版本): osd daemon --> 裸盤disk
- 一個disk搭配固態盤的兩個分區,一個固態盤分兩個分區,一個分區存日誌,一個分區存元數據
- 一個固態盤兩個分區下面搭配一個機械盤。

對比 hammer 版本和 luminous 版本,luminous 版本的 osd daemon 是直接傳輸數據給數據盤的。因此,不需要經歷物理塊與文件系統之間的轉換,讀寫數據效率要高於 hammer 版本。

osd daemon 節點主要負責:

  1. 負責控制數據盤上的文件讀寫操作,與 client 通信完成各種數據對象操作等等

  2. 負責數據的拷貝和恢復

  3. 每一個 osd daemon 守護進程監視它自己的狀態,以及別的 osd deamon 的狀態,並且報告給 Monitor(監控節點,控制了 ceph 集羣的行爲)

pg_temp 狀態

pg 組中的 osd daemon 也有主次之分,一個 pg 組裏面有多個 osd daemon,crush 算法會默認把其中一個 osd damon 作爲 primary osd(主 osd daemon),主 osd daemon 主要負責接收數據的讀寫;其餘的作爲 replication osd(從 osd daemon),從 osd daemon 主要負責數據的備份。

  1. 如果 pg 組中的 replication osd 掛了,crush 算法會默認將 primary osd 的數據備份一份到新加入的 replication osd 中。

  2. 如果 pg 組中的 primary osd 掛了,crush 算法將一個新的 osd deamon 劃分到這個 pg 組中作爲 primary osd,那麼 crush 算法會先將 pg 組裏面原來的 replication osd 暫時先作爲主 osd daemon。等到新劃分的 primary osd 備份了這個 pg 組裏面的數據,會正式作爲主 osd daemon 負責接收這個 pg 組的數據讀寫。發生這種現象,pg 狀態會短暫處於 pg_temp 狀態。

  3. MON(Montior) 集羣

Montior 節點主要負責 :

  1. 監控全局狀態 (cluster map)
cluster map負責監控:
	1. osd daemon map
	2. monitor map
	3. pg map
	4. crush map
  1. 負責管理集羣內部狀態 (osd daemon 掛掉,數據恢復等操作)

  2. 負責授權,客戶端在訪問時會先通過 monitor 集羣驗證操作權限 客戶端需要先跟 monitor 要到 cluster map

ps : monitor 節點的個數 = 2*n+1

  1. 必須爲奇數個

  2. 一個 monitor 存在單點故障的問題,所以最少三個起

MON 集羣爲何 monitor 節點個數應該爲奇數個

MON 集羣可以掛掉幾個 monitor 節點

monitor 進程與 osd daemon 進程能否在同一個物理節點上

Ceph 集羣的核心邏輯概念


ceph 的特性

  1. 僞數據平衡,是通過算法達到的
object ---> pg組    	是通過hash算法實現的
pg組 ---> osd daemon    是通過crush算法實現的

2.ceph 適用於海量小文件,或者單個容量大文件

pg 和 pool 相關概念

ceph 的邏輯單位

一個 osd daemon 應該屬於多少個 pg 組呢

Ceph 網絡劃分


Ceph 推薦主要使用兩個網絡,這麼做,注意從性能 (OSD 節點之間會有大量的數據拷貝操作) 和安全性 (兩網分離) 考慮。

pool 存儲池詳解


Ceph 的 pool 有四大屬性

  1. 所有性和訪問權限

  2. 對象副本數目,默認 pool 池中的一個 pg 只包含兩個 osd daemon,即一份數據交給 pg 後會存下 2 個副本,生產環境推薦設置爲 3 個副本。

  3. pg 數目,pg 是 pool 的存儲單位,pool 的存儲空間就由 pg 組成

  4. crush 規則集合

pg 數與 osd daemon 之間對應關係的影響

創建 pool 時需要確定其 pg 的數目,在 pool 被創建後也可以調整該數字,但是增加池中的 pg 數是影響 ceph 集羣的重大事件之一,在生產環境中應該避免這麼做。因爲 pool 中的 pg 的數目會影響到:

  1. 數據的均勻分佈性

  2. 資源消耗:pg 作爲一個邏輯實體,它需要消耗一定的資源,包括內存,CPU 和帶寬,太多的 pg 的話,則佔用資源會過多

  3. 清理時間:Ceph 的清理工作是以 pg 爲單位進行的。如果一個 pg 內的數據太多,則其清理時間會很長

  4. 數據的持久性:pool 中的 pg 個數應該隨着 osd daemon 的增多而增多,這樣 crush 算法可以將 pg 和 osd 的對應關係儘量均勻一些,降低同一個 osd 屬於很多個 pg 的幾率,如果一個 osd 真的屬於很多很多 pg,這樣可能會很糟糕,可能會出現如下情況:

假設我們 pool 副本的 size 爲 3,則表示每一個 pg 將數據存放在 3 個 osd 上。一旦某個 osd daemon 掛掉,因爲一個 osd daemon 同時屬於很多個 pg,則此時會出現很多 pg 只有 2 個副本的情況,這個時候通過 crush 算法開始進行數據恢復。在數據恢復的過程中,因爲數據量過大,又有一個 osd daemon(也屬於很多很多 pg) 扛不住壓力也崩潰掉了,那麼將會有一部分 pg 只有一個副本。這個時候通過 crush 算法再次開始進行數據恢復,情況繼續惡化,如果再有第三個 osd daemon 掛掉,那麼就可能會出現部分數據的丟失。

由此可見,osd daemon 上的 pg 組數目:

  1. 不能過小,過小則數據分佈不均勻

  2. 不能過大,過大則一個 osd daemon 掛掉影響範圍會很廣,這會增大數據丟失的風險

osd daemon 上的 pg 組數目應該是在合理範圍內的,我們無法決定 pg 組與 osd daemon 之間的對應關係,這個是由 crush 算法決定的。但是我們可以在創建 pool 池時,可以指定 pool 池內所包含 pg 的數量,只要把 pg 的數量設置合理,crush 算法自然會保證數據均勻。

指定 pool 池中 pg 的數量

如何算出一個 pool 池內應該有多少個 pg 數?

計算公式:

(Target PGs per OSD)✖(OSD#)✖(%DATA)/Size

如果如果ceph集羣很長一段時間都不會拓展,我們osd daemon的總數爲9,該存儲池佔用整個ceph集羣整體存儲空間的百分比爲1%(10G/1000G),
pool池中的副本數爲3個,那麼我們在pool池中設置pg的數量爲多少合理?
100 * 9 * 0.01 / 3 = 3 ()

官網也給出了一些參考原則

osd daemon 的總數爲 50 個以上,我們可以使用官網的工具進行計算,來確定 pool 池中 pg 的個數。ceph 官網計算工具網址:https://ceph.com/pgcalc/

Ceph 中 pool 池的兩種類型

1.Replicated pool(默認)

副本型 pool,通過生產對象的多份拷貝

優點 : 保證了數據的安全

缺點 : 浪費空間,如果設置的 pg 對應三個副本,那麼空間只能用到原來空間的三分之一

2.Erasure-coded pool

特點 : 沒有副本,可以把空間百分之百利用起來,但是沒有副本功能 (無法保證數據的安全)

不支持 ceph 的壓縮,不支持 ceph 垃圾回收的功能等

pg 邏輯單位詳解


pg 概念

舉個例子,現在 acting set 是 [0,1,2],出現了一點事情後,它變爲了 [3,2,1]。此時,osd.3 還是空的,它無法提供數據服務,因此它還需要等待回填數據過程結束。這時候,osd.3 會向 monitor 集羣申請一個臨時的 set [1,2,3]。此時,將由 osd.1 提供數據服務。回填數據過程結束後,該臨時的 set 會被丟棄,重新由 osd.3 提供服務。

pg 的狀態

其主要狀態包括

1.Creating 創建中:pg 組正在被創建。

2.Peering 對等互聯:Peering 就是一個 pg 組的所有的 osd daemon 都需要互相通信,pg 組的對象及其元數據的狀態達成一致的過程。

3.Active 活動的:Peering 的過程完成之後,pg 組的狀態就是 active 的。此狀態下,主次的 osd daemon 上的 pg 組數據都是可用的,即 pg 組內主 osd daemon 和從 osd daemon 都處於就緒狀態,可正常提供客戶端請求。

4.Clean 潔淨的:此狀態下,主次 osd daemon 都已經處於就緒狀態,每個副本都就緒了。

5.Down:pg 掉線了。

6.Degraded 降級的:某個 osd daemon 被發現停止服務 (down) 了之後,Ceph 的 Montior 集羣將該 osd daemon 上所有的 pg 的狀態設置爲 degraded,即 pg 包含的 osd 數目不夠,此時該 osd daemon 的對等 osd daemon 會繼續提供數據服務。這時會有兩種結果:

  1. down 掉的 osd daemon 會重新起來,需要再經過 Peering 到 clean 的狀態,而且 Ceph 會發起恢復過程 (recovering 增量恢復),使用該 osd daemon 上過期的數據被恢復到最新狀態。

  2. osd daemon 的 down 狀態持續 300 秒後其狀態被設置爲 out 提出集羣,Ceph 會啓動自恢復操作,選擇其他的 osd daemon 加入 acting set,並啓動回填數據 (backfilling 全量恢復) 到新的 osd daemon 的過程。使 pg 副本數恢復到規定的數目,有時候崩潰的時候也會處於此狀態。

7.Remapped 重映射:每當 pg 的 acting set 改變後,就會發生從舊的 acting set 到新的 acting set 的數據遷移。此過程結束前,舊的 acting set 中的主 osd daemon 將繼續提供服務。一旦該過程結束,Ceph 將使用新的 acting set 中的主 osd dameon 來提供服務。

8.Stale 過期的:每個 osd daemon 每隔 0.5 秒向 monitor 集羣報告其狀態。如果因爲任何原因,主 osd daemon 報告狀態失敗了,或者其他 osd daemon 已經報告了主 osd daemon 狀態爲 down 了,monitor 集羣將會將他們的 pg 標記爲 stale 狀態。

9.Undersized: 當 pg 中副本數少於其他存儲池指定的個數的時候,就爲此狀態。

10.Scrubbing:osd daemon 會週期性的檢查其持有的數據對象的完整性,以確保主 osd daemon 和從 osd daemon 數據的一致,這時候狀態就爲此狀態。另外 pg 偶爾還需要檢查確保一個對象的 osd daemon 能按位匹配,這時候狀態爲 scrubbing + deep。

11.recovering:增量恢復。

12.backfilling:全量恢復。

13.unkown:表示 pg 不知道與哪些 osd daemon 對應。出現這種狀態,表示指定的 Crush 規則錯誤了。

Crush 規則詳解


什麼是 Crush

Crush 在 ceph 集羣中的作用

Crush rules(規則) 的三個作用

  1. 指定從 Crush Map 中的哪個節點開始查找

  2. 指定使用哪個節點作爲故障隔離域

  3. 指定定位副本的搜索模式 (廣度優先 or 深度優先)

自定義 Crush 規則

rule nana_rule {					# 規則集的命名,創建pool時可以指定rule集
	id 1							# id設置爲1
	type replicated					# 定義pool池類型爲replicated(還有esurecode模式)
		
	min_size 1						# pool中最小指定的副本數量不能小於1
	min_size 10						# pool中最大指定的副本數量不能大於10

	# pg到osd daemon的檢索步驟
	step take datacenter0			# 定義pg查找副本的入口點datacenter0
									# 這一步選擇一個根節點,這個節點不一定是root
									# 這個節點可以是任何一個故障域
									# 從指定選擇的這個節點開始執行

	step chooseleaf firstn 0 type rack		# firstn 0表示算法(深度優先),type rack表示故障域設置爲rack
	step emit						# 結束,返回結果
}

如果有三個 osd 物理節點,然後他們都放在同一個機櫃裏,故障域應該設置爲 host;最好是放在三個不同的機櫃裏,然後故障域設置爲 rack。

故障域

Ceph 集羣中的默認的故障域,目的是爲了防止單點故障

存儲引擎


hammer 版本的存儲引擎 : filestore

filestore : osd daemon --> xfs文件系統 --> 磁盤

luminous 版本的存儲引擎 : bluestore

bluestore : osd daemon --> 裸磁盤

luminous 版本我們通常會 osd daemon --> lvm --> 裸磁盤,讓 osd daemon 直接對應一個 lvm。那麼我們爲什麼要這麼做?

如果我們在 ceph 集羣即將用滿的情況下進行擴容,那麼該如何擴容?

1.osd daemon --> 裸磁盤

新增一塊磁盤,然後用 osd daemon 管理它。但問題是,新增的一個 osd daemon,ceph 會在該 osd aemon 上創建一個 pg,說白了就是把該 osd daemon 劃分到一些 pg 組裏面。但凡 osd daemon 被分配到 pg 裏,會發生數據遷移。生產環境中,pg 的數量能不動則不動。

2.osd daemon --> lvm --> 裸磁盤

從 vg 組裏面劃分更多的空間給 lvm,不必新增 osd daemon,後期的擴容,不會發生數據遷移。

考慮到集羣日後的擴容,那麼推薦使用方案:osd daemon --> lvm --> 裸磁盤

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ziJclwuZ3YGnSo3FRloILw