Linux-IO Target在Linux内核中,用软件实现各种SCSI Target,其支持的SAN技术包括Fibre Channel、FCoE、iSCSI等,同时还能为本机生成模拟的SCSI设备,以及为虚拟机提供基于virtio的SCSI设备。Linux-IO Target使用户能够使用相对廉价的Linux系统实现SCSI、SAN的各种功能,而不用购买昂贵的专业设备。
Target和Initiator是SCSI的术语。Initiator指的是SCSI会话的发起方,它向Target请求LUN(Logical Unit Number,可认为是逻辑块设备),并将数据的读写指令发送给Target。Target指的是接受SCSI会话的一方,它接收来自Initiator的指令,为Initiator提供LUN,并实现对LUN的读写。如果用客户端-服务器的模型来考虑,Initiator即是客户端,Target是服务器。在SAN中,主机一般都是Initiator,存储设备则是Target。
由于Linux的流行,人们在内核里加入了各种各样的功能,比如Linux系统可以用作路由器和交换机。人们也希望能够用Linux来实现专业的存储设备才有的功能。在Linux-IO Target之前,Linux内核采用了STGT项目来实现各种Target,配置管理则使用大家熟知的tgtadmin等工具,根据作者的经验,tgtadm使用起来很不友好。STGT的SCSI设备模拟实际都是在用户态中实现的,存在性能瓶颈。Linux-IO Target则在内核态实现了对Target的模拟,配置管理则采用了更为“现代化”的基于sysfs的方式,既消除了性能瓶颈,也提供了友好的用户态管理工具。从内核的2.6.38版起,Linux内核都包含Linux-IO Target的相关模块。在用户态,各大发行版都打包了targetcli和rtslib,其中targetcli程序用于配置、管理,rtslib则提供Python编程接口。
图1. Linux-IO的iSCSI Target架构(摘自LIO官网)
以iSCSI为例,Linux-IO Target的配置结构如图1所示。处于最后端的是各种各样的Linux的存储设备。Linux-IO Target支持的后端存储设备包括Ramdisk、通用块设备和文件,也可以直接映射本地SCSI设备。Linux-IO Target通过创建backstore存储对象来导入这些存储设备。它可以使用各种SAN传输技术来导出这些存储对象。首先,基于某种SAN技术(例如iSCSI)创建一个Target。接着,在Target里创建一个TPG(Target Portal Group)。每个Target下可以创建多个TPG,每个TPG包含了一组入口(Portal)。然后在TPG里创建LUN,并将特定的存储对象与特定的LUN关联起来。最后在TPG里创建一个或者多个入口,对iSCSI来说,每个Portal就是一个IP地址和端口的组合。为了更精确的控制对LUN的访问,还可以在TPG之下创建各种ACL规则。
targetcli介绍
targetcli是Linux-IO Target的用户态的管理配置工具。用户可以使用yum或apt-get直接从各大发行版的官方仓库安装。targetcli提供一个类似shell的界面,而前文提到的各种Target、TPG、LUN、backstore对象则被组织成目录树的形式,用户可以用ls、cd命令来浏览目录树,用create、delete命令来创建和删除各种对象。浏览配置,就是浏览目录树,创建删除各种对象,就是在目录树的各级节点中创建新的节点。同时targetcli还提供了常见的shell命令辅助编辑功能,例如TAB智能补全、上下键切换命令历史、Ctrl + R搜索命令历史。凡是有不熟悉的命令,都可以用help命令查询使用说明。
使用targetcli创建后端存储对象
配置Target的第一步就是创建存储对象。运行targetcli程序,进入一个shell界面,系统显示如清单1。
清单1. targetcli初始提示
targetcli shell version 2.1.fb30
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.
/>
输入ls命令,targetcli便将当前的目录树输出,如清单2。
清单2. 列出初始目录树
/> ls
o- / ............................................... [...]
o- backstores .................................... [...]
| o- block ........................ [Storage Objects: 0]
| o- fileio ....................... [Storage Objects: 0]
| o- pscsi ........................ [Storage Objects: 0]
| o- ramdisk ...................... [Storage Objects: 0]
o- iscsi .................................. [Targets: 0]
o- loopback ............................... [Targets: 0]
o- vhost .................................. [Targets: 0]
输入cd backstores/fileio命令,进入backstores/fileio子目录,并用create命令创建一个文件存储对象。接着使用cd ../ramdisk命令,从backstores/fileio移动到backstores/ramdisk子目录,并用create命令创建一个ramdisk,如清单3。
清单3. 创建文件存储对象
/> cd backstores/fileio
/backstores/fileio> create disk0 /tmp/disk0.img 10MB
Created fileio disk0 with size 10485760
/backstores/fileio> cd ../ramdisk
/backstores/ramdisk> create rd0 10MB
Created ramdisk rd0 with size 10MB.
最后回到backstore这级目录并用ls命令确认当前创建的存储对象,运行结果如清单4。
清单4. 浏览存储对象
/backstores/ramdisk> cd ..
/backstores> ls
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) deactivated]
除了可以创建fileio和ramdisk类型的backstore对象,还可以创建block和pscsi对象。block对象可以用来导入一般的块设备,比如/dev/hdaX、/dev/sdX、/dev/vgX/lvX等。pscsi对象可以用来导入系统里已有的SCSI设备(即lsscsi列出的设备),所有SAN的前端收到的SCSI命令都会透传到pscsi导入的设备。需要注意,Linux-IO Target所模拟的SCSI设备实现了SPC-2、SCP-3和SPC-4规范,也就是说Persistent Reservations (PRs)、Asymmetric Logical Unit Assignment (ALUA)和vStorage APIs for Array Integration (VAAI)等高端SCSI特性都有实现。但是主机上的现有SCSI设备则未必实现了SPC-4,因此在需要高端SCSI特性的场合,最好通过block对象来导入/dev/sdX这样的设备,而不是通过pscsi。
使用targetcli创建iSCSI目标
下面以iSCSI为例子,展示如何创建Target、TPG、LUN和Portal对象。首先,使用cd命令进入iscsi子目录。接着,使用create命令创建一个Target对象,如果不指定Target对象的WWN,targetcli会自动生成一个。创建Target对象的同时,targetcli还在其下自动创建了一个TPG,名为tpg1。在tpg1之下,可以创建LUN、Portal、ACL对象。出于简单起见,我们没有启用ACL和CHAP认证,因此,我们还要用set命令设置此TPG的属性,以允许匿名访问。整个过程如清单5所示。
清单5. 创建iSCSI目标
/backstores/ramdisk> cd /iscsi
/iscsi> create
Created target iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d.
Created TPG 1.
/iscsi> cd iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d/tpg1/
/iscsi/iqn.20...2e88795d/tpg1> luns/ create /backstores/fileio/disk0
Created LUN 0.
/iscsi/iqn.20...2e88795d/tpg1> luns/ create /backstores/ramdisk/rd0
Created LUN 1.
/iscsi/iqn.20...2e88795d/tpg1> portals/ create 0.0.0.0
Using default IP port 3260
Binding to INADDR_ANY (0.0.0.0)
Created network portal 0.0.0.0:3260.
/iscsi/iqn.20...2e88795d/tpg1> set attribute authentication=0 demo_mode_write_protect=0 generate_node_acls=1 cache_dynamic_acls=1
Parameter demo_mode_write_protect is now '0'.
Parameter authentication is now '0'.
Parameter generate_node_acls is now '1'.
Parameter cache_dynamic_acls is now '1'.
在运行cd、create命令的之后,我们还可以运行ls命令以确认执行的结果,出于篇幅本文没有举例,读者可以自己执行ls命令观察结果。最后,我们进入顶层目录,并运行ls命令查看总的结果,输出如清单6。
清单6. 浏览iSCSI和后端存储
/iscsi/iqn.20...2e88795d/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 activated]
| o- pscsi .............................................. [Storage Objects: 0]
| o- ramdisk ............................................ [Storage Objects: 1]
| o- rd0 ............................................. [(10.0MiB) activated]
o- iscsi ........................................................ [Targets: 1]
| o- iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d . [TPGs: 1]
| o- tpg1 .............................................. [gen-acls, no-auth]
| o- acls ...................................................... [ACLs: 0]
| o- luns ...................................................... [LUNs: 2]
| | o- lun0 .............................. [fileio/disk0 (/tmp/disk0.img)]
| | o- lun1 ................................................ [ramdisk/rd0]
| o- portals ................................................ [Portals: 1]
| o- 0.0.0.0:3260 ................................................. [OK]
o- loopback ..................................................... [Targets: 0]
o- vhost ........................................................ [Targets: 0]
从清单6中,我们可以很形象的看到Target(名为“iqn.2003-01...”的对象)、TPG、ACL、LUN和Portal的从属关系,也可以很清楚的看到lun0的后端对象是fileio/disk0,映射的文件是/tmp/disk0.img,lun1的后端是ramdisk/rd0。如果对结果满意,则可运行saveconfig命令,会将配置保存为一个json文件。为了让系统启动的时候能够自动重新加载这个json文件,则应该启用target服务,以SystemD为例,运行“systemctl enable target”即可。
要测试刚才配置好的iSCSI Target,我们在别的机器上,用Linux的软件实现的iSCSI Initiator来装载Target。首先安装RPM包iscsi-initiator-utils,里面包含了iscsiadm命令。我们运行iscsiadm可以检测导出的Target并装载其中的LUN,简单起见,我们在同一台机器上装载Target。最后运行lsscsi,我们可以发现输出中新增了sdb和sdc这两个新的设备。命令输出如清单7所示。
清单7. 装载iSCSI Target
[root@localhost edward]# iscsiadm -m discovery -t sendtargets -p 127.0.0.1
127.0.0.1:3260,1 iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d
[root@localhost edward]# iscsiadm --mode node \
> --targetname iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d \
> --portal 127.0.0.1 --login
Logging in to [iface: default, target: iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d, portal: 127.0.0.1,3260] (multiple)
Login to [iface: default, target: iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d, portal: 127.0.0.1,3260] successful.
[root@localhost edward]# 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
[6:0:0:0] disk LIO-ORG disk0 4.0 /dev/sdb
[6:0:0:1] disk LIO-ORG rd0 4.0 /dev/sdc
为了删除刚才创建的Target,我们首先让Initiator卸载它,然后从targetcli中用delete命令将其删除即可。targetcli除了可以以shell形式运行,还可将要运行的操作指令作为参数直接调用targetcli,targetcli执行指令后就自动退出,很方便。命令输出如清单8。可以发现,只需要删除指定的Target,其目录下的TPG、LUN、Portal、ACL等对象会自动被级联删除,操作起来简单又符合直觉。
清单8. 卸载并删除iSCSI Target
[root@localhost edward]# iscsiadm --mode node --targetname iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d --portal 127.0.0.1 --logout
Logging out of session [sid: 1, target: iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d, portal: 127.0.0.1,3260]
Logout of [sid: 1, target: iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d, portal: 127.0.0.1,3260] successful.
[root@localhost edward]# targetcli iscsi/ delete iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d
Deleted Target iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.d6f52e88795d.
[root@localhost edward]# targetcli 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) deactivated]
o- iscsi ........................................................ [Targets: 0]
o- loopback ..................................................... [Targets: 0]
o- vhost ........................................................ [Targets: 0]
(未完待续)