您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Ceph基礎數(shù)據(jù)結構有哪些”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Ceph基礎數(shù)據(jù)結構有哪些”這篇文章吧。
Pool 的概念前面講過了,Ceph 支持豐富的對 Pool 的操作,主要的包括:
列表、創(chuàng)建和刪除 pool ceph osd pool create {pool-name} {pg-num} [{pgp-num}] [replicated] [crush-ruleset-name] ceph osd pool create {pool-name} {pg-num} {pgp-num} erasure [erasure-code-profile] [crush-ruleset-name] ceph osd pool delete {pool-name} [{pool-name} --yes-i-really-really-mean-it] QoS 支持: ceph osd pool set-quota {pool-name} [max_objects {obj-count}] [max_bytes {bytes}] 快照創(chuàng)建和刪除: ceph osd pool mksnap {pool-name} {snap-name} ceph osd pool rmsnap {pool-name} {snap-name} 元數(shù)據(jù)修改 ceph osd pool set {pool-name} {key} {value} 設置對象拷貝份數(shù)(注意該份數(shù)包括對象自身) ceph osd pool set {poolname} size {num-replicas} 在 degraded 模式下的拷貝份數(shù) ceph osd pool set data min_size 2
Image 對應于 LVM 的 Logical Volume,它將被條帶化為 N 個子數(shù)據(jù)塊,每個數(shù)據(jù)塊將會被以對象(object)形式保存在 RADOS 對象存儲中的簡單塊設備(simple block devicees)。比如:
#創(chuàng)建 100 GB 大小的名字為 ‘myimage’ 的 RBD Image,默認情況下,它被條帶化為 4MB 大小的 25 個對象
rbd create mypool/myimage --size 102400 #同樣是 100MB 大小的 RBD Image,但是它被被條帶化為 8MB 大小的13 個對象 rbd create mypool/myimage --size 102400 --order 23
#將 image mount 到linux 主機稱為一個 deivce /dev/rbd1
rbd map mypool/myimage
#向 /dev/rbd1 寫入數(shù)據(jù)
dd if=/dev/zero of=/dev/rbd1 bs=1047586 count=4 #刪除 image rbd rm mypool/myimage
接下來我們來看看 image 的一些內(nèi)部信息。
(1)創(chuàng)建新的對象
首先在一個空的 pool 中創(chuàng)建一個 100 GB 的 image
root@ceph2:~# rbd create -p pool100 image1 --size 102400 --image-format 2root@ceph2:~# rbd list pool100 image1
這時候在 pool 中看到多了一些 object:
root@ceph2:~# rados -p pool100 ls rbd_directory rbd_id.image1 rbd_header.a89c2ae8944a
從名字也能看出來,這些 object 存放的不是 image 的數(shù)據(jù),而是 ID,header 之類的元數(shù)據(jù)信息。其中,rbd_directory 中保存了image 的所有 ID 和 name 信息:
root@ceph2:~# rados -p pool100 listomapvals rbd_directory id_a89c2ae8944a value: (10 bytes) : 0000 : 06 00 00 00 69 6d 61 67 65 31 : ....image1 name_image1 value: (16 bytes) : 0000 : 0c 00 00 00 61 38 39 63 32 61 65 38 39 34 34 61 : ....a89c2ae8944a
而 rbd_header 保存的是 Image 的元數(shù)據(jù):
root@ceph2:~# rados -p pool100 listomapvals rbd_header.a89c2ae8944a features value: (8 bytes) : 0000 : 01 00 00 00 00 00 00 00 : ........ object_prefix value: (25 bytes) : 0000 : 15 00 00 00 72 62 64 5f 64 61 74 61 2e 61 38 39 : ....rbd_data.a89 0010 : 63 32 61 65 38 39 34 34 61 : c2ae8944a order value: (1 bytes) : 0000 : 16 : . size value: (8 bytes) : 0000 : 00 00 00 00 19 00 00 00 : ........ snap_seq value: (8 bytes) : 0000 : 00 00 00 00 00 00 00 00 : ........
這些信息正是下面命令的信息來源:
root@ceph2:~# rbd -p pool100 info image1 rbd image 'image1': size 102400 MB in 25600 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.a89c2ae8944a format: 2 features: layering
同時還能看出來,該 image 的數(shù)據(jù)對象的名稱前綴是 rbd_header.a89c2ae8944a。而對于一個新建的 image,因為沒有數(shù)據(jù)對象,其實際占用的存儲空間只是元數(shù)據(jù)對象所占的非常小的空間。
(2)向該對象中寫入數(shù)據(jù) 8MB 的數(shù)據(jù)(該 pool 中一個 object 是 4MB)
root@ceph2:~# rbd map pool100/image1
root@ceph2:~# rbd showmapped id pool image snap device 1 pool100 image1 - /dev/rbd1
root@ceph2:~# dd if=/dev/zero of=/dev/rbd1 bs=1048576 count=8 8+0 records in 8+0 records out 8388608 bytes (8.4 MB) copied, 0.316369 s, 26.5 MB/s
在來看看 pool 中的對象:
root@ceph2:~# rados -p pool100 ls rbd_directory rbd_id.image1rbd_data.a89c2ae8944a.0000000000000000 rbd_data.a89c2ae8944a.0000000000000001 rbd_header.a89c2ae8944a
可以看出來多了 2 個 4MB 的 object。繼續(xù)看第一個對象所在的 OSD:
root@ceph2:~# ceph osd map pool100 rbd_data.a89c2ae8944a.0000000000000000osdmap e81 pool 'pool100' (7) object 'rbd_data.a89c2ae8944a.0000000000000000' -> pg 7.df059252 (7.52) -> up ([8,6,7], p8) acting ([8,6,7], p8)
PG 的 ID 是 7.52,主 OSD 是 8,從 OSD 是 6 和 7。查看 OSD 8 所在的節(jié)點為 ceph4:
root@ceph4:/data/osd2/current/7.52_head# ceph osd tree # id weight type name up/down reweight -1 0.1399 root default -4 0.03998 host ceph4 5 0.01999 osd.5 up 1 8 0.01999 osd.8 up 1
登錄 ceph4,查看 /var/lib/ceph/osd 目錄,能看到 ceph-8 目錄:
root@ceph4:/var/lib/ceph/osd# ls -l total 0 lrwxrwxrwx 1 root root 9 Sep 18 02:59 ceph-5 -> /data/osd lrwxrwxrwx 1 root root 10 Sep 18 08:22 ceph-8 -> /data/osd2
查看 7.52 開頭的目錄,可以看到兩個數(shù)據(jù)文件:
root@ceph4:/data/osd2/current# find . -name '*a89c2ae8944a*'./7.5c_head/rbd\uheader.a89c2ae8944a__head_36B2DADC__7 ./7.52_head/rbd\udata.a89c2ae8944a.0000000000000001__head_9C6139D2__7 ./7.52_head/rbd\udata.a89c2ae8944a.0000000000000000__head_DF059252__7
可見:
(1) RBD image 是簡單的塊設備,可以直接被 mount 到主機,成為一個 device,用戶可以直接寫入二進制數(shù)據(jù)。
(2)image 的數(shù)據(jù)被保存為若干在 RADOS 對象存儲中的 data objects。
(3)image 的數(shù)據(jù)空間是 thin provision 的,意味著ceph 不預分配空間,而是等到實際寫入數(shù)據(jù)時按照 object 分配空間。
(4)每個 data object 被保存為多份。
RBD image 的快照(snapshot)是該 image 在特定時刻的狀態(tài)的一份只讀拷貝 (A snapshot is a read-only copy of the state of an image at a particular point in time.)。需要注意的是,在做 snapshot 之前,需要停止 I/O;如果 image 中包含文件系統(tǒng),系統(tǒng)確保文件系統(tǒng)是處于連續(xù)狀態(tài)。
用戶可以使用 rbd 工具或者其它 API 操作 snapshot:
rbd create -p pool101 --size 102400 image1 --format 2 #創(chuàng)建 image
rbd snap create pool101/image1@snap1 #創(chuàng)建snapshotrbd snap ls pool101/image1 #列表 rbd snap protect pool101/image1@snap1 #保護 rbd snap unprotect pool101/image1@snap1 #去保護 rbd snap rollback pool101/image1@snap1 #回滾snapshot 到 image。注意這是個耗時操作,rbd 會顯示進度條 rbd snap rm pool101/image1@snap1 #刪除
rbd snap purge pool101/image1 #刪除 image 的所有snapshot
rbd clone pool101/image1@snap1 image1snap1clone1 #創(chuàng)建 clone
rbd children pool101/image1@snap1 #列表它的所有 clone
我們也來看看 snapshot 的內(nèi)部原理。
(1)創(chuàng)建 image1,寫入 4MB 的數(shù)據(jù),然后創(chuàng)建一個 snapshot: rbd snap create pool100/image1@snap1
(2)Ceph 在該 pool 中沒有創(chuàng)建新的的對象,也就是說這時候并沒有分配存儲空間來給 snap1 創(chuàng)建 data objects。
root@ceph2:~# rbd map pool101/image1
root@ceph2:~# rbd showmapped
id pool image snap device
1 pool100 image1 - /dev/rbd1
2 pool101 image1 - /dev/rbd2
root@ceph2:~# dd if=/dev/sda1 of=/dev/rbd2 bs=1048576 count=4
4+0 records in
4+0 records out
4194304 bytes (4.2 MB) copied, 0.123617 s, 33.9 MB/s
root@ceph2:~# rados -p pool101 ls
rbd_directory
rb.0.fc9d.238e1f29.000000000000
image1.rbd
root@ceph2:~# rbd snap create pool101/image1@snap1
root@ceph2:~# rbd snap ls pool101/image1
SNAPID NAME SIZE
10 snap1 102400 MB
root@ceph2:~# rados -p pool101 ls
rbd_directory
rb.0.fc9d.238e1f29.000000000000
image1.rbd
(3)Ceph 而是將 snapshot 的信息增加到了 rbd_header.{image_id} 對象中
root@ceph2:~# rados -p pool101 listomapvals rbd_header.a9262ae8944a
snapshot_0000000000000006
value: (74 bytes) :
0000 : 03 01 44 00 00 00 06 00 00 00 00 00 00 00 05 00 : ..D.............
0010 : 00 00 73 6e 61 70 31 00 00 00 00 19 00 00 00 01 : ..snap1.........
0020 : 00 00 00 00 00 00 00 01 01 1c 00 00 00 ff ff ff : ................
0030 : ff ff ff ff ff 00 00 00 00 fe ff ff ff ff ff ff : ................
0040 : ff 00 00 00 00 00 00 00 00 00 : ..........
(4)再向 image1 中寫入 4MB 數(shù)據(jù)(其實是覆蓋第一個 object 中的數(shù)據(jù)),發(fā)現(xiàn)數(shù)據(jù)目錄中多了一個 4MB 的文件:
root@ceph4:/data/osd2/current/8.2c_head# ls /data/osd/current/8.3e_head/ -l
total 8200
-rw-r--r-- 1 root root 4194304 Sep 28 03:25 rb.0.fc9d.238e1f29.000000000000__a_AE14D5BE__8
-rw-r--r-- 1 root root 4194304 Sep 28 03:25 rb.0.fc9d.238e1f29.000000000000__head_AE14D5BE__8
可見 Ceph 使用 COW (copy on write)方式實現(xiàn) snapshot:在寫入object 之前,將其拷貝出來,作為 snapshot 的 data object,然后繼續(xù)修改 object 中的數(shù)據(jù)。
(5)再執(zhí)行命令 dd if=/dev/sda1 of=/dev/rdb1 bs=1048576 seek=4 count=4 向 image 寫入 [4MB,8MB)的數(shù)據(jù)。該操作創(chuàng)建了第二個 data object。因為這是在做 snapshot 之后創(chuàng)建的,所有它和 snapshot 沒有關系。
(6)再創(chuàng)建一個snapshot,然后修改第二個 data object,這時候第二個 data object 所在的文件夾中多出了 snapshot 的一個 data object 文件:
root@ceph4:/data/osd2/current/8.2c_head# ls /data/osd/current/8.a_head/ -l total 4100 -rw-r--r-- 1 root root 4194304 Sep 28 03:31 rb.0.fc9d.238e1f29.000000000001__head_9C84738A__8 root@ceph4:/data/osd2/current/8.2c_head# ls /data/osd/current/8.a_head/ -l total 8200 -rw-r--r-- 1 root root 4194304 Sep 28 03:35 rb.0.fc9d.238e1f29.000000000001__b_9C84738A__8 -rw-r--r-- 1 root root 4194304 Sep 28 03:35 rb.0.fc9d.238e1f29.000000000001__head_9C84738A__8
因此,
(1)snapshot 的 data objects 是和 image 的 data objects 保存在同一個目錄中。
(2)snapshot 的粒度不是整個 image,而是RADOS 中的 data object。
(3)當 snapshot 創(chuàng)建時,只是在 image 的元數(shù)據(jù)對象中增加少量字節(jié)的元數(shù)據(jù);當 image 的 data objects 被修改(write)時,變修改的 objects 會被拷貝(copy)出來,作為 snapshot 的 data objects。這就是 COW 的含義。
創(chuàng)建 Clone 是將 image 的某一個 Snapshot 的狀態(tài)復制變成一個 image。如 imageA 有一個 Snapshot-1,clone 是根據(jù) ImageA 的 Snapshot-1 克隆得到 imageB。imageB 此時的狀態(tài)與Snapshot-1完全一致,并且擁有 image 的相應能力,其區(qū)別在于 ImageB 此時可寫。
從用戶角度來看,一個 clone 和別的 RBD image 完全一樣。你可以對它做 snapshot、讀/寫、改變大小 等等,總之從用戶角度來說沒什么限制。同時,創(chuàng)建速度很快,這是因為 Ceph 只允許從 snapshot 創(chuàng)建 clone,而 snapshot 一直是只讀的。
rbd clone pool101/image1@snap1 image1snap1clon3 root@ceph2:~# rbd info image1snap1clon3 rbd image 'image1snap1clon3': size 102400 MB in 25600 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.a8f63d1b58ba format: 2 features: layering parent: pool101/image1@snap1 overlap: 102400 MB
從系統(tǒng)角度,clone 也是使用 COW 技術,現(xiàn)在來通過下面的步驟具體了解一下:
(1)創(chuàng)建一個 clone (創(chuàng)建之前,需要 protect snapshot)。你會發(fā)現(xiàn) RADOS 中多了三個object:
root@ceph2:~# rbd clone pool101/image1@snap1 pool101/image1snap1clone1
root@ceph2:~# rbd ls -p pool101
image1
image1snap1clone1
root@ceph2:~# rados -p pool101 ls
rbd_header.89903d1b58ba
rbd_directory
rbd_id.image1snap1clone1
rbd_id.image1
rbd_children
rbd_header.a9532ae8944a
rbd_data.a9532ae8944a.0000000000000000
其中,rbd_children 記錄了父子關系:
root@ceph2:~# rados -p pool101 listomapvals rbd_children
key: (32 bytes):
0000 : 08 00 00 00 00 00 00 00 0c 00 00 00 61 39 35 33 : ............a953
0010 : 32 61 65 38 39 34 34 61 0e 00 00 00 00 00 00 00 : 2ae8944a........
value: (20 bytes) :
0000 : 01 00 00 00 0c 00 00 00 38 39 39 30 33 64 31 62 : ........89903d1b
0010 : 35 38 62 61 : 58ba
相比 rbd_header.a9532ae8944a,rbd_header.89903d1b58ba 只是多了 partent 信息:
parent
value: (46 bytes) :
0000 : 01 01 28 00 00 00 08 00 00 00 00 00 00 00 0c 00 : ..(.............
0010 : 00 00 61 39 35 33 32 61 65 38 39 34 34 61 0e 00 : ..a9532ae8944a..
0020 : 00 00 00 00 00 00 00 00 00 00 19 00 00 00 : ..............
這里父子關系和 rbd children 結果的來源:
root@ceph2:~# rbd children pool101/image1@snap1 pool101/image1snap1clone1
可見,Clone 也是對 snapshot 使用 COW 方式實現(xiàn)的。
(2)從 clone 讀數(shù)據(jù)
從本質(zhì)上是 clone 的 RBD image 中讀數(shù)據(jù),對于不是它自己的 data objects,ceph 會從它的 parent snapshot 上讀,如果它也沒有,繼續(xù)找它的parent image,直到一個 data object 存在。從這個過程也看得出來,該過程是缺乏效率的。
(3)向 clone 中的 object 寫數(shù)據(jù)
Ceph 會首先檢查該 clone image 上的 data object 是否存在。如果不存在,則從 parent snapshot 或者 image 上拷貝該 data object,然后執(zhí)行數(shù)據(jù)寫入操作。這時候,clone 就有自己的 data object 了。
root@ceph3:/data/osd3/current/8.32_head# ls -l total 4100 -rw-r--r-- 1 root root 4194304 Sep 28 05:14 rbd\udata.89903d1b58ba.0000000000000000__head_CEDDC1B2__8
這是增加了 clone 后的各對象之間的關系:
從上面的分析我們知道,克隆操作本質(zhì)上復制了一個 metadata object,而 data objects 是不存在的。因此在每次讀操作時會先向本卷可能的 data object 訪問。在返回對象不存在錯誤后會向父卷訪問對應的對象最終決定這塊數(shù)據(jù)是否存在。因此當存在多個層級的克隆鏈后,讀操作需要更多的損耗去讀上級卷的 data objects。只有當本卷的 data object 存在后(也就是寫操作后),才不需要訪問上級卷。
為了防止父子層數(shù)過多,Ceph 提供了 flattern 函數(shù)將 clone 與 parent snapshot 共享的 data objects 復制到 clone,并刪除父子關系。
rbd 工具的 flatten 方法:
rbd flatten <image-name>: fill clone (image-name) with data of parent (make it independent)
如果一個 image 是個 clone,從它的 parent snapshot 拷貝所有共享的 blocks (data objects),刪除與其 parent 的依賴關系。此時,其 parent snapshot 可以被去保護(unprotected),如果沒有其它的 clone 的話,它是允許被刪除的。 該功能要求 image 為 format 2 格式。
注意這是一個非常耗時的操作。Flatten 之后,clone 與原來的父 snapshot 之間也不再有關系了,真正成為一個獨立的 image:
root@ceph2:~# rbd flatten image1snap1clon2 Image flatten: 100% complete...done. root@ceph2:~# rbd info image1snap1clon2 rbd image 'image1snap1clon2': size 102400 MB in 25600 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.fb173d1b58ba format: 2 features: layering
令人奇怪的是,該操作在parent image 和 clone 產(chǎn)生的 image 的目錄中產(chǎn)生了大量空的文件:
root@ceph2:/data/osd/current# ls /data/osd/current/8.7f_head/ -l total 788 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.000000000000014f__head_17C7607F__8 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.0000000000000232__head_96D143FF__8 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.0000000000000399__head_4D4E557F__8 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.00000000000003ae__head_CE165DFF__8 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.00000000000003e1__head_42EA8A7F__8 -rw-r--r-- 1 root root 0 Sep 28 05:33 rbd\udata.89903d1b58ba.0000000000000445__head_701607FF__8
判斷父子關系層數(shù),達到一定數(shù)目后 flatten clone,在刪除 snapshot 的偽代碼:
img = self.rbd.Image(client.ioctx, img_name) #根據(jù)輸入的 img_name 獲得其 RBD Image 對象
_pool, parent, snap = self._get_clone_info(img_name) #當 name 為 img_name 的 RBD image 是個 clone 時,通過遞歸,獲取它的 parent image 和 parent snapshot
img.flatten() # 將 parent snapshot 的 data 拷貝到該 clone 中
parent_volume = self.rbd.Image(client.ioctx, parent) #獲取 parent image parent_volume.unprotect_snap(snap) #將 snap 去保護 parent_volume.remove_snap(snap) #如果snapshot 沒有其它的 clone,將其刪除
RBD image 的 head,object,snapshot 以及 與 client 和 parent 之間的關系:
以上是“Ceph基礎數(shù)據(jù)結構有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。