天天看點

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

本系列文章會深入研究 Ceph 以及 Ceph 和 OpenStack 的內建:

  Ceph 作為一個統一的分布式存儲,其一大特色是提供了豐富的程式設計接口。我們來看看下面這張經典的圖:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

其中,librados 是 Ceph 的基礎接口,其它的接口比如 RADOSGW, RBD 和 CephFS 都是基于 librados 實作的。本文試着分析下 Ceph 的各種接口庫和常用的工具。

  Ceph 提供一個消息層協定(messaging layer protocol)使得 ceph 用戶端可以和 Ceph Monitor 以及 Ceph OSD Daemon 互動。librados 就是一個該協定的編碼庫形式的實作。所有的 Ceph clients 要麼使用 librados 要麼使用其封裝的更高層 API 與對象存儲進行互動。比如,librbd 使用 librados 提供 Ceph 用戶端與 RBD 互動 API。

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

librados 是使用 C++ 實作的。它實作了 Ceph 的一個私有協定,使得用戶端可以直接、同步或者異步、并行地和 MON  和 OSD 服務通信,來執行如下操作:

Pool Operations

Snapshots

Read/Write Objects

Create or Remove

Entire Object or Byte Range

Append or Truncate

Create/Set/Get/Remove XATTRs

Create/Set/Get/Remove Key/Value Pairs

Compound operations and dual-ack semantics

librados 于 OSD 互動的示例:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

同時也提供 C, python,Java 和 PHD 語言的綁定。使用它之前,你需要安裝它:

安裝 C/C++ 版本的 librados,比如在 Ubuntu 環境中,運作 sudo apt-get install librados-dev,然後你就會在 /usr/include/rados 目錄中找到C/C++的頭檔案。

使用 Python 版本的 librados,比如在 Ubuntu 環境中,運作 sudo apt-get install python-rados。具體請見 1.1.2 部分。

一個 Ceph client 通過 librados 存放或者讀取資料塊到 Ceph 中,需要經過以下步驟:

Client 調用 librados 連接配接到 Ceph monitor,擷取 Cluster map。

當 client 要讀或者寫資料時,它建立一個與 pool 的 I/O Context。該 pool 關聯有 ruleset,它定義了資料在 Ceph 存儲叢集中是怎麼存放的。

client 通過 I/O Context 提供 object name 給 librados,它使用該 object name 和 cluster map 計算出 PG 和 OSD 來定位到資料的位置。

client 直接和 OSD Deamon 互動來讀或者寫資料。

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

可見,第一步中,ceph client 需要知道 Ceph Minotor 的通路方法,以及使用者的身份資訊,而這些資訊往往是放在 ceph 配置檔案中,比如:

(1)要使用 rados.py 子產品,在你的代碼中 import rados

(2)建立一個 cluster handler,你需要提供 ceph.conf 檔案和 keystring

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

(3)連接配接到 ceph cluster

(4)擷取 ceph cluster 的資訊,以及操作 pool

(5)向 ceph 叢集讀寫資料,需要有一個 I/O Context (ioctx)

(6)然後就可以讀寫資料了

RBD 是  Rados Block Device  的縮寫,而 librbd 是通路 RBD 的庫。它調用 librados C 語言綁定,以及與Linux 核心中的 rbd 子產品通信,來提供 RMD image 的建立、删除、映射和删除映射等操作。其中,建立和删除等操作是調用 librados,而将 RDB Image 映射到主機上則是調用 Linux rbd 核心子產品:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

Open a connection to the rbd pool

Creates an image called test (Removing it before if necessary)

Maps it to a block device on the local host

Creates a snapshot of the image, called test-snap.

Lists and prints the snapshots available.

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

   它隻封裝了 librbd 中的同步操作。它主要提供了 RBD、Image 和 SnapIterator 三個類。在 Ubuntu 上,安裝 python-rbd 包就可以在你的機器上找到該檔案:/usr/lib/python2.7/dist-packages/rbd.py。 提供類似檔案通路的方式去通路 ceph RBD image (連接配接-打開-使用-關閉)。該子產品除了提供主要三個類 Rados, Ioctx, 和Image (Rados 對應于 ceph 叢集;Ioctx 對應于 pool;Image 對應于 RBD Image)以外,還封裝了 librdb 的傳回值作為 Error 類。rbd 子產品還提供 Error 類的具體的子類,比如 PermissionError 和 IOError。

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

更優化的編碼方式:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

class rbd.RBD 該類封裝了 librbd 的 CURD 操作,包括:

create(ioctx, name, size, order=None, old_format=True, features=0, stripe_unit=0, stripe_count=0):建立一個 RBD Image

list(ioctx)  傳回 RBD Image 的名稱清單

clone(p_ioctx, p_name, p_snapname, c_ioctx, c_name, features=0, order=None):克隆 Image 的snapshot 到一個 COW 克隆

features (int) – bitmask of features to enable; if set, must include layering

order (int) – the image is split into (2**order) byte objects

remove(ioctx, name) :删除一個 RBD image。這可能會需要較長的時間,因為它需要等待組成該 image 的每個對象都被删除。

rename(ioctx, src, dest):修改 RBD Image 的名稱

該類的一個執行個體代表一個 RBD image。它的方法用于對 image 的 I/O 操作和處理其 snapshot。它的主要方法包括:

class rbd.Image(ioctx, name, snapshot=None, read_only=False)

copy(dest_ioctx, dest_name) Copy the image to another location.

create_snap(name)  Create a snapshot of the image

flatten()  Flatten clone image (copy all blocks from parent to child)

list_snaps()  Iterate over the snapshots of an image

protect_snap(name) Mark a snapshot as protected. This means it can’t be deleted until it is unprotected.

read(offset, length, fadvise_flags=0)  Read data from the image. 

remove_snap(name)  Delete a snapshot of the image

resize(size)  Change the size of the image

rollback_to_snap(name)  Revert the image to its contents at a snapshot.

set_snap(name)   Set the snapshot to read from. Writes will raise ReadOnlyImage while a snapshot is set. Pass None to unset the snapshot (reads come from the current image) , and allow writing again.

size()  Get the size of the image  in bytes

stat()  Get information about the image.

unprotect_snap(name)   Mark a snapshot unprotected. This allows it to be deleted if it was protected.

write(data, offset, fadvise_flags=0)  Write data to the image.

parent_info  Get information about a cloned image’s parent (if any)

  使用 Ceph 的塊存儲有兩種路徑:

一種是利用QEMU走librbd路徑,主要為虛拟機提供塊儲存設備

另一種是使用 kernel module,走 kernel 的路徑,主要為Host提供塊裝置支援。

  兩種途徑的接口實作不完全相同。就目前來說,前者是目前更穩定的途徑,也是Ceph所有應用場景中最廣泛使用的。網上多篇文章認為目前核心子產品尚不穩定,建議盡量不要使用。

QEMU 通過 librbd 庫通路 RBD,而 librbd 是調用 librados。

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

QEMU 對 librbd 的調用關系可以使用 ldd 指令檢視:

qemu-img 指令支援直接建立 rbd 鏡像,比如:

然後可以使用 virsh 将它定義為一個 device,下面是 device.xml 檔案:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

然後該 device 添加到虛機中即可。虛機通路 RBD 裝置是通過:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

   我們知道,Linux Kernel 中的塊裝置驅動是 virtio_blk,它會對虛機的塊裝置各種請求封裝成一個消息通過 virtio 架構提供的隊列發送到 QEMU 的 IO 線程,QEMU 收到請求後會轉給相應的 QEMU Block Driver 來完成請求,當使用 RDB 時 QEMU block driver 會調用 librbd 來通路 Ceph RDB 裝置。

    rbd 工具也可以調用 Linux RBD 核心子產品來将 RBD Image 挂載到Linux 主機上作為一個新的裝置。一開始,該核心子產品并沒有被加載,但是在執行了 rbd map 操作後,libceph 子產品自動被加載:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

root@compute2:~# lsmod | grep rbd                      #此時,rbd 核心子產品還沒有被加載

root@compute2:~# rbd -n client.cinder map vms/smb01_d1 #做 rbd map 操作

/dev/rbd1

root@compute2:~# lsmod | grep rbd                      #此時, rbd 核心子產品已經被自動加載

rbd 63787 1

libceph 225461 1 rbd

root@compute2:~# rmmod rbd                             #這時候,rbd 核心子產品也無法被解除安裝

rmmod: ERROR: Module rbd is in use

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

在看 rbd 的幫助,我們要可以看到 map,unmap,showmapped 指令确實調用的是 rbd 核心子產品:

過程:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

其實,rbd 是和 /sys/bus/rbd 互動來完成map:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

你甚至可以直接對 /sys/bus/rbd 操作來 map,showmapped 和 unmap RBD Image:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

  Ceph 提供 rbd 作為一個操作 ceph rados 塊裝置(RBD)image 的 工具,根據調用的底層子產品,其功能可分為兩部分:

正常的 create, list, introspect 和 remove block device images,以及 clone images, create snapshots, rollback an image to a snapshot, view a snapshot 等操作,是通過調用 librados 來實作的。其調用層次為 rbd -> librbd -> librados:

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]
了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

将 RBD image map 給 Linux 主機,以及從 Linux 主機 unmap等操作,是通過和 Linux rbd 核心子產品通信來實作的。詳情請參考 1.4.2 部分。

rbd [ -c ceph.conf ] [ -m monaddr ] [ -p | –pool pool ] [ –size size ] [ –order bits ] [ command ... ]

  部分使用示例:

在 pool ‘mypool’ 中建立 100 GB 的 rbd image ‘myimage’:  rbd create mypool/myimage --size 102400

在預設的 ‘rbd’ pool 中建立 image:rbd create myimage --size 102400

建立對象大小為 8MB 的 image:rbd create mypool/myimage --size 102400 --order 23

這裡的 order 參數比較特别,它和 ceph 的對象條帶化有關。ceph 用戶端的一個資料塊,會被條帶化成多個小的對象,被儲存在 Ceph 分布式對象存儲(RADOS) 中。這樣的話,對 image 的讀和寫操作可以被分散到叢集的多個節點上,通常來講這樣可以防止某個 image 非常大或者非常忙時單個節點稱為性能瓶頸。

Ceph 的條帶化行為受三個參數控制:

order:被條帶化的對象的大小為 2^[order] bytes。預設的 oder 為 22,這時候對象大小為4MB。

stripe_unit:每個 [stripe_unit]的連續位元組會被相連的儲存到同一個對象中,直到去寫下一個對象

stripe_count:在寫入了 [stripe_unit] 位元組到 [stripe_unit]各對象後,ceph 又重新從第一個對象開始寫下一個條帶,直到該對象達到了它的最大size。這時候,ceph 轉移到下 [stripe_unit] 個對象。

預設的時候,[stripe_unit] 等于 object size;stripe_count 為1. 要設定其他的 [stripe_unit] 值,需要Ceph v0.53 版本及以後版本對 STRIPINGV2 的支援以及使用 format 2 image 格式。 

删除 image:rbd rm mypool/myimage

建立 snapshot:rbd snap create mypool/myimage@mysnap

建立 clone:rbd clone mypool/myimage@mysnap otherpool/cloneimage

檢視snapshot 的所有 clone:rbd children mypool/myimage@mysnap

删除 snapshot:rbd snap rm mypool/myimage@mysnap

将 image map 到 linux 主機:rbd map mypool/myimage 

将 image 從主機上删除 (unmap):rbd unmap /dev/rbd0

了解 OpenStack + Ceph (3):Ceph RBD 接口和工具 [Ceph RBD API and Tools]

<a href="http://www.wzxue.com/rbdcache/" target="_blank">http://www.wzxue.com/rbdcache/</a>

<a href="https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-rbd" target="_blank">https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-rbd</a>

<a href="http://docs.ceph.com/docs/master/rbd/rbd/" target="_blank">http://docs.ceph.com/docs/master/rbd/rbd/</a>

    本文轉自SammyLiu部落格園部落格,原文連結:http://www.cnblogs.com/sammyliu/p/4838139.html,如需轉載請自行聯系原作者