向 stgt 添加对 RBD 的支持
tgt,Linux SCSI 目标框架(或者说其中之一),是一个 iSCSI 目标实现,其目标包括在用户空间实现大部分 SCSI 仿真代码。tgt 可以通过以太网或 InfiniBand 上的 iSER(RDMA 的 iSCSI 扩展)提供 iSCSI。它可以模拟各种 SCSI 目标类型(实际上
“命令集”)
- SBC(普通的“磁盘”类型设备)
- SMC(“点唱机”媒体更换器)
- MMC(CD/DVD 驱动器)
- SSC(磁带设备)
- OSD(“对象存储设备”)
它可以将原始块设备或文件用作这些设备类型中的任何一种的后端存储。
鉴于 Ceph 在网络上提供了一个分布式可靠的存储池,将该存储作为 iSCSI 设备访问似乎很自然;这样,即使不知道存储位于 Ceph 集群上(除了知道它是高可用且安全的),也会说 iSCSI 的客户端也无需知道。许多类型的虚拟机提供商和云软件都可以说 iSCSI,如果 Ceph 可以将存储导出为 iSCSI 设备,那么将所有这些提供商连接到 Ceph 集群将很容易。
为此,我为 tgt 编写了一个后端,可以使用 RADOS 块设备 (rbd) 镜像作为 iSCSI 目标设备的存储。现在,您可能会说:“但是,我已经可以在 Ceph 集群上创建一个 RBD 镜像,将其映射到我的内核中作为块设备,并使用 tgt 或 LIO 或其他 iSCSI 工具将其导出为 iSCSI 目标”,这是正确的;人们今天已经成功地这样做。但是,完全用户空间的方法具有几个优点
- 用户空间代码通常在新的功能方面领先于内核实现。截至撰写本文时,用户空间 rbd 可以使用写时复制克隆和“花哨的条带化”,这些功能仍在内核中实现
- 用户空间代码可以在较旧的内核上编译和安装,这些内核可能根本没有可用的内核 rbd 模块,或者可能具有较旧、不太稳定的版本
- 避免内核对于节流内存/带宽、常规管理、委派访问、安全性、避免内核崩溃等可能很有用。
- 在不冒内存死锁的风险的情况下,我们可以在用户空间 librbd 中执行更好的缓存
当然,这些优势并非免费的;性能方面也可能存在成本。tgt 项目已经采取了一些措施来减轻性能影响,但您的实际结果可能会有所不同。但是,端口的简易性和修改以获取新功能的简易性使得即使面对可能的性能下降,这也是一项值得的努力。
bs_rbd 后端存储驱动程序 ¶
由于 tgt 的模块化设计和简单的后端存储驱动程序,将 rbd 支持添加到 tgt 相对简单。从 bs_rdwr 后端存储驱动程序开始,该驱动程序使用常规 open/close /read/write 函数将由守护程序提供的实例备份到文件系统中的文件或块设备,我添加了初始化以使用 librados 连接到 RADOS 集群,并添加了一个小函数来解析 rbd 池、镜像名称和快照名称(如下所示)。然后,POSIX 调用被转换为 librbd 调用,用于 rbd_open、rbd_close 等。librbd 在同步和异步形式上都与 POSIX 文件操作非常相似,因此转换显而易见且容易。
该补丁已于 2013 年 2 月中旬被接受到 主线仓库,并附带了一些关于如何使用它的简要 README 信息。编辑:但是,tgtd 必须使用 CEPH_RBD 标志构建才能支持 rbd;您可能需要从源代码自行构建。您可以使用以下命令检查是否支持:
tgtadm --lld iscsi --mode system --op show
如果您的 tgtd 支持 rbd,则“后端存储:”中应显示“rbd”。
以下是关于该简要用法的更多说明
tgtd 通过 tgtadm 命令进行配置;要为 tgtd 实例选择 RBD 镜像作为后端存储,您可以使用 –bstype rbd 选项告诉 tgtd 它应该使用 bs_rbd 访问存储。此外,使用 –backing-store 选项选择通常的 Ceph 语法中的 (已存在的) rbd 镜像:–backing-store [pool/]image[@snap] 以选择名为“image”的 rbd 镜像,可选地位于池“pool”中,以及可选地该镜像的只读快照 @snap。您可以使用 rbd 命令行工具以通常的方式创建镜像。
您必须为要创建的设备指定一个名称;典型的名称形式是“IQN”(iSCSI 资格名称),形式为:iqn。
使用 tgtd 的 bs_rbd ¶
使用手动命令的典型设置可能如下所示:首先,在您正在运行的 Ceph 集群上创建一个镜像
rbd create iscsi-image --size 500 # 一个名为 iscsi-image 的 500 MB 镜像
tgtadm/tgtd 将使用默认 Ceph 配置文件(默认情况下,/etc/ceph/$cluster.conf、~/.ceph/$cluster.conf 和 ./$cluster.conf,其中 $cluster 默认情况下为“ceph”)或 CEPH_CONF 环境变量提供的配置访问集群;确保您的配置可以通过其中一种设置访问。
接下来,为 tgtd 守护程序创建一个新的目标来模拟(编辑:截至 2013 年 7 月 16 日,由于原因不明,您可能无法使用 tid 0)
tgtadm --lld iscsi --mode target --op new --tid 1 --targetname rbd
在此目标上创建一个 LUN,该 LUN 绑定到 rbd 镜像(编辑:lun 0 始终保留给“控制”节点,因此 lun 1 是第一个可用的)
tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 --backing-store iscsi-image --bstype rbd
允许访问该 lun
tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
验证本地 iscsi 发起程序是否可以看到该镜像。我在这里使用 iscsiadm,它是 open-iscsi 包的一部分
iscsiadm -m discovery -t st -p localhost
登录到节点,这将创建一个 /dev/sdX 块设备
iscsiadm -m node --login
现在,您可以使用 iSCSI 作为 /dev/sdX 在本地访问该设备。您也可以从不同的网络主机执行最后两个步骤,指定 -p
完成操作后,您可以终止会话并删除该设备
iscsiadm -m node --logout
bs_rbd 后端存储驱动程序详细信息、未来可能的工作 ¶
作为首次实现,我编写的 bs_rbd 驱动程序最多可以处理 20 个并发 rbd 镜像(只是一个任意固定大小的数组限制),并使用 bs_rdwr 模块作为起点,以便 I/O 与 RADOS 集群同步。但是,tgtd 本身维护一个默认情况下为 16 个线程的线程工作池,因此虽然 I/O 在 RADOS 集群中阻塞,但守护程序本身维护多个未决请求。可以使用 LUN 创建时提供的 -t 或 –nr-iothreads 调整线程计数。
使用 librbd 的异步 I/O 支持可能会提高性能或 CPU 利用率;这可能是实验的基础。我选择了更简单的实现作为工作概念验证;欢迎进行性能研究和实验。
该驱动程序链接到 librbd 和 librados,因此必须在您的机器上安装这些库才能进行构建,并且必须通过例如“make CEPH_RBD=1”选择配置选项 CEPH_RBD。
试试吧! ¶
这就是 tgt 中 rbd 支持的故事!请尝试一下并告诉我们您的想法;将任何错误报告到 stgt 邮件列表和 ceph 开发列表:stgt@vger.kernel.org 和 ceph-devel@vger.kernel.org。
