ceph块存储特性包括_Ceph块存储客户端架构及流程简析

82ba2c965052174cf54d1d941a4b9fd3.png

Ceph可以提供文件、块和对象三种类型的存储形式,但最为主要的存储形式就是块存储。Ceph块存储可以直接与云计算平台进行对接,比如OpenStack等。另外,Ceph提供了访问块存储的API和内核模块。内核模块解决了通过裸机访问Ceph块存储的问题。本文主要介绍一下用户态块存储客户端的架构和基本的读写流程,后续再详细介绍内核模块客户端的实现。

16ed83b01c162fa456e3327456bed308.png

在介绍客户端实现之前我们有必要介绍一下Ceph块存储实现的基本原理。我们知道块存储(磁盘)在用户端呈现的其实就是一个线性空间,如图2蓝色长条。Ceph的做法是将该空间切割为等长的段,并用对象存储表示,而对象名称就是磁盘的LBA。

ea7954020ca4a5f03c60d90e530860dd.png

比如我们创建了一个1G的块存储,并采用Ceph默认的策略(每4MB用一个对象存储)。那么,如果在磁盘的开头有写数据(比如1KB),客户端就会创建一个4MB的对象,名称格式为image_hash_lba。如图3是一个块存储存储数据的对象的实例,其中红色方框中的内容正是数据的LBA。

5c55e02d6827ba47a7893c4fcd8c64d0.png

总的来说,Ceph的块存储是转换为对象来存储的

Ceph的块存储API

在后续分析块存储架构之前,我们先了解一下客户端的API及使用方法。下面给出一些代码片段,这里并非完整的代码,也没有异常处理,仅仅用于说明基本流程。

/* 访问块存储需要定义的对象 */
librados::Rados rados; /* rados集群 */
librados::IoCtx io_ctx;   /* IO上下文 */
librbd::RBD rbd;          /* 块设备 */
librbd::Image image;   /* 具体的磁盘 */

/* 下面是基本的访问流程 */
/* 集群初始化工作,完成与Rados集群的连接 */
ret = rados.init("admin");
rados.conf_read_file("/etc/ceph/ceph.conf");
rados.connect();
/* 创建一个IO上下文,用于对象级的读写 */
rados.ioctx_create(pool_name, io_ctx);
/* 块设备的访问,构建image,并使用其方法 */
rbd.open(io_ctx, image, image_name);
image.write2(ofs_w, len_w, bl_r, 0);

了解到上述流程后,我们知道与块存储相关的有2个类,分别是RBD和Image。其中RBD是块存储系统相关的类,用于实现块存储相关的管理操作,比如创建删除镜像、创建镜像组和镜像的复制配对等等操作。而Image类则用于具体镜像(磁盘)的操作,比如镜像数据的读写、镜像属性和快照的创建删除等等。

Ceph块存储客户端基本架构

在介绍块存储架构之前,我们先看一下块存储的使用流程。从上面代码可以看到这里核心的有2点,一个是创建一个IO上下文,这个是实现对象级数据读写的,我们在librados中曾经介绍过;另外一个是通过rbd.open打开一个块存储设备,而这里面最为重要的是传入了IO上下文参数(IoCtx)。 如果我们再继续深入介绍之前,我们先看一下rbd.open函数,如下是该函数的源代码(省略了部分不重要的内容)。从代码中可以看出这里的核心是创建了一个ImageCtx对象,并且通过参数传出。而传出的参数就是我们后面需要使用的访问磁盘的对象。同时,这里还需要注意的是构建ImageCtx对象时讲IO上下文传入其中,因此后续的IO操作就可以通过该上下文接口实现。

int RBD::open(IoCtx& io_ctx, Image& image, const char *name,
                const char *snap_name)
  {
    /* 构建一个ImageCtx对象,这里表示一个磁盘设备 */
    ImageCtx *ictx = new ImageCtx(name, "", snap_name, io_ctx, false);
    TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx)); 
    ... ...
    int r = ictx->state->open(false);
    if (r < 0) { 
      tracepoint(librbd, open_image_exit, r);
      return r;
    }    

    image.ctx = (image_ctx_t) ictx;
    tracepoint(librbd, open_image_exit, 0);
    return 0;
  }

对于Ceph块存储客户端可以简单的划分为3层,分别是API接口层、块存储逻辑层和lirados层。当然,实际情况比这个要复杂的多(例如前文librados就包含4层),我们这里为了简化描述,暂且认为只包含这3层。后续,我们将深入介绍没一层。

72f04fc9570692d29ec9ebc3ed14e979.png

结合上述3层架构,我们看一下每层涉及的类。在API层主要包括RBD和Image 2个类,关于这两个类的作用我们在前文已经做过介绍,这里不在赘述。

4316bb00284ba5e7b590ba2d85f98d5e.png

块存储逻辑层最主要的类是ImageCtx类,其中主要包含CephContext、ImageRquestWQ和ObjectDispatcher类。其中ImageCtx类为块设备(Image)上下文类,该类负责处理块设备相关的,核心是实现块设备线性空间到对象存储之间的转换。除此之外,还包括一些高级功能,包括磁盘镜像、快照和磁盘组等。 上述ImageRequestWQ类是一个IO相关的队列类,接口层的异步请求会缓存到该队列中,并通过起内部接口实现IO的发送。而ObjectDispatcher类则负责将转换后的请求(对象请求)发送到RADOS集群中。

写数据的流程浅析

前面了解了RBD的基本架构及涉及的主要类,下面我们以写数据为例介绍一下其主要的流程。写流程的发起是以Image类的write函数开始的。整个调用流程如图4所示。

dda9a99b8386209b4a765adb2fdfc7c0.png

具体细节我们不做介绍,这里需要注意的一点是调用了一个名为file_to_extents的函数,该函数将块设备的IO请求转化为对对象的IO请求。在该函数中,会根据块层IO的偏移和镜像的属性将IO切割为适合进行对象操作的IO序列。并且进一步的交给下层进行具体的处理。 好了,今天先到这里,今天我们介绍了Ceph块存储客户端的基本架构和写数据的流程,并对涉及的类进行了简单的介绍。后续,我们将进一步的深入细节,介绍块存储关键流程的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值