大話Ceph--RBD那點事兒
引言
這篇文章主要介紹了RBD在Ceph底層的儲存方式,解釋了RBD的實際佔用容量和RBD大小的關係,用幾個檔案的例子演示了檔案在RBD(更恰當的是xfs)中的儲存位置,最後組裝了一個RBD,給出了一些FAQ。
RBD是什麼
RBD : Ceph’s RADOS Block Devices , Ceph block devices are thin-provisioned, resizable and store data striped over multiple OSDs in a Ceph cluster.
上面是官方的闡述,簡單的說就是:
-
RBD就是Ceph裡的塊裝置,一個4T的塊裝置的功能和一個4T的SATA類似,掛載的RBD就可以當磁碟用。
-
resizable
:這個塊可大可小。 -
data striped
:這個塊在ceph裡面是被切割成若干小塊來儲存,不然1PB的塊怎麼存的下。 -
thin-provisioned
:精簡置備,我認為的很容易被人誤解的RBD的一個屬性,1TB的叢集是能建立無數1PB的塊的。說白了就是,塊的大小和在ceph中實際佔用的大小是沒有關係的,甚至,剛創建出來的塊是不佔空間的,今後用多大空間,才會在ceph中佔用多大空間。打個比方就是,你有一個32G的U盤,存了一個2G的電影,那麼RBD大小就類似於32G,而2G就相當於在ceph中佔用的空間。
RBD,和下面說的塊
,是一回事。
實驗環境很簡單,可以參考一分鐘部署單節點Ceph
建立一個1G的塊foo
,因為是Hammer
預設是format 1
的塊,具體和format 2
的區別會在下文講到:
[[email protected] cluster]# ceph -s
cluster fc44cf62-53e3-4982-9b87-9d3b27119508
health HEALTH_OK
monmap e1: 1 mons at {ceph=233.233.233.233:6789/0}
election epoch 2, quorum 0 ceph
osdmap e5: 1 osds: 1 up, 1 in
pgmap v7: 64 pgs, 1 pools, 0 bytes data, 0 objects
7135 MB used, 30988 MB / 40188 MB avail
64 active+clean
[ [email protected] cluster]# rbd create foo --size 1024
[[email protected] cluster]# rbd info foo
rbd image 'foo':
size 1024 MB in 256 objects
order 22 (4096 KB objects)
block_name_prefix: rb.0.1014.74b0dc51
format: 1
[[email protected] cluster]# ceph -s
...
pgmap v10: 64 pgs, 1 pools, 131 bytes data, 2 objects
7136 MB used, 30988 MB / 40188 MB avail
64 active+clean
Tips :
rbd
的指令如果省略-p / --pool
引數,則會預設-p rbd
,而這個rbd pool是預設生成的。
對剛剛的rbd info
的幾行輸出簡單介紹下:
size 1024 MB in 256 objects
order 22 (4096 KB objects)
block_name_prefix: rb.0.1014.74b0dc51
format: 1
-
size
: 就是這個塊的大小,即1024MB=1G,1024MB/256 = 4M
,共分成了256個物件(object),每個物件4M,這個會在下面詳細介紹。 -
order 22
, 22是個編號,4M是22, 8M是23,也就是2^22 bytes = 4MB, 2^23 bytes = 8MB。 -
block_name_prefix
: 這個是塊的最重要的屬性了,這是每個塊在ceph中的唯一字首編號,有了這個字首,把伺服器上的OSD都拔下來帶回家,就能復活所有的VM了。 -
format
: 格式有兩種,1和2,下文會講。
觀察建foo
前後的ceph -s
輸出,會發現多了兩個檔案,檢視下:
pgmap v10: 64 pgs, 1 pools, 131 bytes data, 2 objects
[[email protected] cluster]# rados -p rbd ls
foo.rbd
rbd_directory
再檢視這兩個檔案裡面的內容:
[[email protected] ~]# rados -p rbd get foo.rbd foo.rbd
[[email protected] ~]# rados -p rbd get rbd_directory rbd_directory
[[email protected] ~]# hexdump -vC foo.rbd
00000000 3c 3c 3c 20 52 61 64 6f 73 20 42 6c 6f 63 6b 20 |<<< Rados Block |
00000010 44 65 76 69 63 65 20 49 6d 61 67 65 20 3e 3e 3e |Device Image >>>|
00000020 0a 00 00 00 00 00 00 00 72 62 2e 30 2e 31 30 31 |........rb.0.101|
00000030 34 2e 37 34 62 30 64 63 35 31 00 00 00 00 00 00 |4.74b0dc51......|
00000040 52 42 44 00 30 30 31 2e 30 30 35 00 16 00 00 00 |RBD.001.005.....|
[email protected] ~]# hexdump -vC rbd_directory
00000000 00 00 00 00 01 00 00 00 03 00 00 00 66 6f 6f 00 |............foo.|
這時候我們再建立一個RBD叫bar
,再次對比檢視:
[[email protected] ~]# rbd create bar --size 1024
[[email protected] ~]# rados -p rbd ls
bar.rbd
foo.rbd
rbd_directory
[[email protected] ~]# rados -p rbd get rbd_directory rbd_directory
[[email protected] ~]# hexdump -vC rbd_directory
00000000 00 00 00 00 02 00 00 00 03 00 00 00 62 61 72 00 |............bar.|
00000010 00 00 00 03 00 00 00 66 6f 6f 00 00 00 00 |.......foo....|
多出了個bar.rbd
檔案,很容易聯想到這個檔案的內容是和foo.rbd
內容類似的,唯一不同的是儲存了各自的block_name_prefix
。然後,rbd_directory
裡面多出了bar
這個塊名字。可以得出以下的推論:
每個塊(RBD)剛建立(format 1)時都會生成一個rbdName.rbd
這樣的檔案(ceph裡的物件),裡面儲存了這個塊的prefix
。同時,rbd_directory
會增加剛剛的建立的rbdName
,顧名思義這個檔案就是這個pool裡面的所有RBD的索引。
為了簡單試驗,刪掉剛剛的bar
只留下foo
:
[[email protected] ~]# rbd rm bar
Removing image: 100% complete...done.
RBD使用
建好了塊,我們就開始使用這個塊了:
[[email protected] ~]# rbd map foo
/dev/rbd0
[[email protected] ~]# mkfs.xfs /dev/rbd0
meta-data=/dev/rbd0 isize=256 agcount=9, agsize=31744 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=1024 swidth=1024 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=8 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[[email protected] ~]# mkdir /foo
[[email protected] ~]# mount /dev/rbd0 /foo/
[[email protected] ~]# df -h
檔案系統 容量 已用 可用 已用% 掛載點
/dev/vda1 40G 7.0G 31G 19% /
...
/dev/rbd0 1014M 33M 982M 4% /foo
我喜歡記點東西,比如上面的33M
就是剛格式化完的xfs
系統的大小,算是一個特點吧。
先別急著用,叢集發生了點變化,觀察下:
[[email protected] ~]# ceph -s
pgmap v44: 64 pgs, 1 pools, 14624 KB data, 15 objects
[[email protected] ~]# rados -p rbd ls |sort
foo.rbd
rb.0.1014.74b0dc51.000000000000
rb.0.1014.74b0dc51.000000000001
rb.0.1014.74b0dc51.00000000001f
rb.0.1014.74b0dc51.00000000003e
rb.0.1014.74b0dc51.00000000005d
rb.0.1014.74b0dc51.00000000007c
rb.0.1014.74b0dc51.00000000007d
rb.0.1014.74b0dc51.00000000007e
rb.0.1014.74b0dc51.00000000009b
rb.0.1014.74b0dc51.0000000000ba
rb.0.1014.74b0dc51.0000000000d9
rb.0.1014.74b0dc51.0000000000f8
rb.0.1014.74b0dc51.0000000000ff
rbd_directory
比剛剛多了13個檔案,而且特別整齊還!觀察這些檔案的字尾,可以發現,字尾是以16進位制進行編碼的,那麼從0x00 -> 0xff
是多大呢,就是十進位制的256
,這個數字是不是很眼熟:
size 1024 MB in 256 objects
可是這裡只有13個檔案,並沒有256個啊,這就是RBD的精簡置備
的一個驗證,剛剛建立foo
的時候,一個都沒有呢,而這裡多出的13個,是因為剛剛格式化成xfs
時生成的。我們著重關注索引值為0x00 & 0x01
這兩個碎片檔案(Ceph Object):
[[email protected] ~]# rados -p rbd get rb.0.1014.74b0dc51.000000000000 rb.0.1014.74b0dc51.000000000000
[[email protected] ~]# rados -p rbd get rb.0.1014.74b0dc51.000000000001 rb.0.1014.74b0dc51.000000000001
[[email protected] ~]# hexdump -vC rb.0.1014.74b0dc51.000000000000|more
00000000 58 46 53 42 00 00 10 00 00 00 00 00 00 04 00 00 |XFSB............|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 c5 79 ca f7 fc 5d 48 2d 81 5e 4c 75 29 3c 90 d3 |.y...]H-.^Lu)<..|
...
[[email protected] ~]# ll rb.* -h
-rw-r--r-- 1 root root 128K 10月 12 19:10 rb.0.1014.74b0dc51.000000000000
-rw-r--r-- 1 root root 16K 10月 12 19:10 rb.0.1014.74b0dc51.000000000001
[[email protected] ~]# file rb.0.1014.74b0dc51.000000000000
rb.0.1014.74b0dc51.000000000000: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)
[[email protected] ~]# rbd export foo hahahaha
Exporting image: 100% complete...done.
[[email protected] ~]# file hahahaha
hahahaha: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)
[[email protected] ~]# hexdump -vC rb.0.1014.74b0dc51.000000000001
00000000 49 4e 41 ed 02 01 00 00 00 00 00 00 00 00 00 00 |INA.............|
00000010 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 57 fe 15 be 0b cb a3 58 |........W......X|
00000030 57 fe 15 be 0b cb a3 58 00 00 00 00 00 00 00 06 |W......X........|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
...............太長了自己看~
[[email protected] ~]# hexdump -vC rb.0.1014.74b0dc51.000000000001|grep IN |wc -l
64
這裡的每一行輸出都是很值得思考的,首先我們匯出剛剛提到的兩個物件,檢視第一個物件,開頭就是XFSB
,可以驗證這是剛剛mkfs.xfs
留下來的,這時候檢視檔案大小,發現並沒有4M那麼大,別擔心一會會變大的,值得關注的是file
第0x00個物件,輸出居然是XFS filesystem data
,進一步驗證了剛剛mkfs.xfs
的足跡,這和整個塊的file
資訊是一樣的,我猜測xfs
把檔案系統核心資訊就儲存在塊裝置的最最前面的128KB。而後面的第0x01個物件裡面的IN
輸出是64,我不負責任得猜想這個可能是傳說中的inode
。拋去猜想這裡給到的結論是:
在使用塊裝置的容量後,會按需生成對應的物件,這些物件的共同點是:命名遵循 block_name_prefix+index
, index
range from [0x00, 0xff],而這個區間的大小正好是所有物件數的總和。
現在讓我們把foo
塞滿:
[[email protected] ~]# dd if=/dev/zero of=/foo/full-me
dd: 正在寫入"/foo/full-me": 裝置上沒有空間
記錄了2010449+0 的讀入
記錄了2010448+0 的寫出
1029349376位元組(1.0 GB)已複製,37.9477 秒,27.1 MB/秒
[[email protected] ~]# ceph -s
pgmap v81: 64 pgs, 1 pools, 994 MB data, 258 objects
10500 MB used, 27623 MB / 40188 MB avail
這裡寫了將近1G的資料,重點在後面的258 objects
,如果理解了前面說的內容,這258個物件自然是由rbd_directoy
和foo.rbd
還有256個prefix+index
物件構成的,因為我們用完了這個塊的所有容量,所以自然就生成了所有的256的小4M物件。
寫入檔案
我們把環境恢復到foo
被填滿的上一步,也就是剛剛mkfs.xfs
和mount /dev/rbd0 /foo
這裡。向這個塊裡面寫入檔案:
[[email protected] ~]# echo '111111111111111111111111111111111111111111' > /foo/file1.txt
[[email protected] ~]# echo '222222222222222222222222222222222222222222' > /foo/file2.txt
[[email protected] ~]# echo '333333333333333333333333333333333333333333' > /foo/file3.txt
[[email protected] ~]# rados -p rbd get rb.0.106a.74b0dc51.000000000001 rb.0.106a.74b0dc51.000000000001
這裡我之所以只匯出了0x01
這個物件,是因為我之前已經匯出過所有的物件,經過對比後發現,在寫入檔案之後,只有這個檔案的大小增大了diff
之後,很快找到了寫入的內容。
[[email protected] ~]# hexdump -vC rb.0.106a.74b0dc51.000000000001
00000000 49 4e 41 ed 02 01 00 00 00 00 00 00 00 00 00 00 |INA.............|
00000010 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 01 |................|
00000020 00 00 00 00 00 00 00 00 57 fe 25 2f 32 6c 64 83 |........W.%/2ld.|
00000030 57 fe 25 2f 32 6c 64 83 00 00 00 00 00 00 00 36 |W.%/2ld........6|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 ff ff ff ff 03 00 00 00 40 00 09 00 30 66 69 6c |[email protected]|
00000070 65 31 2e 74 78 74 00 00 40 03 09 00 48 66 69 6c |[email protected]|
00000080 65 32 2e 74 78 74 00 00 40 04 09 00 60 66 69 6c |[email protected]`fil|
00000090 65 33 2e 74 78 74 00 00 40 05 00 00 00 00 00 00 |[email protected]|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
...
00004000 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 |1111111111111111|
00004010 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 |1111111111111111|
00004020 31 31 31 31 31 31 31 31 31 31 0a 00 00 00 00 00 |1111111111......|
00004030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
...
00005000 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 |2222222222222222|
00005010 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 |2222222222222222|
00005020 32 32 32 32 32 32 32 32 32 32 0a 00 00 00 00 00 |2222222222......|
00005030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
...
00006000 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 |3333333333333333|
00006010 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 |3333333333333333|
00006020 33 33 33 33 33 33 33 33 33 33 0a 00 00 00 00 00 |3333333333......|
00006030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
這裡我們找到了檔名和檔案的內容,這很xfs
!因為是xfs
將這些檔案和他們的內容組織成這樣的格式的,再關注下每一行前面的編號,這裡同樣是16進位制編碼,如果之前我對IN == inode
的猜測是對的話,所有的inode
即IN
都出現在索引範圍為[0x00000000, 0x00004000)
的區間,這個0x00004000
的單位是byte
轉換過來就是16KB
,這個小4M內的所有的inode
都儲存在前16KB區間。而檔案出現的第一個索引為0x00004000
,第二個在0x00005000
,第三個在0x00006000
,之間相差了0x1000 bytes
也就是4096 bytes == 4KB
,還記得mkfs.xfs
時的輸出嗎:
[[email protected] ~]# mkfs.xfs /dev/rbd1
meta-data=/dev/rbd1 isize=256 agcount=9, agsize=31744 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=1024 swidth=1024 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=8 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
也就是這裡的bsize = 4096
使得檔案之間間隔了4KB,很抱歉我的xfs
知識還是一片空白,所以這裡很多東西都靠猜,等我補完這一課會回來再做更正的。所以這裡我們的結論就是:
RBD其實是一個完完整整的塊裝置,如果把1G的塊想成一個1024層樓的高樓的話,xfs
可以想象成住在這個大樓裡的樓管,它只能在大樓裡面,也就只能看到這1024層的房子,樓管自然可以安排所有的住戶(檔案or檔名),住在哪一層哪一間,睡在地板還是天花板(檔案偏移量),隔壁的樓管叫做ext4
,雖然住在一模一樣的大樓裡(foo
or bar
),但是它們有著自己的安排策略,這就是檔案系統如果組織檔案的一個比喻了,我們就不做深究,明白到這裡就好了。然並卵,拆遷大隊長跑來說,我不管你們(xfs
orext4
)是怎麼安排的,蓋這麼高的樓是想上天了?,然後大隊長把這1024層房子,每4層(4MB)砍了一刀,一共砍成了256個四層,然後一起打包帶走了,運到了一個叫做Ceph
的小區裡面,放眼望去,這個小區裡面的房子最高也就四層(填滿的),有的才打了地基(還沒寫內容)。。。
這一節最主要的目的就是說明,在Ceph眼裡,它並不關心這個RBD是做什麼用處的,統統一刀斬成4M大小的物件,而使用這個RBD的使用者(比如xfs
),它只能從RBD裡面操作,它可能將一個大檔案從三樓寫到了五樓,但是Ceph不管,直接從四樓砍一刀,檔案分了就分了,反正每個小四層都有自己的編號(index),不會真的把檔案給丟了。
最後再來個小操作(4210688=0x405000):
[[email protected] ~]# cat /foo/file2.txt
222222222222222222222222222222222222222222
[[email protected] ~]# echo Ceph>Ceph
[[email protected] ~]# dd if=Ceph of=/dev/rbd0 seek=4210688 oflag=seek_bytes
記錄了0+1 的讀入
記錄了0+1 的寫出
5位元組(5 B)已複製,0.0136203 秒,0.4 kB/秒
[[email protected] ~]# hexdump -Cv /dev/rbd0 -n 100 -s 0x405000
00405000 43 65 70 68 0a 32 32 32 32 32 32 32 32 32 32 32 |Ceph.22222222222|
00405010 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 |2222222222222222|
00405020 32 32 32 32 32 32 32 32 32 32 0a 00 00 00 00 00 |2222222222......|
00405030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
[[email protected] ~]# cat /foo/file2.txt
Ceph
2222222222222222222222222222222222222
AMAZING!,至少我是這麼覺得的,我們通過檢視index
為0x01
的小4M檔案,得知了file2.txt
這個檔案內容在這個小4M內儲存的位置為0x5000
,因為0x01
前面還有一個小4M檔案即0x00
,那麼這個file2.txt
在整個RBD內的偏移量為4MB+0x5000B=0x400,000B+0x5000B=0x405000B=4210688B
,也就是說儲存在/dev/rbd0
的偏移量為0x405000
的位置,這時候用dd
工具,直接向這個位置寫入一個Ceph
,再檢視file2.txt
的內容,果然,被修改了!
RBD組裝
受到這篇文章啟發,我們開始組裝一個RBD,所謂組裝,就是把剛剛的13個小4M碎片從叢集中取出來,然後利用這13個檔案,重建出一個1G的RBD塊,這裡的實驗環境沒有那篇文章裡面那麼苛刻,因為叢集還是能訪問的,不像文章裡提到的叢集已死,不能執行ceph指令,需要從OSD裡面把碎片檔案一個個撈出來。
一點思考: 使用
find .
這種方法太慢了,有一個事實是,可以從任何一個dead OSD
匯出這個叢集的CRUSHMAP,我有一個未證實的猜想,能否將這個CRUSHMAP注入到一個活的叢集,然後這兩個叢集的ceph osd map <pool> <object>
的輸出如果一樣的話:
live
叢集:ceph osd map <pool> foo.rbd
,得到塊名所儲存的位置,前往dead
叢集找到之。
dead
叢集: 讀取foo.rbd
檔案讀取prefix
。希望你還能記得這個塊的大小。
live
叢集: 做個迴圈,讀取ceph osd map <pool> prefix+index[0x00,Max_index]
的輸出,可以獲取在dead
叢集的某個OSD的某個PG下面,這樣就可以直接定位而不需要從find .
結果來過濾了。只是猜想,未證實,這兩天證實過再回來訂正。
我們很快就可以把那13個檔案拿出來了,現在開始組裝:
[[email protected] rbd]# ll
總用量 14636
-rw-r--r-- 1 root root 131072 10月 13 11:35 rb.0.1078.74b0dc51.000000000000
-rw-r--r-- 1 root root 28672 10月 13 11:35 rb.0.1078.74b0dc51.000000000001
-rw-r--r-- 1 root root 16384 10月 13 11:35 rb.0.1078.74b0dc51.00000000001f
-rw-r--r-- 1 root root 16384 10月 13 11:35 rb.0.1078.74b0dc51.00000000003e
-rw-r--r-- 1 root root 16384 10月 13 11:35 rb.0.1078.74b0dc51.00000000005d
-rw-r--r-- 1 root root 4194304 10月 13 11:36 rb.0.1078.74b0dc51.00000000007c
-rw-r--r-- 1 root root 4194304 10月 13 11:36 rb.0.1078.74b0dc51.00000000007d
-rw-r--r-- 1 root root 2129920 10月 13 11:36 rb.0.1078.74b0dc51.00000000007e
-rw-r--r-- 1 root root 16384 10月 13 11:36 rb.0.1078.74b0dc51.00000000009b
-rw-r--r-- 1 root root 16384 10月 13 11:36 rb.0.1078.74b0dc51.0000000000ba
-rw-r--r-- 1 root root 16384 10月 13 11:36 rb.0.1078.74b0dc51.0000000000d9
-rw-r--r-- 1 root root 16384 10月 13 11:36 rb.0.1078.74b0dc51.0000000000f8
-rw-r--r-- 1 root root 4194304 10月 13 11:36 rb.0.1078.74b0dc51.0000000000ff
組裝的基本思想就是,先搭建一個1024層的大樓,然後,把剛剛的13個四層根據它的index
,安插到對應的樓層,缺少的樓層就空在那就好了,指令碼來自剛剛的文章,我對其進行了一小部分的修改,使之適合我們這個實驗,指令碼將輸出一個名為foo
的塊:
#!/bin/sh
# Rados object size 這是剛剛的4M的大小
obj_size=4194304
# DD bs value
rebuild_block_size=512
#rbd="${1}"
rbd="foo" #生成的塊名
#base="${2}" #prefix
base="rb.0.1078.74b0dc51"
#rbd_size="${3}" #1G
rbd_size="1073741824"
base_files=$(ls -1 ${base}.* 2>/dev/null | wc -l | awk '{print $1}')
if [ ${base_files} -lt 1 ]; then
echo "COULD NOT FIND FILES FOR ${base} IN $(pwd)"
exit
fi
# Create full size sparse image. Could use truncate, but wanted
# as few required files and dd what a must.
dd if=/dev/zero of=${rbd} bs=1 count=0 seek=${rbd_size} 2>/dev/null
for file_name in $(ls -1 ${base}.* 2>/dev/null); do
seek_loc=$(echo ${file_name} | awk -F_ '{print $1}' | awk -v os=${obj_size} -v rs=${rebuild_block_size} -F. '{print os*strtonum("0x" $NF)/rs}')
dd conv=notrunc if=${file_name} of=${rbd} seek=${seek_loc} bs=${rebuild_block_size} 2>/dev/null
done
從上面的指令碼就可以看出,這是一個填樓工程,將其填完之後,我們來看得到的foo
檔案:
[[email protected] rbd]# file foo
foo: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)
[[email protected] rbd]# du -sh foo
15M foo
[[email protected] rbd]# ll -h foo
-rw-r--r-- 1 root root 1.0G 10月 13 12:26 foo
這時候,我們掛載會出現一個小問題,uuid重複:
[[email protected] rbd]# mount foo /mnt
mount: 檔案系統型別錯誤、選項錯誤、/dev/loop0 上有壞超級塊、
缺少內碼表或助手程式,或其他錯誤
有些情況下在 syslog 中可以找到一些有用資訊- 請嘗試
dmesg | tail 這樣的命令看看。
[[email protected] rbd]# dmesg |tail
[3270374.155472] XFS (loop0): Filesystem has duplicate UUID 1c4b010c-a2d8-4615-8307-be5419d94add - can't mount
原因很簡單,還記得我們剛剛操作時的mount /dev/rbd0 /foo
嗎? foo
塊是/dev/rbd0
的克隆,所以foo
的UUID
是和/dev/rbd0
的是一樣的,這時候我們umount /foo
即可:
[[email protected] rbd]# umount /foo/
[[email protected] rbd]# mount foo /mnt
[[email protected] rbd]# ls /mnt/
file1.txt file2.txt file3.txt
[[email protected] rbd]# cat /mnt/file2.txt
Ceph
2222222222222222222222222222222222222
神奇吧,我們用碎片檔案組裝了一個完完整整的RBD塊,能和Ceph裡map出來的RBD一樣使用,並且資料也是一樣的,相信如果理解了前幾節的內容,對這個實驗的結果就不會很意外了。