本系列文章會深刻研究 Ceph 以及 Ceph 和 OpenStack 的集成:html
(1)安裝和部署python
(2)Ceph RBD 接口和工具linux
(3)Ceph 物理和邏輯結構git
(4)Ceph 的基礎數據結構github
(6)QEMU-KVM 和 Ceph RBD 的 緩存機制總結ubuntu
(7)Ceph 的基本操做和常見故障排除方法centos
(8)關於Ceph PGsapi
Ceph 做爲一個統一的分佈式存儲,其一大特點是提供了豐富的編程接口。咱們來看看下面這張經典的圖:緩存
其中,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。
librados 是使用 C++ 實現的。它實現了 Ceph 的一個私有協議,使得客戶端能夠直接、同步或者異步、並行地和 MON 和 OSD 服務通訊,來執行以下操做:
librados 於 OSD 交互的示例:
同時也提供 C, python,Java 和 PHD 語言的綁定。使用它以前,你須要安裝它:
一個 Ceph client 經過 librados 存放或者讀取數據塊到 Ceph 中,須要通過如下步驟:
可見,第一步中,ceph client 須要知道 Ceph Minotor 的訪問方法,以及用戶的身份信息,而這些信息每每是放在 ceph 配置文件中,好比:
[global] mon host = 192.168.1.1 keyring = /etc/ceph/ceph.client.admin.keyring
Python rados 模塊是 librados 的 Python 的很薄的封裝,它在 github 上的源文件在 /src/pybind/rados.py, 安裝到 Ubunt 後的源文件在 /usr/lib/python2.7/dist-packages/rados.py。
(1)要使用 rados.py 模塊,在你的代碼中 import rados
(2)建立一個 cluster handler,你須要提供 ceph.conf 文件和 keystring
import rados, sys #Create Handle Examples. 你有多種方式來指定 ceph.conf (1)cluster = rados.Rados(conffile='ceph.conf') #默認路徑的 ceph.conf (2)cluster = rados.Rados(conffile=sys.argv[1]) #指定路徑的 ceph.conf (3)cluster = rados.Rados(conffile = 'ceph.conf', conf = dict (keyring = '/path/to/keyring')) #默認路徑的 ceph.conf 和指定的 keystring
(3)鏈接到 ceph cluster
cluster.connect()
(4)獲取 ceph cluster 的信息,以及操做 pool
cluster_stats = cluster.get_cluster_stats()
pools = cluster.list_pools()
cluster.create_pool('test')
cluster.delete_pool('test')
(5)向 ceph 集羣讀寫數據,須要有一個 I/O Context (ioctx)
ioctx = cluster.open_ioctx('data')
(6)而後就能夠讀寫數據了
ioctx.write_full("hw", "Hello World!") #向 「hw」 object 寫入 "Hello World!" print ioctx.read("hw") #讀取 」hw「 object 的數據 ioctx.remove_object("hw") #刪除 「hw」 object
更多的信息,能夠參考 LIBRADOS (PYTHON)。
RBD 是 Rados Block Device 的縮寫,而 librbd 是訪問 RBD 的庫。它調用 librados C 語言綁定,以及與Linux 內核中的 rbd 模塊通訊,來提供 RMD image 的建立、刪除、映射和刪除映射等操做。其中,建立和刪除等操做是調用 librados,而將 RDB Image 映射到主機上則是調用 Linux rbd 內核模塊:
// MapDevice maps an image to a device on the host. Returns the device path and // any errors. On error, the device path will be blank. func (img *Image) MapDevice() (string, error)
librbd 的源代碼在 https://github.com/contiv/librbd,是使用 Go 語言實現的,調用 librados 的 C 庫以及linux 內核模塊,在 Ubuntu 14 上它的文件在 /usr/lib/x86_64-linux-gnu/librbd.so.1。它支持:
rbd python 模塊 rbd.py 的源代碼在 https://github.com/ceph/ceph/blob/master/src/pybind/rbd.py,它是 librbd 的一個 python 封裝。
def load_librbd(): """ Load the librbd shared library. """ librbd_path = find_library('rbd') if librbd_path: return CDLL(librbd_path) # try harder, find_library() doesn't search LD_LIBRARY_PATH # in addition, it doesn't seem work on centos 6.4 (see e46d2ca067b5) try: return CDLL('librbd.so.1') except OSError as e: raise EnvironmentError("Unable to load librbd: %s" % e)
它只封裝了 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。
#使用 rbd 以前,鏈接到 RADOS,並打開一個 IO context (和特定 pool 相關) cluster = rados.Rados(conffile='my_ceph.conf') cluster.connect() ioctx = cluster.open_ioctx('mypool') #初始化一個 RBD 對象 rbd_inst = rbd.RBD() size = 4 * 1024**3 # 4 GiB #建立 image rbd_inst.create(ioctx, 'myimage', size) #初始化 image 對象 image = rbd.Image(ioctx, 'myimage') #準備 600 個字符的數據 data = 'foo' * 200 #寫入數據 image.write(data, 0) #關閉 image 對象 image.close() #關閉 IO Context ioctx.close() #關閉鏈接 cluster.shutdown()
更優化的編碼方式:
with rados.Rados(conffile='my_ceph.conf') as cluster: with cluster.open_ioctx('mypool') as ioctx: rbd_inst = rbd.RBD() size = 4 * 1024**3 # 4 GiB rbd_inst.create(ioctx, 'myimage', size) with rbd.Image(ioctx, 'myimage') as image: data = 'foo' * 200 image.write(data, 0)
使用 Ceph 的塊存儲有兩種路徑:
兩種途徑的接口實現不徹底相同。就目前來講,前者是目前更穩定的途徑,也是Ceph全部應用場景中最普遍使用的。網上多篇文章認爲目前內核模塊尚不穩定,建議儘可能不要使用。
QEMU 經過 librbd 庫訪問 RBD,而 librbd 是調用 librados。
QEMU 對 librbd 的調用關係可使用 ldd 命令查看:
root@compute1:~# ldd /usr/bin/qemu-system-x86_64 | grep rbd librbd.so.1 => /usr/lib/x86_64-linux-gnu/librbd.so.1 (0x00007f76ef9e8000)
qemu-img 命令支持直接建立 rbd 鏡像,好比:
qemu-img create -f rbd rbd:vmimages/ubuntu-newdrive 2G
而後可使用 virsh 將它定義爲一個 device,下面是 device.xml 文件:
<disk type='network' device='disk'> <driver name='qemu' type='raw'/> <auth username='vmimages'> <secret type='ceph' uuid='76e3a541-b997-58ac-f7bd-77dd7d4347cb'/> </auth> <source protocol='rbd' name='vmimages/ubuntu-newdrive'> <host name='192.168.0.100' port='6789'/> </source> <target dev='vdc' bus='virtio'/> </disk>
而後該 device 添加到虛機中便可。虛機訪問 RBD 設備是經過:
咱們知道,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 模塊自動被加載:
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
在看 rbd 的幫助,咱們要能夠看到 map,unmap,showmapped 命令確實調用的是 rbd 內核模塊:
map <image-name> map image to a block device using the kernel unmap <device> unmap a rbd device that was mapped by the kernel showmapped show the rbd images mapped by the kernel
過程:
#建立一個 RDB Image root@compute1:~# rbd -n client.cinder create vms/smb01_d2 --size 1000 --image-format 2
#將 Image map 給主機
root@compute1:~# rbd -n client.cinder map vms/smb01_d2 /dev/rbd2
#列表已經被映射的 RDB Image
root@compute1:~# rbd showmapped
id pool image snap device
1 vms smb01_d1 - /dev/rbd1
2 vms smb01_d2 - /dev/rbd2
3 vms smb01_d3 - /dev/rbd3
#unmap
root@compute1:~# rbd unmap /dev/rbd1
root@compute1:~# rbd unmap /dev/rbd2
root@compute1:~# rbd unmap /dev/rbd3
其實,rbd 是和 /sys/bus/rbd 交互來完成map:
access("/sys/bus/rbd", F_OK) = 0 socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, 15) = 3 setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\r\0\0\0\0\0\0\0\3000b\261\375\177\0\0", 16) = 0 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000002}, 12) = 0 getsockname(3, {sa_family=AF_NETLINK, pid=6958, groups=00000002}, [12]) = 0 setsockopt(3, SOL_SOCKET, SO_PASSCRED, [1], 4) = 0 open("/sys/bus/rbd/add_single_major", O_WRONLY) = -1 ENOENT (No such file or directory) open("/sys/bus/rbd/add", O_WRONLY) = 4 write(4, "9.115.251.194:6789,9.115.251.195:6789,9.115.251.218:6789 nam"..., 101) = 101 close(4)
你甚至能夠直接對 /sys/bus/rbd 操做來 map,showmapped 和 unmap RBD Image:
root@compute1:~#echo "10.20.30.40 name=admin rbd foo" | sudo tee /sys/bus/rbd/add #map root@compute1:~# ls /sys/bus/rbd/devices #showmapped 1 root@compute1:~# echo 1 | sudo tee /sys/bus/rbd/remove #unmap 1 root@compute1:~# ls /sys/bus/rbd/devices
相信能夠參考 RBD KERNEL OBJECT OPERATIONS 和 這篇文章。
Ceph 提供 rbd 做爲一個操做 ceph rados 塊設備(RBD)image 的 工具,根據調用的底層模塊,其功能可分爲兩部分:
root@compute1:~# which rbd /usr/bin/rbd root@compute1:~# ldd /usr/bin/rbd | grep rbd librbd.so.1 => /usr/lib/x86_64-linux-gnu/librbd.so.1 (0x00007fcf7ae62000) root@compute1:~# ldd /usr/lib/x86_64-linux-gnu/librbd.so.1 | grep rados librados.so.2 => /usr/lib/x86_64-linux-gnu/librados.so.2 (0x00007f29b543f000)
在 Ubuntu 上,你安裝了 ceph-common 就能夠獲得該工具,其命令行格式爲: