一個塊是一個連續的字節序列(例如一個512字節的連續數據是一個塊)。基於塊的存儲接口通常是旋轉介質,例如磁盤、光盤、軟盤等。塊設備接口的普及使得可以用虛擬的塊設備成為和大容量數據存儲系統交互的接口,如Ceph這樣的系統。

注意:內核模塊可以使用Linux頁緩存。 對於基於librbd的應用,Ceph支持RBD緩存。
Ceph的塊設備可以在為Linux的內核,KVM虛擬機,以及像OpenStack和CloudStack這種使用libvirt的雲計算平台提供高性能和無限可擴展的的存儲。Ceph支持在集群中同時運行Ceph的RADOS網關,Ceph的文件系統和Ceph的塊存儲。
塊設備命令
rbd的命令能夠創建、列出、內省、和刪除塊設備鏡像。你一可以使用其來克隆鏡像,創建快照,回滾快照,查看快照等。跟詳細的信息可以參閱管理RADOS塊設備鏡像
創建一個鏡像
使用鏡像之前,必須在Ceph的存儲集群中創建鏡像。執行下面的命令:
rbd create {鏡像名稱} --size {鏡像大小} --pool {存儲池名稱}
例如,在名為swinmmingpool中創建一個1GB的名字為foo的鏡像:
rbd create foo --size 1024
rbd create bar --size 1024 --pool swimmingpool
你必須首先創建一個存儲池(pool)
列出鏡像
rbd ls
rbd ls {poolname}
獲取鏡像信息
rbd --image {image-name} info
rbd --image {image-name} -p {pool-name} info
改變鏡像大小
rbd resize --image foo --size 2048
刪除鏡像
rbd rm {image-name}
rbd rm {image-name} -p {pool-name}
快照
快照是一個鏡像在某一個特定時間點的只讀拷貝。其中Ceph塊設備的高級功能是能夠創建快照保留鏡像的歷史狀態。Ceph支持快照分層,允許快速克隆鏡像。 Ceph還支持使用RDB和如KVM,libvirt等創建快照。
當做快照時需要停止I/O。如果鏡像包含文件系統,文件系統必須在做快照前保持一致性

基本的快照
創建快照
rbd --pool rbd snap create --snap snapname foo
rbd snap create rbd/foo@snapname
快照回滾
rbd --pool rbd snap rollback --snap snapname foo
rbd snap rollback rbd/foo@snapname
注意:回滾快照就是將當前鏡像的數據用快照重新替換。回滾的執行時間隨着鏡像大小的增加而增加。克隆將會比回滾快照更花時間。
分層快照
Ceph支持創建許多copy-on-write(COW)的克隆快照。 分層快照支持Ceph快設備的客戶端快速創建鏡像。例如,你可能創建了一個虛擬機的鏡像並寫入了一些數據。然后,做一個快照,保護這個快照,按照需要創建許多copy-on-write的克隆。一個快照是只讀的,所以克隆快照語義上的簡化讓克隆的速度很快。

筆記:Parent和Child意味着一個snapshot是parent,克隆鏡像是child。
每一個child存儲着一個與之相關的parent鏡像,能夠讓克隆鏡像打開parent快照並從中讀數據。
一個COW的克隆快照的表現形式是一個Ceph的塊設備。你可以讀、寫、克隆和調整鏡像的大小。對克隆的快照並沒有更多的限制,但是克隆鏡像依賴於一個之前的快照,所以你必須在克隆鏡像之前保護快照。下面的圖表描述了這個過程。
注意 Ceph僅僅支持兩種形式的鏡像。1)通過rbd創建的鏡像。2)不被kernel的rbd模式支持。你必須使用qemu/kvm或者librbd直接通過克隆的方式進行。
制作分層快照
Ceph的分層快設備是一個簡單的過程。你必須首先有一個鏡像、創建一個這個鏡像的快照,保護這個快照。一旦你做完了這三個步驟,你能夠開始克隆快照。

克隆鏡像必須制定一個parent快照,包括這個快照所在的pool ID、image ID和snapshot ID。包含pool ID意味着可以從另外一個pool中克隆快照。
- 鏡像模版: 一種通用的使用分層快照的方法是創建一個主鏡像和一個快照提供克隆的模版。例如,一個用戶可以創建一個Linux發行版的鏡像,安裝完成后生成一個快照。之后對快照進行保護后克隆快照。
- 擴展模版: 一種更為高級的方式制作模版。例如,一個用戶可能克隆了一個鏡像並且安裝了其他軟件(例如數據庫等),之后對這個鏡像做快照。之后這個鏡像又變成了一個新的基本鏡像。
- 模版池: 一種使用分層塊設備的方法是創建一個存儲池包括主鏡像,並進行各種快照擴展,用戶可以以只讀方式訪問這個模版池。
- 鏡像遷移和恢復 還有一種使用分層塊設備的方法就是用於從不同的鏡像池中遷移或者恢復數據
分層快照
克隆鏡像需要訪問parent快照,如果用戶無意中刪除了parent快照,所有的克隆將會無法恢復,所以克隆之前必須重新保護快照。
rbd --pool rbd snap protect --image my-image --snap my-snapshot
rbd snap protect rbd/my-image@my-snapshot
被保護的快照不可以刪除
克隆快照
rbd clone rbd/my-image@my-snapshot rbd/new-image
你可以從一個存儲池克隆快照到另一個存儲池。例如,你可以修復一個只讀的鏡像,並且在一個存儲池做一個快照模版。在另一個存儲池中克隆。
取消保護快照
rbd --pool rbd snap unprotect --image my-image --snap my-snapshot
rbd snap unprotect rbd/my-image@my-snapshot
列出快照的兒子
rbd --pool rbd children --image my-image --snap my-snapshot
rbd children rbd/my-image@my-snapshot
合並鏡像
克隆鏡像存在依賴關系。取消這種依賴關系叫做合並鏡像。合並鏡像花費的時間和鏡像的大小成正比。 要刪除一個快照模版,必須先合並子鏡像。
rbd --pool rbd flatten --image my-image
rbd flatten rbd/my-image
注意:合並的鏡像會占據更多的存儲空間。
在KVM中使用Ceph塊設備
最常見的Ceph的塊設備使用案例包括提供虛擬機設備鏡像。例如,用戶會創建一個主鏡像安裝了操作系統和相關軟件並且已經配置好。之后,用戶創建一個快照。最后通過克隆這個快照使用虛擬機。這種方式可以用來快速部署虛擬機。因為客戶端不需要每次下載整個鏡像。

Ceph的塊設備能夠集成在kvm的虛擬機中。
使用方法
kvm的命令行會指定存儲池的名稱和鏡像的名稱。也可以制定一個快照的名稱。
kvm將會從默認的位置獲取ceph的配置參數(/etc/ceph/$cluter.conf)。
qemu-img {command} [options] rbd:glance-pool/maipo:id=glance:conf=/etc/ceph/ceph.conf
創建鏡像
qemu-img create -f raw rbd:data/foo 10G
重要: RAW格式是RBD原生支持的格式,qcow2和vmdk將會帶來更大的開銷,並且在虛擬機遷移時帶來不安全。
改變大小
qemu-img resize rbd:data/foo 10G
獲取鏡像信息
qemu-img info rbd:data/foo
運行虛擬機
qemu -m 1024 -drive format=raw,file=rbd:data/squeeze
設定緩存選項
qemu -m 1024 -drive format=rbd,file=rbd:data/squeeze,cache=writeback
如果設定了rbd_cache=true,必須設置cache=writeback,否則有數據丟失的風險。沒有設置cache=writeback,kvm將不會發送刷新請求到librbd。
支持丟棄和邊界對齊
在Ceph 0.46和kvm 1.1 以后, Ceph塊設備支持丟棄操作。時就意味着客戶端可以發送TRIM請求讓Ceph塊設備釋放未被使用的空間。這種操作可以通過ext4或者xfs支持。
要支持這個選項,需要這樣運行虛擬機:
qemu -m 1024 -drive format=raw,file=rbd:data/squeeze,id=drive1,if=none -device driver=ide-hd,drive=drive1,discard_granularity=512
注意:必須使用IDE設備,而不能使用virtio,virtio不支持丟棄操作
如果使用libvirt,需要編輯其xml文件:
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<qemu:commandline>
<qemu:arg value='-set'/>
<qemu:arg value='block.scsi0-0-0.discard_granularity=4096'/>
<qemu:arg value='-set'/>
<qemu:arg value='block.scsi0-0-1.discard_granularity=65536'/>
</qemu:commandline>
</domain>
