使用targetcli创建loop Target和vhost Target
除了常见的SAN Target之外,Linux-IO Target还支持两种特殊的Target,loop和vhost。其中loop Target可以为本机模拟一个完全实现了SPC-3和SPC-4规范的设备。vhost则是专门为虚拟化设计的功能,它在宿主操作系统的内核中实现一个支持virtio规范的SCSI Target,Initiator则是客户机器virtio-scsi控制器,使用半虚拟化virtio驱动。这样客户操作系统就可以通过virtio-scsi驱动和宿主操作系统内核中的vhost Target直接通信,而不需要Hypervisor的干预,减少了切换开销,提高了IO吞吐量。在客户操作系统看来,virtio-scsi控制器连接的virtio-scsi设备和一般的SCSI设备一样,在宿主这端,我们则可以很灵活的让vhost Target与各种各样的backstore对象关联。配置灵活,性能也较高。
在Linux-IO Target现有的架构上实现vhost-scsi设备并不复杂。图2显示了Linux-IO Target的各个组件。LIO模拟了通用的SCSI设备,并且实现了SPC-3和4。接着,通过各种各样的backstore对象,来导入真正的后端存储,最后连接上各种前端Fabric模块,来导出模拟的SCSI设备。无论是Fibre Channel、FCoE、iSCSI还是vhost(即virtio),都只是一种Fabric技术,我们可以将其理解成传输协议,而在这些传输协议中传输的SCSI命令则总是由核心的SCSI设备处理的。要支持新的Fabric技术,并不需要修改核心的SCSI设备和后端存储模块,只需要按照该Fabric技术的规范实现对SCSI命令的传输就可以了。iSCSI技术就是把SCSI命令放在TCP/IP中传输,vhost技术就是把SCSI命令放在virtio队列中传输。
图2. Linux-IO Target的各逻辑组件(摘自LIO官网)
创建loopback Target的指令如清单9。创建完毕后,可以运行lsscsi,系统发现了新的SCSI设备,设备节点是/dev/sdb。
清单9. 创建loopback Target
[root@localhost edward]# targetcli
/> cd loopback
/loopback> create
Created target naa.5001405c81b9d906.
/loopback> cd naa.5001405c81b9d906/
/loopback/naa.5001405c81b9d906> luns/ create /backstores/ramdisk/rd0
Created LUN 0.
/loopback/naa.5001405c81b9d906> cd /
/> ls
o- / ..................................................................... [...]
o- backstores .......................................................... [...]
| o- block .............................................. [Storage Objects: 0]
| o- fileio ............................................. [Storage Objects: 1]
| | o- disk0 ............... [/tmp/disk0.img (10.0MiB) write-back deactivated]
| o- pscsi .............................................. [Storage Objects: 0]
| o- ramdisk ............................................ [Storage Objects: 1]
| o- rd0 ............................................. [(10.0MiB) activated]
o- iscsi ........................................................ [Targets: 0]
o- loopback ..................................................... [Targets: 1]
| o- naa.5001405c81b9d906 ............................. [naa.5001405f01cea298]
| o- luns ........................................................ [LUNs: 1]
| o- lun0 .................................................. [ramdisk/rd0]
o- vhost ........................................................ [Targets: 0]
/> exit
[edward@localhost ~]$ lsscsi
[0:0:0:0] disk ATA HITACHI HTS72755 JF3Z /dev/sda
[1:0:0:0] cd/dvd HL-DT-ST DVDRAM GT50N LT20 /dev/sr0
[7:0:1:0] disk LIO-ORG rd0 4.0 /dev/sdb
我们可以使用dd命令测试一下sdb的读写速度,由于sdb的后端实际是ramdisk,读写速度应该特别快。在作者的笔记本电脑上,测试的结果如清单10所示。
清单10. 读写loopback SCSI设备
[root@localhost edward]# dd if=/dev/zero of=/dev/sdb bs=1048576 count=10 oflag=dsync,direct
记录了10+0 的读入
记录了10+0 的写出
10485760字节(10 MB)已复制,0.00621256 秒,1.7 GB/秒
[root@localhost edward]# dd if=/dev/sdb of=/dev/null count=10 bs=1048576 iflag=dsync,direct
记录了10+0 的读入
记录了10+0 的写出
10485760字节(10 MB)已复制,0.00590365 秒,1.8 GB/秒
创建vhost Target的指令如清单11所示,创建成功后,可以启动KVM虚拟机,并在客户操作系统中找到对应的LUN。
清单11. 创建vhost Target并启动KVM虚拟机
[root@localhost edward]# targetcli
targetcli shell version 2.1.fb30
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.
/> loopback/ delete naa.5001405c81b9d906
Deleted Target naa.5001405c81b9d906.
/> cd vhost
/vhost> create
Created target naa.5001405162d5cf9d.
Created TPG 1.
/vhost> cd naa.5001405162d5cf9d/tpg1/
/vhost/naa.50...62d5cf9d/tpg1> luns/ create /backstores/ramdisk/rd0
Created LUN 0.
/vhost/naa.50...62d5cf9d/tpg1> cd /
/> ls
o- / ..................................................................... [...]
o- backstores .......................................................... [...]
| o- block .............................................. [Storage Objects: 0]
| o- fileio ............................................. [Storage Objects: 1]
| | o- disk0 ............... [/tmp/disk0.img (10.0MiB) write-back deactivated]
| o- pscsi .............................................. [Storage Objects: 0]
| o- ramdisk ............................................ [Storage Objects: 1]
| o- rd0 ............................................. [(10.0MiB) activated]
o- iscsi ........................................................ [Targets: 0]
o- loopback ..................................................... [Targets: 0]
o- vhost ........................................................ [Targets: 1]
o- naa.5001405162d5cf9d .......................................... [TPGs: 1]
o- tpg1 .............................. [naa.50014059b977cca7, no-gen-acls]
o- acls ...................................................... [ACLs: 0]
o- luns ...................................................... [LUNs: 1]
o- lun0 ................................................ [ramdisk/rd0]
/> exit
[root@localhost edward]# qemu-system-x86_64 -m 1024 -enable-kvm -device \
> vhost-scsi-pci,id=vhost-scsi0,wwpn=naa.5001405162d5cf9d \
> -cdrom iso/Fedora-Live-Xfce-x86_64-20-1.iso \
> -vnc 127.0.0.1:1 -vga qxl
使用VNC客户端登陆127.0.0.1:1,我们就进入了客户操作系统的图形界面。在客户操作系统中,我们可以运行lspci命令,可以看到Virtio SCSI控制器,运行lsscsi,则可以看到/dev/sda设备,这个设备的后端就是我们通过vhost在宿主操作系统中导出的LUN。命令的输出如清单12所示。
清单12. 在客户操作系统中列出Virtio SCSI控制器和设备
[root@localhost liveuser]# lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Red Hat, Inc. Device 0100 (rev 04)
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
00:04.0 SCSI storage controller: Red Hat, Inc Virtio SCSI
[root@localhost liveuser]# lsscsi
[1:0:0:0] cd/dvd QEMU QEMU DVD-ROM 1.6. /dev/sr0
[2:0:1:0] disk LIO-ORG rd0 4.0 /dev/sda
我们可以在客户操作系统中读写sda,sda的真正的后端是宿主操作系统上的ramdisk,因此读写速度应该比较快,dd命令的输出结果如清单13。
清单13. 在客户操作系统中读写Virtio SCSI设备
[root@localhost liveuser]# dd if=/dev/sda of=/dev/null count=10 bs=1048576 iflag=dsync,direct
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00762005 s, 1.4 GB/s
[root@localhost liveuser]# dd if=/dev/zero of=/dev/sda count=10 bs=1048576 oflag=dsync,direct
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.0144263 s, 727 MB/s
小结
targetcli的操作简便,界面友好。用户在熟悉了Linux-IO Target的各个对象的层级关系之后,可以很轻松的创建、修改、删除目录树的各级节点,管理各种各样的后端存储和Target。用过targetcli之后,估计读者再也不想回到tgtadmin的时代了。
rtslib介绍
rtslib是一个Python程序库,让用户可以以编程的方式配置Linux-IO Target的各项功能。rtslib中的对象也被组织成树状结构,并且与我们在targetcli中熟悉的各种对象也很相似。熟悉了targetcli的操作之后,用rtslib编程就变得十分容易。首先,我们需要安装python-rtslib的RPM包。还可以安装python-rtslib-doc的RPM包,里面包含了接口的说明文档。下面以iSCSI为例,展示如何用rtslib创建Target。程序见清单14。
清单14. 使用rtslib创建iSCSI目标(iscsiTest.py)
import rtslib
def createTarget():
fio = rtslib.FileIOStorageObject(
'disk0', dev='/tmp/disk0.img', size=100 * 1024 * 1024)
iscsiMod = rtslib.FabricModule('iscsi')
tgt = rtslib.Target(iscsiMod, mode='create')
tpg = rtslib.TPG(tgt, tag=None, mode='create')
rtslib.LUN(tpg, lun=None, storage_object=fio)
tpg.set_attribute('generate_node_acls', '1')
tpg.set_attribute('cache_dynamic_acls', '1')
tpg.set_attribute('authentication', '0')
tpg.set_attribute('demo_mode_write_protect', '0')
tpg.enable = True
rtslib.NetworkPortal(tpg, '0.0.0.0', mode='create')
return tgt.wwn
print createTarget()
以超级用户运行iscsiTest.py以创建iSCSI Target,为了验证,运行targetcli ls命令,可以查看结果,输出如清单15。
清单15. 运行iscsiTest.py并验证结果
[root@localhost edward]# python iscsiTest.py
iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.5896eabe652f
[root@localhost edward]# targetcli ls
o- / ..................................................................... [...]
o- backstores .......................................................... [...]
| o- block .............................................. [Storage Objects: 0]
| o- fileio ............................................. [Storage Objects: 1]
| | o- disk0 ................ [/tmp/disk0.img (100.0MiB) write-thru activated]
| o- pscsi .............................................. [Storage Objects: 0]
| o- ramdisk ............................................ [Storage Objects: 0]
o- iscsi ........................................................ [Targets: 1]
| o- iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.5896eabe652f . [TPGs: 1]
| o- tpg1 .............................................. [gen-acls, no-auth]
| o- acls ...................................................... [ACLs: 0]
| o- luns ...................................................... [LUNs: 1]
| | o- lun0 .............................. [fileio/disk0 (/tmp/disk0.img)]
| o- portals ................................................ [Portals: 1]
| o- 0.0.0.0:3260 ................................................. [OK]
o- loopback ..................................................... [Targets: 0]
o- vhost ........................................................ [Targets: 0]
iscsiTest.py的核心代码只有10来行,就创建了一个文件后端对象,和一个iSCSI Target,使用rtslib编程很方便。要了解每个方法调用的意义,读者可以参考rtslib的文档,如果装了python-rtslib-doc,文档的位置是/usr/share/doc/python-rtslib-doc/html/index.html。需要注意的是,Fedora、RHEL、CentOS打包的rtslib和官方版的编程接口略有不同,示例程序是针对Fedora发行的python-rtslib写的,如果读者要在Ubuntu或Debian上使用rtslib,需要参考官方接口文档。
小结
Linux-IO Target是Linux平台上比较先进的内核态SCSI Target方案。其功能强大,可以导入各种后端存储,实现了对SPC-3和4的模拟,支持多种SAN技术,还为虚拟化提供了特别的优化。targetcli 是其用户态的配置工具,以shell的方式在一个配置目录树上运行,界面十分友好。rtslib是Linux-IO Target的Python编程接口,使用起来很简单,短短10来行代码就能创建存储后端和Target。根据Linux-IO Target项目的官方时间表,2014年将支持NPIV,很值得期待。
参考资源
参考SCSI Target的维基百科页面,了解SCSI Target和Initiator的功能。
参考Linux-IO Target的官方介绍,以了解其具体特性和开发时间表。
参考Linux Weekly News,了解LIO的历史。
参考targetcli的Wiki页面,详细了解targetcli的各个功能。
参考iSCSI的Wiki页面,了解如何使用Linux-IO Target管理iSCSI Target。
参考loopback的Wiki页面,了解如何使用Linux-IO Target管理loopback Target。
参考virtio-scsi的介绍,了解virtio-scsi在虚拟化中的应用。
参考virtio-scsi的讨论,了解各种SCSI模拟技术在虚拟化中的应用。
参考vhost的Wiki页面,了解如何使用Linux-IO Target管理vhost Target。
参考rtslib官方接口文档,详细了解rtslib的编程接口。