1 Ceph基礎介紹
Ceph是一個可靠地、自動重均衡、自動恢復的分布式存儲系統,根據場景划分可以將Ceph分為三大塊,分別是對象存儲、塊設備存儲和文件系統服務。在虛擬化領域里,比較常用到的是Ceph的塊設備存儲,比如在OpenStack項目里,Ceph的塊設備存儲可以對接OpenStack的cinder后端存儲、Glance的鏡像存儲和虛擬機的數據存儲,比較直觀的是Ceph集群可以提供一個raw格式的塊存儲來作為虛擬機實例的硬盤。
Ceph相比其它存儲的優勢點在於它不單單是存儲,同時還充分利用了存儲節點上的計算能力,在存儲每一個數據時,都會通過計算得出該數據存儲的位置,盡量將數據分布均衡,同時由於Ceph的良好設計,采用了CRUSH算法、HASH環等方法,使得它不存在傳統的單點故障的問題,且隨着規模的擴大性能並不會受到影響。
2 Ceph的核心組件
Ceph的核心組件包括Ceph OSD、Ceph Monitor和Ceph MDS。
Ceph OSD:OSD的英文全稱是Object Storage Device,它的主要功能是存儲數據、復制數據、平衡數據、恢復數據等,與其它OSD間進行心跳檢查等,並將一些變化情況上報給Ceph Monitor。一般情況下一塊硬盤對應一個OSD,由OSD來對硬盤存儲進行管理,當然一個分區也可以成為一個OSD。
Ceph OSD的架構實現由物理磁盤驅動器、Linux文件系統和Ceph OSD服務組成,對於Ceph OSD Deamon而言,Linux文件系統顯性的支持了其拓展性,一般Linux文件系統有好幾種,比如有BTRFS、XFS、Ext4等,BTRFS雖然有很多優點特性,但現在還沒達到生產環境所需的穩定性,一般比較推薦使用XFS。
伴隨OSD的還有一個概念叫做Journal盤,一般寫數據到Ceph集群時,都是先將數據寫入到Journal盤中,然后每隔一段時間比如5秒再將Journal盤中的數據刷新到文件系統中。一般為了使讀寫時延更小,Journal盤都是采用SSD,一般分配10G以上,當然分配多點那是更好,Ceph中引入Journal盤的概念是因為Journal允許Ceph OSD功能很快做小的寫操作;一個隨機寫入首先寫入在上一個連續類型的journal,然后刷新到文件系統,這給了文件系統足夠的時間來合並寫入磁盤,一般情況下使用SSD作為OSD的journal可以有效緩沖突發負載。
Ceph Monitor:由該英文名字我們可以知道它是一個監視器,負責監視Ceph集群,維護Ceph集群的健康狀態,同時維護着Ceph集群中的各種Map圖,比如OSD Map、Monitor Map、PG Map和CRUSH Map,這些Map統稱為Cluster Map,Cluster Map是RADOS的關鍵數據結構,管理集群中的所有成員、關系、屬性等信息以及數據的分發,比如當用戶需要存儲數據到Ceph集群時,OSD需要先通過Monitor獲取最新的Map圖,然后根據Map圖和object id等計算出數據最終存儲的位置。
Ceph MDS:全稱是Ceph MetaData Server,主要保存的文件系統服務的元數據,但對象存儲和塊存儲設備是不需要使用該服務的。
查看各種Map的信息可以通過如下命令:ceph osd(mon、pg) dump
3 Ceph基礎架構組件
從架構圖中可以看到最底層的是RADOS,RADOS自身是一個完整的分布式對象存儲系統,它具有可靠、智能、分布式等特性,Ceph的高可靠、高可拓展、高性能、高自動化都是由這一層來提供的,用戶數據的存儲最終也都是通過這一層來進行存儲的,RADOS可以說就是Ceph的核心。
RADOS系統主要由兩部分組成,分別是OSD和Monitor。
基於RADOS層的上一層是LIBRADOS,LIBRADOS是一個庫,它允許應用程序通過訪問該庫來與RADOS系統進行交互,支持多種編程語言,比如C、C++、Python等。
基於LIBRADOS層開發的又可以看到有三層,分別是RADOSGW、RBD和CEPH FS。
RADOSGW:RADOSGW是一套基於當前流行的RESTFUL協議的網關,並且兼容S3和Swift。
RBD:RBD通過Linux內核客戶端和QEMU/KVM驅動來提供一個分布式的塊設備。
CEPH FS:CEPH FS通過Linux內核客戶端和FUSE來提供一個兼容POSIX的文件系統。
4 Ceph數據分布算法
在分布式存儲系統中比較關注的一點是如何使得數據能夠分布得更加均衡,常見的數據分布算法有一致性Hash和Ceph的Crush算法。Crush是一種偽隨機的控制數據分布、復制的算法,Ceph是為大規模分布式存儲而設計的,數據分布算法必須能夠滿足在大規模的集群下數據依然能夠快速的准確的計算存放位置,同時能夠在硬件故障或擴展硬件設備時做到盡可能小的數據遷移,Ceph的CRUSH算法就是精心為這些特性設計的,可以說CRUSH算法也是Ceph的核心之一。
在說明CRUSH算法的基本原理之前,先介紹幾個概念和它們之間的關系。
存儲數據與object的關系:當用戶要將數據存儲到Ceph集群時,存儲數據都會被分割成多個object,每個object都有一個object id,每個object的大小是可以設置的,默認是4MB,object可以看成是Ceph存儲的最小存儲單元。
object與pg的關系:由於object的數量很多,所以Ceph引入了pg的概念用於管理object,每個object最后都會通過CRUSH計算映射到某個pg中,一個pg可以包含多個object。
pg與osd的關系:pg也需要通過CRUSH計算映射到osd中去存儲,如果是二副本的,則每個pg都會映射到二個osd,比如[osd.1,osd.2],那么osd.1是存放該pg的主副本,osd.2是存放該pg的從副本,保證了數據的冗余。
pg和pgp的關系:pg是用來存放object的,pgp相當於是pg存放osd的一種排列組合,我舉個例子,比如有3個osd,osd.1、osd.2和osd.3,副本數是2,如果pgp的數目為1,那么pg存放的osd組合就只有一種,可能是[osd.1,osd.2],那么所有的pg主從副本分別存放到osd.1和osd.2,如果pgp設為2,那么其osd組合可以兩種,可能是[osd.1,osd.2]和[osd.1,osd.3],是不是很像我們高中數學學過的排列組合,pgp就是代表這個意思。一般來說應該將pg和pgp的數量設置為相等。這樣說可能不夠明顯,我們通過一組實驗來體會下:
先創建一個名為testpool包含6個PG和6個PGP的存儲池
ceph osd pool create testpool 6 6
通過寫數據后我們查看下pg的分布情況,使用以下命令:
ceph pg dump pgs | grep ^1 | awk '{print $1,$2,$15}'
dumped pgs in format plain
1.1 75 [3,6,0]
1.0 83 [7,0,6]
1.3 144 [4,1,2]
1.2 146 [7,4,1]
1.5 86 [4,6,3]
1.4 80 [3,0,4]
第1列為pg的id,第2列為該pg所存儲的對象數目,第3列為該pg所在的osd
我們擴大PG再看看
ceph osd pool set testpool pg_num 12
再次用上面的命令查詢分布情況:
1.1 37 [3,6,0]
1.9 38 [3,6,0]
1.0 41 [7,0,6]
1.8 42 [7,0,6]
1.3 48 [4,1,2]
1.b 48 [4,1,2]
1.7 48 [4,1,2]
1.2 48 [7,4,1]
1.6 49 [7,4,1]
1.a 49 [7,4,1]
1.5 86 [4,6,3]
1.4 80 [3,0,4]
我們可以看到pg的數量增加到12個了,pg1.1的對象數量本來是75的,現在是37個,可以看到它把對象數分給新增的pg1.9了,剛好是38,加起來是75,而且可以看到pg1.1和pg1.9的osd盤是一樣的。
而且可以看到osd盤的組合還是那6種。
我們增加pgp的數量來看下,使用命令:
ceph osd pool set testpool pgp_num 12
再看下
1.a 49 [1,2,6]
1.b 48 [1,6,2]
1.1 37 [3,6,0]
1.0 41 [7,0,6]
1.3 48 [4,1,2]
1.2 48 [7,4,1]
1.5 86 [4,6,3]
1.4 80 [3,0,4]
1.7 48 [1,6,0]
1.6 49 [3,6,7]
1.9 38 [1,4,2]
1.8 42 [1,2,3]
再看pg1.1和pg1.9,可以看到pg1.9不在[3,6,0]上,而在[1,4,2]上了,該組合是新加的,可以知道增加pgp_num其實是增加了osd盤的組合。
通過實驗總結:
(1)PG是指定存儲池存儲對象的目錄有多少個,PGP是存儲池PG的OSD分布組合個數
(2)PG的增加會引起PG內的數據進行分裂,分裂相同的OSD上新生成的PG當中
(3)PGP的增加會引起部分PG的分布進行變化,但是不會引起PG內對象的變動
pg和pool的關系:pool也是一個邏輯存儲概念,我們創建存儲池pool的時候,都需要指定pg和pgp的數量,邏輯上來說pg是屬於某個存儲池的,就有點像object是屬於某個pg的。
以下這個圖表明了存儲數據,object、pg、pool、osd、存儲磁盤的關系
本質上CRUSH算法是根據存儲設備的權重來計算數據對象的分布的,權重的設計可以根據該磁盤的容量和讀寫速度來設置,比如根據容量大小可以將1T的硬盤設備權重設為1,2T的就設為2,在計算過程中,CRUSH是根據Cluster Map、數據分布策略和一個隨機數共同決定數組最終的存儲位置的。
Cluster Map里的內容信息包括存儲集群中可用的存儲資源及其相互之間的空間層次關系,比如集群中有多少個支架,每個支架中有多少個服務器,每個服務器有多少塊磁盤用以OSD等。
數據分布策略是指可以通過Ceph管理者通過配置信息指定數據分布的一些特點,比如管理者配置的故障域是Host,也就意味着當有一台Host起不來時,數據能夠不丟失,CRUSH可以通過將每個pg的主從副本分別存放在不同Host的OSD上即可達到,不單單可以指定Host,還可以指定機架等故障域,除了故障域,還有選擇數據冗余的方式,比如副本數或糾刪碼。
下面這個式子簡單的表明CRUSH的計算表達式:
CRUSH(X) -> (osd.1,osd.2.....osd.n)
式子中的X就是一個隨機數。
下面通過一個計算PG ID的示例來看CRUSH的一個計算過程:
(1)Client輸入Pool ID和對象ID;
(2)CRUSH獲得對象ID並對其進行Hash運算;
(3)CRUSH計算OSD的個數,Hash取模獲得PG的ID,比如0x48;
(4)CRUSH取得該Pool的ID,比如是1;
(5)CRUSH預先考慮到Pool ID相同的PG ID,比如1.48。