作者简介:万群,Intel 存储软件工程师,主要从事SPDK软件测试工作
文章转载自DPDK与SPDK开源社区
01.基本概念
逻辑卷介绍
大多数卷管理器都有着相同的基本设计。它们由物理卷(PV, Physical Volume)入手,这可以是硬盘,硬盘分区,或者是外部存储设备的逻辑单元号(LUN, Logical Unit Number)。卷管理将每一个PV都视作是由一系列称为物理区段(PE, Physical Extent)的块组成的[1]。
通常, 物理卷只是简单地一对一映射到逻辑区域中(LE, Logical Extent)中。通过镜像,多个PE映射到单个LE。PE从物理卷组(PVG, Physical Volume Group)中抽取,这是一组相同大小的PV,其作用类似于RAID1阵列中的硬盘。
系统将LE集中到一个卷组中(VG, Volume Group)。合并后的LE可以被连接到称为逻辑卷(或者简称为LV)的虚拟磁盘分区中。系统可以使用LV作为原始块设备,就像磁盘分区一样:在其上创建可安装的文件系统,或者使用它们作为交换存储。
密集配置与精简配置
密集配置是一种存储分配方式,在磁盘创建时,磁盘上的存储容量在物理存储上预先分配。
精简配置使用虚拟化技术来使得物理资源比实际可用的看起来更多[2],如果一个系统总是有足够的资源来同时支持所有的虚拟化资源,那么它就不是精简配置。例如,计算机中的实际内存通常使用某种形式的虚拟化地址转换技术对运行任务进行精简配置。每个任务看上去就像被分配了实际内存一样。分配给任务的虚拟内存的总和通常超过实际内存的总和。
精简配置与密集配置的效率并非取决于技术差异,而是取决于不同的用例情况。当所使用的资源数量与所分配的资源数量非常接近时,密集配置通常会效率更高;当使用的资源量远小于所分配的资源量时,精简配置更为高效,所以,只提供所需资源带来的益处超过了使用虚拟化技术增加的成本。
图2展示了传统密集配置与精简配置的区别。
SPDK实现的逻辑卷概述
SPDK建立在SPDK blobstore之上,因为blobstore提供了高性能、低开销的群集分配。此外,在blobstore中,也支持精简配置、快照和写入时复制。在最新的SPDK版本中,它实现了具有以下功能的逻辑卷[3]。
- 卷的动态分配(bdevs)
- 可以独立管理卷(创建、调整大小、删除)
- 支持精简配置
- 快照和克隆(写入时复制)
- 实现为虚拟bdev (可以在其他所有SPDK bdevs上分层)[4]
图3显示了nvmf + lvol的用例。
02.基本RPC命令
1. 创建 malloc bdev
./rpc.py construct_malloc_bdev -b [NAME] total_size block_size
-b: bdev的名字(可选)
Total size: 逻辑卷大小(以兆字节为单位)
Block size:块大小(以字节为单位)
示例:
下面的示例显示当malloc0已经存在时,rpc工具按以下方法发布它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/spdk/scripts# ./rpc.py construct_malloc_bdev -b Malloc0 100 4096 Got JSON-RPC error response request: { "jsonrpc": "2.0", "params": { "block_size": 4096, "num_blocks": 25600, "name": "Malloc0" }, "method": "construct_malloc_bdev", "id": 1 } response: { "message": "Invalid parameters", "code": -32602 } |
nvmf tgt应用也将打印如下内容:
1 |
bdev.c:2067:_spdk_bdev_register: *ERROR*: Bdev name:Malloc0 already exists |
2.使用rpc构建lvol存储
./rpc.py construct _lvol_store bdev_name lvs_name
bdev_name: base bdev的名字
lvs_name: lvol store的名字
-c CLUSTER_SZ:以字节为单位的簇大小(可选)
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/spdk/scripts# ./rpc.py construct_lvol_store Malloc0 lvs0 4f15fdfe-51c2-11e8-b802-a4bf0139e748 /spdk/scripts# ./rpc.py get_lvol_stores [ { "uuid": "4f15fdfe-51c2-11e8-b802-a4bf0139e748", "base_bdev": "Malloc0", "free_clusters": 24, "cluster_size": 4194304, "total_data_clusters": 24, "block_size": 4096, "name": "lvs0" } ] |
计算free_cluster的公式是:
Free_clusters = total_size/block_size (小数点自动加一)
3. 使用 rpc 构造密集配置 lvol
./rpc.py construct_lvol_bdev -l LVS_NAME lvol_name size
LVS_NAME:lvol store 的名字
lvol_name:此lvol的名字
size:此bdev的大小(以兆字节为单位)。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/spdk/scripts# ./rpc.py construct_lvol_bdev -l lvs0 lvol1 10 lvs0/lvol1 /spdk/scripts# ./rpc.py get_lvol_stores [ { "uuid": "4f15fdfe-51c2-11e8-b802-a4bf0139e748", "base_bdev": "Malloc0", "free_clusters": 21, "cluster_size": 4194304, "total_data_clusters": 24, "block_size": 4096, "name": "lvs0" } ] |
Free_clusters = total_data_clusters – size/cluster_size(小数点自动加一)
4.使用rpc创建自动精简配置逻辑卷
./rpc.py construct _lvol_bdev -l LVS_NAME lvol_name size –t
-t: 自动精简配置选项 (创建自动精简配置的lvol_bdev)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/spdk/scripts# ./rpc.py construct_lvol_bdev -l lvs0 lvol2 10 -t lvs0/lvol2 /spdk/scripts# ./rpc.py get_lvol_stores [ { "uuid": "4f15fdfe-51c2-11e8-b802-a4bf0139e748", "base_bdev": "Malloc0", "free_clusters": 21, "cluster_size": 4194304, "total_data_clusters": 24, "block_size": 4096, "name": "lvs0" } ] |
对于自动精简配置,free_cluster保持不变,直到写操作发生。当写操作发生时,free_cluster的计算公式如下:
Free_clusters = total_data_clusters - size/cluster_size (小数点自动加一)
03.使用场景
注释:
-以 NVMe为例, 它与 iscsi和vhost的步骤相似, 唯一 不同的是应用程序的运行。
-逻辑卷总大小不会自动增加 (大小在创建时已固定)
-性能数据仅供参考, 因为此功能尚处于早期开发阶段。
运行性能数据的步骤:
1.使用rdma编译SPDK
1 2 |
./configure --with-rdma make -j 8 |
2.使用以下命令运行nvmf_tgt应用程序。
1 |
./app/nvmf_tgt/nvmf_tgt |
3.创建大小为100MB LVS和10MB LV的逻辑卷存储和逻辑卷。
1 2 3 |
./rpc.py construct_malloc_bdev -b Malloc0 100 4096 ./rpc.py construct_lvol_store Malloc0 lvs0 ./rpc.py construct_lvol_bdev -l lvs0 lvol1 10 |
4.创建子系统
1 2 |
./rpc.py construct_nvmf_subsystem nqn.2016-06.io.spdk:cnode1 "trtype:RDMA traddr:192.168.0.1 trsvcid:4420" "" -a -s SPDK00000000000001 -n lvs0/lvol1 ./rpc.py construct_nvmf_subsystem nqn.2016-06.io.spdk:cnode2 "trtype:RDMA traddr:192.168.0.1 trsvcid:4420" "" -a -s SPDK00000000000001 -n lvs0/lvol2 |
5.连接子系统
1 2 |
nvme connect -t rdma -n "nqn.2016-06.io.spdk:cnode1" -a 192.168.0.1 -s 4420 nvme connect -t rdma -n "nqn.2016-06.io.spdk:cnode2" -a 192.168.0.1 -s 4420 |
6.Fio配置文件命名为thin_provisioning_fio_file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[global] thread=1 rw=randrw runtime=10 time_based=1 ioengine=libaio direct=1 bs=4096 invalidate=1 iodepth=1 norandommap=1 #Thick provisioning [job0] filename=/dev/nvme0n1 #Thin provisioning [job1] filename=/dev/nvme1n1 |
7.运行fio命令,测试性能指标
1 |
fio thin_provisioning_fio_file |
8.断开子系统
1 2 |
nvme disconnect -n "nqn.2016-06.io.spdk:cnode1" nvme disconnect -n "nqn.2016-06.io.spdk:cnode2" |
参考文献
[1]https://en.wikipedia.org/wiki/Logical_volume_management
[2] https://en.wikipedia.org/wiki/Thin_provisioning
[3]https://ci.spdk.io/download/events/2018-summit/day2_01_VerkampLogicalVolumes.pdf
[4]http://www.spdk.io/doc/logical_volumes.html