美文网首页CephCeph
ceph rbd:nbd原理

ceph rbd:nbd原理

作者: chnmagnus | 来源:发表于2018-03-23 17:42 被阅读141次

    前言

    rbd是ceph提供的块存储服务。主要有几种使用场景:

    • map成块设备直接使用
    • 结合iSCSI使用
    • 结合OpenStack使用

    map成块设备,主要有两种方式:

    经过考察,发现RBD Kernel Module项目更新缓慢,其功能已经远远落后于librbd提供的功能。像striping、object map、exclusive lock等功能均不支持。

    RBD-NBD方式,基于Network Block Device(nbd)实现,并且nbd已经经过了很长时间的实践,稳定性有所保证。对块设备的请求,由nbd间接调用librbd完成,可以支持最新的特性,是比较理想的方式。

    下文将对rbd通过nbd进行读写和map的实现进行介绍。

    nbd

    nbd是一种起源于linux的轻量级块访问协议,可以让你将任何存储方式作为操作系统的块设备来使用。它主要分成两部分,server端和client端。client端位于linux内核。server端需要由你实现。

    当我们对/dev/nbdx设备发起io操作时,会由内核中的nbd client封装成nbd请求通过tcp网络发送给对应的nbd server,server端解析请求,做出处理后,返回结果到nbd client端。

    image.png

    有关协议的内容和操作方式,见官方文档
    注意,这里文档里称内核中的部分为server,我们实现的部分为client。

    rbd-nbd

    ceph社区为nbd实现了一个server,这个server会接收来自内核中nbd的请求,然后转调librdb完成请求,返回结果。

    rbd对nbd的支持全部位于rbd-nbd.cc文件,大概1000行代码。

    命令基本实现

    • 使用rbd-nbd map image-spec|snap-spec 命令将一个rbd镜像map到块设备,是fork出一个server进程,并为该server进程和内核client指定通信所用的socket fd。当然,还要为client设置timeout、block size、device size等等一些参数,以及一些flags。之后,server进程会运行两个线程,然后调用ioctl(nbd, NBD_DO_IT)进入阻塞状态,直到unmap过程中调用ioctl(nbd, NBD_DISCONNECT)。一个为读线程,接收来自client的请求,解析后放入一个pending队列,然后调用image.aio_write``image.aio_read``image.aio_flush等命令异步执行操作,在其完成后会调用提前注册的回调函数,将请求从pending队列转移到finish队列。另一个为写线程,finish队列为空时,写线程阻塞,当finish队列不为空时,写线程负责从finish队列中取出完成的请求,将结果返回给nbd client端。
    • 使用rbd-nbd unmap devpath命令进行unmap操作,其实只有两行代码: int nbd = open_device(devpath.c_str())ioctl(nbd, NBD_DISCONNECT)(NBD_DISCONNECT是nbd的协议原语之一)。
    • 使用rbd-nbd list-mapped命令查看所有map的nbd设备和rbd镜像的对应关系,其步骤是:从x=0开始遍历,通过/sys/block/nbd<x>/pid获取该nbd设备对应的server进程pid,然后通过/proc/<pid>/cmdline获取该进程启动时的命令(肯定是rbd-nbd map image-spec|snap-spec),通过解析cmdline来获得image、pool等信息。

    一些要点

    • rbd-nbd server与client的通信是使用socketpair(AF_UNIX, SOCK_STREAM, 0, fd)产生fd进行的。client端通过fd[0]向server发送请求与接收结果。server端通过fd[1]接收client端发送的请求,并返回结果。
    • 通过nbd map的块设备只可能有两个cache,一个是内核中的块设备缓存,一个是librbd的缓存。nbd本身没有做缓存。
    • rbd-nbd会监控rbd image size的变化,发生变化时,会依次清空blk设备缓存ioctl(fd, BLKFLSBUF, NULL),设置新size到nbd clientioctl(fd, NBD_SET_SIZE, new_size),重新扫描分区表ioctl(fd, BLKRRPART, NULL),清空image缓存image.invalidate_cache()

    写的不是很详细,有问题私戳我吧。。

    参考

    https://sourceforge.net/p/nbd/code/ci/master/tree/doc/proto.md
    https://nbd.sourceforge.io/
    https://github.com/ceph/ceph/blob/master/src/tools/rbd_nbd/rbd-nbd.cc

    相关文章

      网友评论

      • 8894e69a3048:谢谢分享,写的真好,受用,再结合代码看看 :+1: 期待更多源码分析

      本文标题:ceph rbd:nbd原理

      本文链接:https://www.haomeiwen.com/subject/slkxcftx.html