nova – > libvird – > qemu -> librbd -> ceph -> vilume bacl -> cinder
譬如这边有一个OpenStack实例主机 ansibale-centos7-shanghai-area1.qcow2 ,这个文件被分成4份(a1、a2、a3、a4) 往 osd daemon并发的开始存写实例镜像数据,每个底层的存储只分担到一部分任务,速度快了,其次由原来传统的一块存储盘存写实例镜像数据变成了又现在的四块硬盘来存写,容量的使用上也得到了提升。
假设a1的磁盘出现故障,a2、a3、a4正常,正常情况下,这个实例镜像在a1存储的部分数据就损坏导致了数据不完整。
在Ceph中常用的方案中,设立a1的副本数为3可以保存3份,假设a1底层的存储总共有10TB,能实际使用的就是10TB/3的数据量,造成资源开销很大。假设ansibale-centos7-shanghai-area1.qcow2 分成了4份进行存储,每一份存储下面又关联到存储的副本硬盘,文件寻找的复杂度变成了原来的3倍,一粒沙子丢进海里找个地方进行存储,为了降低这种复杂度,可以将osd daemon (a1-1、a1-2、a1-3)划分成一个PG组,之后的存储读写的任务下发到PGa1、a2、a3、a4组。
一个PGa1收到存储读写任务存放给a1,acting set 一个有序列表的形式,存放了3个osd的编号,编号1负责数据的读写,不需要考虑性能问题,后面两个编号负责数据备份功能的。
在云主机运行实例上/dev/vda1挂载到/opt使用的,这个系统盘是由ceph提供的,/opt的数据是怎么样一步一步写到ceph存储里的呢?
ansibale-centos7-shanghai-area1 数据实际上通过qemu给到librbd进行维护和处理,需要使用块存储,可以通过kernel映射内核的方式(性能极其不稳定)和librbd实现。
块存储怎么实现?
qemu 存放的是文件级别的数据,交给librbd进行切分处理(默认最小单位4M),假设ansibale-centos7-shanghai-area1.qcow2是50G,那么就切分为12800份,文件到底层就是一个二进制,一个二进制被称为一个object,实际上是ceph的存储单位,往ceph里面存。
-
一个object可以存放在多个PG里吗?
不可以,这样会导致一个数据变成了多份,默认一个object只会对应一个PG。 -
两个object可以存放在1个PG里吗?
可以,ceph是一个伪数据平衡。 -
Object和PG对应的关系?
一对多的关系。 -
PG和OSD daemon的对应关系?
多对多关系。
Ceph在部署后如何提供块设备出来提供服务?
在传统的LVM中,先要有底层的硬盘创建物理卷这个过程osd daemon相当于创建osd daemon,做完PV后要做VG创建卷组,ceph中相当于包含了一堆PG,,PG映射了具体的物理设备(osd daemon,具体映射了物理空间),LVM中做VG相当于做了逻辑卷,在ceph中相当于划了一个存储池,若客户端想使用ceph的空间需要手动建存储池,为客户端提供块存储功能服务。
[zhupengfei@ceph-centos7-shanghai-area1 ~]$ sudo ceph osd pool create volumes 128 128 # 通过ceph客户端命令去创建一个pool,制定包含多少个PG,是逻辑单位
注意:ceph存放小文件的效率是不高的,性能会随着底层的OSD数目不断地增大,性能会理论上无限增高,底层OSD越多,则管理的硬盘数量越多。
分析:
实例ansibale-centos7-shanghai-area1.qcow2使用块设备使用50G硬盘空间,对应存储池划分一块逻辑空间,称为一个image,跟LVM非常像,ceph可以在线动态扩容。客户端需要知道pool id 自己位于哪一个存储池,通过调用librbd将完整的文件分成多个部分,一个object对应一个id号,客户端需要pool id 和object id,映射到pg上,客户端用的都是pg,把自己image对应的放到pg里面(因为是多对一,进行推导:object id 做hash ,作取模运算得到一个值,针对pool id 再做一个hash得到一个值,综合得到一个小数值,就是pg id 就找到一个具体的pg),pg通过crush算法保存到crushmap 中,得到osd daemon到达disk硬盘上。
注意:客户端需要链接到monister集群上跟monister集群把crushmap要回来,monister监控通过整个集群的状态(monister 、osd、pg、crushmap),客户端想要使用在数据分块之前会调用 librbd, librbd会调用链接到集群,客户端就能掌握整个集群的状态。