用戶文件在Ceph RADOS中存儲、定位過程大概包括:用戶文件切割成對象、對象映射到PG、PG分組PGP、PG映射到OSD。這些過程中,可能涉及了大量概念和變量,而其實它們大部分是通過HASH、CRUSH等算法計算出來的,初始參數可能也就只有這么幾個:用戶文件inode、layout、crush_map等。Ceph所有組件和客戶端通過計算就能得到所有對象的Location,而且只要輸入的參數信息不變,Location就不會變,另外通過PG作為中間層將對象與OSD解綁,使得對象在Ceph RADOS分布更均勻,在OSD增刪時,能夠保證只有盡可能少的對象發生遷移。在PG、PGP調整或OSD增刪后,某些Location發生變化的對象的遷移路線,需要了解各級HASH映射的原理、步驟,更多的計算和分析才能得知。在此基礎上才能分析調整PG和PGP對Ceph集群的影響做一些可靠的定性分析,進而指導我們采用更合適的策略去實現Ceph集群的擴容和數據再均衡。
1. 從用戶文件到對象
從用戶文件到對象的映射過程就是對用戶文件進行切割的過程。CephFS會將用戶文件按照一定的對象大小進行切割,得到若干對象,OSD負責對象的管理。例如,設定對象大小為4MB,則CephFS按照文件字節邏輯地址將1GB的用戶文件切割成1GB/4MB=1024個對象,對象的編號obj_offset取值范圍為[0,1024)。Obj_name = FileInode.obj_offset,FileInode為用戶文件inode的十六進制碼,obj_offset是用戶文件被切割后對象的編號,代表用戶文件的第幾個對象。
如下圖所示:
通過Striper::file_to_extents將用戶文件內容映射到各對象,參數包括用戶文件的布局layout,用戶文件內容的字節邏輯地址偏移offset和長度len等。
對象大小是否可配置?
文件布局可以控制如何把文件內容映射到各Ceph RADOS對象,可以使用虛擬擴展屬性或xattrs來讀、寫某一個文件的布局。布局字段包括object_size,但只能在文件size為0的情況下,才能重新配置。
# 通過以下命令讀取布局字段:
getfattr -n ceph.file.layout.object_size file# 通過以下命令修改布局字段:
setfattr -n ceph.file.layout.object_size -v 10485760 file
2. 從對象到OSD
從對象到OSD的過程包括:對象名hash、對象到PG、PG分組PGP、PG到OSD等主要過程。這里將以某個cephfs用戶文件為例闡述詳細的映射過程。
2.1. 創建文件
-
創建一個文件
touch /mnt/cephfs/file002
-
查看文件ino
ls -i /mnt/cephfs/file0021099511876737 /mnt/cephfs/file002
-
Ino進制轉換
printf "%x\n" 10995118767371000003cc81
-
查看pool信息
ceph osd ?pool ls detailpool 5 'cephfs_data' replicated size 2 min_size 1 crush_rule 0 object_hash rjenkins pg_num 1024 pgp_num 1024 last_change 142 flags hashpspool stripe_width 0 expected_num_objects 16986931 application cephfspool 7 'cephfs_meta' replicated size 2 min_size 1 crush_rule 0 object_hash rjenkins pg_num 1024 pgp_num 1024 last_change 142 flags hashpspool stripe_width 0 expected_num_objects 169869 application cephfs
一個pool有pool_id、pool_name、副本數、pg_num、pgp_num等主要信息參數。pg_num和pgp_num調整分析也是本文的主要內容。從pool的詳細查詢結果可知,5號pool的名字為cephfs_data,采用2副本策略,pg和pgp都為1024。
2.2. 查找零號對象
通過命令可以找到/mnt/cephfs/file002的零號對象存儲在哪個OSD上。
ceph osd map cephfs_data 1000003cc81.00000000osdmap e213 pool 'cephfs_data' (5) object '1000003cc81.00000000' -> pg 5.b184543c (5.3c) -> up ([4,10], p4) acting ([4,10], p4)
從以上結果可知,零號對象1000003cc81.00000000存儲在pg 5.3c,對應的OSD SET是 [4,10],OSD SET為2副本,pg 5.3c的主副本存儲在osd.4中,次副本存儲在osd.10中。
2.3. 對象名HASH
pg 5.b184543c是如何組成的?
以‘.’為分割符,可以分成兩部分5和0xb184543c。5取自pool ‘cephfs_data’的pool_id,而0xb184543是obj_name ‘1000003cc81.00000000’的HASH hex值。
在源碼中,HASH函數ceph_str_hash_rjinkins,根據obj_name計算出一個隨機值。對于同樣的對象名,計算出來的結果永遠都是相同的。而對象名字構成中,用戶文件inode號保證了不同文件之間的對象名字不同,而obj_offset確保了同一用戶文件中不同對象的名字不同。
2.4. 從對象到PG
從“pg 5.b184543c (5.3c)”可知,使用的是5號pool,object 1000003cc81.00000000的HASH hex為“0xb184543c”,本文用obj_hash表示,也稱為對象的placement seed,此值會被保存在代表pg的類pg_t的對象中,這里簡稱為pg_seed。
那pg 5.3c為什么只取了object hash hex碼的后2兩位呢?
是因為5號pool的pg總數為1024個,1024對應0x400,則mask = 0x400 - 1 =0x3ff,因此只需要取0x3ff & b184543c = 0x3c,這樣就完成了從對象到PG的映射。最終,一個pg可以表示為pool_id.(mask & obj_hash),一個pool中pg的編號取值范圍為[0,mask]。
2.5. PG分組PGP
眾所周知,Ceph官方建議一個pool的pg_num = pgp_num
,而且為2的冪次方。而說白了,PG分組PGP就是將眾多PG分成各個PGP組。在二者相等的情況下,一個PGP中就只有一個PG。
但如果PGP小于PG呢?根據抽屜原理,肯定存在某些PGP分配到了2個或2個以上的PG。這種情況是否存在呢?答案是肯定的,該狀態可能只是個中間態,在用戶采用了小步調多次調整策略實施PG和PGP的調整,來配合集群OSD添加,最終pg_num會等于pgp_num。
例如,Ceph集群通過增加OSD數量達到擴容的目的,擴容后每個OSD平均承擔的PG數量將會小于Ceph官方建議的100~200個,因為在這個取值范圍內,集群數據分布均衡度與OSD負載都是比較合適的。因此,擴容后需要相應的調大pg_num和pgp_num,二者的調整是兩個獨立的順序操作,因此會存在二者不相等的中間狀態。另外,為了保證集群的穩定性,通常是小步調多次的調整pg_num和pgp_num,經過多輪的調整后達到整體調整目標。
這里可能會有一個疑問是,處于相同或不同PGP中的各PG,會有什么聯系呢?
答案是,同一個pool中處于相同PGP中的各個PG會被映射到相同的OSD SET,而處于不同PGP中的各個PG一般會被映射到不同的OSD SET,但也不能完全排除被映射到相同OSD SET的可能性,這塊的內容涉及到了ceph引以為傲的CRUSH算法,由于本文重點不在此,后期將有專門的文章做介紹。
下圖中,ceph_state_mod通過PG的pg_seed與pgp_num_mask按位&,將各PG映射到PGP。
2.6. 從PG到OSD
Ceph數據存儲策略有副本和EC兩種,本文基于副本策略。用戶可以選擇2副本、3副本等,副本越多空間利用率就越低,而可靠性就越高,因此需要用戶在空間利用率與可靠性二者之間做平衡。多副本情況下,PG到OSD的映射其實是PG到OSD SET的映射,OSD SET的成員個數為副本數,而首成員為主副本,其他成員為次副本,客戶端的讀寫由主副本負責,這塊內容涉及到了ceph集群的讀寫流程,這里不做太詳細的介紹,后期文章再做分析。
下圖中,_pg_to_raw_osds完成PG到OSD SET的映射,首先調用了pool.raw_pg_tp_pps完成了PG到PGP的分組,會得到分組唯一標識的placement ps即pps。然后,通過crush->find_rule找到pool的ruleno。最后,調用crush->do_rule基于ruleno和pps完成PG到OSD SET的映射。
雖然,兩個PG的ps可能不同,但pps可能相同,那映射到的OSD SET就會相同,可以說它們選擇了相同的OSD SET來存儲數據,也就是說同一個OSD上會承擔多個PG,每個OSD上平均承擔的PG越多,在非常大量的對象情況下,每個OSD上存儲的數據就越均衡。每個OSD上承擔的PG越多,OSD管理PG的壓力就越大,因此官方對每個OSD平均承擔的PG數的合理取值范圍為100~200。
CRUSH算法是ceph非常非常引以為傲的的特色,通過它,ceph中的每個組件或客戶端都能自己計算出對象到OSD SET的映射,并不需要提供映射表查詢的中心節點,從而避免了中心節點的瓶頸問題。本文重點不在CRUSH算法,此處不做詳細闡述分析,后期會有單獨文章做介紹。
3. 對象文件的命名規則
這里需要說明一下,本文中涉及的對象文件名字與對象名字不同,盡管二者就是同一個對象。對象文件名字指的是對象在linux xfs文件系統中的文件名字。
當前,OSD的兩個主要類型為Filestore和Bluestore,本文基于Filestore。Filestore類型的OSD一般利用linux本地文件系統xfs存儲和管理對象文件,用戶文件被切割成對象文件后,一個對象就對應xfs的一個文件,一個xfs文件通過文件路徑Path和文件名FileName定位,舉例如下:
?/var/lib/ceph/osd/ceph-4/current/5.3c_head/DIR_C/DIR_3/DIR_4/1000003cc81.00000000__head_B184543C__5
該對象文件的Path = “/var/lib/ceph/osd/ceph-4/current/5.3c_head/DIR_C/DIR_3/DIR_4/”,FileName = “1000003cc81.00000000__head_B184543C__5”。
Path也包含了許多含義,ceph-4代表了osd.4,5.3c代表了5號pool中0x3c的pg,這些信息與前面章節一致。而DIR_C、DIR_3和DIR_4是pg dir split的結果,目的是為了保證每個目錄中文件數不要過多,xfs某個目錄特別大時,對于執行目錄的ls等操作不利,而且過大的目錄在被讀進內存時,會消耗過多的內存,對該目錄進行flush時也會花費更多的時間,當然還有其他缺點存在。
不難發現,將“_”作為分隔符,可以將FileName分割成若干部分,1000003cc81.00000000是對象名字,B184543C為對象名字的HASH hex值即pg的ps,5就是pool cephfs_data的號。對象文件名字結構如下所示:
很多組成部分在文章前面已經做了介紹,這里只做以下補充:
-
key和hash不能同時指定,而且常見的是hash;
-
snap_num為head,代表普通對象,否則為snapshot對象。可以給rbd image創建snapshot,這時候底層對象就有snapshot信息了;
-
namespace可以認為是對pool空間的進一步劃分,在邏輯上隔離各個用戶。一個pool可以劃分多個namespace,這些namespace中的對象都使用該pool。尤其應用在ceph rgw服務中。
到此為止,我們已經對用戶文件是如何在Ceph中存儲的過程有了大概的了解。該過程可以概括為:用戶文件切割成對象、對象映射到PG、PG映射到OSD。這個過程中,可能涉及了大量概念和變量,而其實它們大部分是通過HASH、CRUSH等算法計算出來的,初始參數可能也就只有這么幾個:用戶文件inode、layout、crush_map等,通過計算就能得到所有對象的Location,而且只要輸入的參數信息不變,Location就不變,另外通過PG作為中間層將對象與OSD解綁,而且使得對象在ceph RADOS中均勻分布。但本人覺得這也有一點點的小缺點,就是在PG、PGP調整或OSD增刪后,某些Location發生變化的對象遷移路線并不是那么直接和直觀,需要了解各級HASH映射的原理、步驟,更多的計算和分析才能得知。
4. PG調整的影響
為了簡化問題,抓住重點,假設對象的分布如下:
根據文章前面的內容,表格中所有代號都能找到定義和計算方法,這里做一個簡單的總結:?
-
obj_hash = hash(obj_name);
-
pg_seed = obj_hash;
-
pgId = pg_seed & pg_mask;
-
pgpId = pg_seed & pgp_mask;
4.1. PG非冪次方調整
將pg_num由2調整為3,pgp_num依然為2。調整后,對象的分布如下:
從表中可知:?
-
pg_2分擔了原屬于pg_0的obj_2和obj_8,pg_2與pg_0對應同一個OSD SET,因此obj_2和obj_8只是OSD內部的遷移;
-
pg_2分擔了原屬于pg_1的obj_5和obj_11,pg_2與pg_1對應不同的OSD SET,obj_5和obj_11涉及到了OSD之間的遷移,不同OSD之間就會有網絡通信開銷;
-
pg_0分擔了原屬于pg_1的obj_3和obj_9,也會涉及網絡通信開銷;
-
pg_1分擔了原屬于pg_0的obj_4和obj_10,也會涉及網絡通信開銷。
總之,共涉及OSD內部遷移2次,共涉及OSD之間遷移6次。我們將OSD內部遷移率定義為inter_mig_ratio,將OSD之間遷移率定義為ext_mig_ratio,則計算結果為:
由于OSD內部遷移,只是將一個對象文件從源目錄mv到目的目錄,由于源目錄與目的目錄共享同一個OSD的根目錄,因此mv操作只涉及xfs文件系統元數據的更新,不涉及對象文件數據的讀取和寫入,可以稱OSD內部遷移為輕遷移;
而OSD之間遷移,源OSD需要讀取對象文件數據,網絡通信發送到目的OSD,目的OSD再創建該對象文件,目的OSD寫入對象文件數據,源OSD刪除該對象文件,稱OSD之間遷移為重遷移。
我們將OSD內部一次對象遷移的工作量定義為1,將OSD之間一次對象遷移的工作量定義為4,則總的工作量為:
因此,inter_mig_ratio反應了輕遷移率,而ext_mig_ratio反應了重遷移率,盡量減少重遷移,降低重遷移率,將重遷移變成輕遷移,最終減少數據遷移對ceph集群整體穩定性和性能的影響。
4.2. PG冪次方調整
將pg_num由2調整為4,pgp_num依然為2。調整后,對象的分布如下:
從表中可知:?
-
pg_2分擔了原屬于pg_0的obj_2、obj_6和obj_10,pg_2與pg_0對應同一個OSD SET,因此obj_2、obj_6和obj_10只是OSD內部的遷移;
-
pg_3分擔了原屬于pg_1的obj_3、obj_7和obj_11,pg_3與pg_1對應同一個OSD SET,因此obj_3、obj_7和obj_11也只是OSD內部的遷移。
總之,共涉及OSD內部遷移6次。
4.3. PG非冪次與冪次調整對比
inter_mig_ratio | ext_mig_ratio | work_load | |
非冪次(2->3) | 16.67% | 50% | 2.17 |
冪次(2->4) | 50% | 0% | 0.5 |
由上表可知,本文中PG非冪次調整引入的工作量遠遠高于冪次調整引入的工作量,因此建議PG調整最好選擇冪次調整,盡量減少PG調整引入的工作量,降低PG調整對ceph集群穩定性和性能的負面影響。
比如,PG由2調整到16,當然可以選擇直接調整到目標16,PG調整一步到位。也可以選擇小步調多次調整,推薦這樣的調整步調2->4->8->16。一步到位的調整策略與小步調多次調整策略各有優缺點,前者實現PG調整一次到位,但單次調整就引入大量的OSD內部遷移,雖然沒有OSD之間遷移;后者將單次引入的大量OSD內部遷移分散到了多次調整里,因此單次小步調調整引入的OSD內部遷移相對較少,降低了PG調整對ceph集群穩定性和性能的負面影響,但是由于后者分成多次調整達到最終目標,相對前者會引入額外的中間態OSD內部遷移,因此后者總的OSD內部遷移量會高于前者。因為實踐證明,后者的優點大于缺點,因此推薦采用PG小步調多次調整策略。
5. PGP調整的影響
為了簡化問題,抓住重點,假設OSD SET只有0和1,對象的分布如下:
5.1. PGP非冪次方調整
將pgp_num由2調整為3,pg_num依然為4。調整后,對象的分布如下:
從表中可知:?
-
pgp_2分擔了原屬于pgp_0的pg_2,而pgp_2使用OSD SET 0,而pg_2原本就使用OSD SET 0,因此這一變動不會有任何數據遷移;
-
pgp_0分擔了原屬于pgp_1的pg_3,而pg_3對應的OSD SET由1號變成了0號,因此pg_3的所有對象將由OSD SET 0遷移到OSD SET 1,涉及到了OSD之間的遷移,不同OSD之間就會有網絡通信開銷。
總之,共涉及OSD內部遷移0次,涉及OSD之間遷移6次。則inter_mig_ratio、ext_mig_ratio和work_load為:
因此,inter_mig_ratio代表了輕遷移率,而ext_mig_ratio代表了重遷移率,盡量減少重遷移,降低重遷移率,將重遷移變成輕遷移,最終減少數據遷移對ceph集群整體穩定性和性能的影響。
5.2. PGP冪次方調整
將pgp_num由2調整為3,pg_num依然為4。調整后,對象的分布如下:
總之,共涉及OSD內部遷移0次,涉及OSD之間遷移0次。則inter_mig_ratio、ext_mig_ratio和work_load為:
通過以上表格發現,雖然pg_2和pg_3對應的pgp有變化,但對應的OSD SET未發生變化,因此該調整,不會發生任何的數據遷移。?
5.3. PGP非冪次與冪次調整對比
PGP調整章節的分析內容僅限于ceph集群OSD SET組合情況未變話,而實際情況導致OSD SET組合情況變更的條件包括:副本策略變化、OSD增減、故障域變更等等。
inter_mig_ratio | ext_mig_ratio | work_load | |
非冪次(2->3) | 0% | 25% | 1 |
冪次(2->4) | 0% | 0% | 0 |
由上表可知,PGP冪次調整優于非冪次調整。
6. 疑問和思考
用戶文件的對象切割,對象名字的組成部分,對象到PG的映射過程,PG與PGP的關系,PG到OSD的映射過程,最后介紹了PG和PGP冪次和非冪次調整策略對ceph集群穩定性和性能的負面影響分析,但PG和PGP調整最終目標是好的,是為了配合ceph集群OSD擴容,是為了ceph集群數據分布的更均衡和合理,只是在選擇PG和PGP調整策略時要有所選擇,而并不是盲目的去實施。