iSCSI
简单的说,iSCSI是一种存储设备远程映射技术,它可以将一个远程服务器上的存储设备映射到本地,并呈现为一个块设备(大白话就是磁盘)。从普通用户的角度,映射过来的磁盘与本地安装的磁盘毫无差异。iSCSI 这个架构主要将储存装置与使用的主机分为两个部分,负责连接的软件成为启动器。而提供存储服务的计算机成为服务端,其中的软件成为目标器。
- iSCSI Target:储存设备端,存放磁盘或 RAID 的设备。
- iSCSI Initiator:能够使用 Target 的客户端,通常是服务器。
与iSCSI类似的是NFS技术,它们都是为了解决存储资源共享的方案,只不过工作层次不一样,前者在客户机呈现的是一个块设备,后者呈现的是一个目录树。
在这篇文章中,我们将使用SPDK开发工具包的 iscsi_tgt
程序来部署iSCSI。
本文在第二章对部署步骤和常用命令进行介绍 ,第三章将演示一个完整的部署过程。
如果您想获取更详细的信息,请参考官方文档
基本概念
![image-20210305102234994](spdk-iscsi/iSCSI structure.png)
Network Portal: 网络端口。网络实体的一个组成部分,它有一个 TCP/IP 地址。 网络端口在 Initiator 用 IP 地址标识, 在 Target 用 IP 地址+侦听的 TCP 端口标识。
Session: 连接 Initiator 和 Target 的一组 TCP 连接构成一个 session(可以简单理解为 I_T nexus)。可以向 session 添加 TCP 连接,也可以把 TCP 连接从 session 删除。 也就是说一个session中是可以有多个连接的。通过一个 session 的所有连接,Initiator 只看到同一个 Target。
Connection : 一个 TCP 连接。Initiator 和 Target 之间使用一或者多个 TCP 连接通信。
CID(Connection ID): 一个 session 里的每个 connection 用 CID 进行标识,该标识在 session 范围内是唯一。CID 由 Initiator 产生,在 login 请求和使用 logout 关闭 连接时传递给 Target。
SSID(Session ID):一个 iSCSI Initiator 与 iSCSI Target 之间的会话(Session)由会话ID(SSID)定义,该会话ID是一个由发起方部分(ISID)和目标部分(Target Portal Group Tag)组成的元组。 ISID 在会话建立时由发起者明确指定。 Target Portal Group Tag 由发起者在连接建立时选择的 TCP端口来隐式指定。 当给定 targetName 时,targetPortalGroupTag 也必须由目标在连接建立期间作为确认返回。
Portal Groups: 网络端口组。iSCSI session 支持多连接,一些实现能把通过多个端口建立的多个连接捆绑到一个 session。 一个 iSCSI 网络实体的多个网络端口被定义为一个网络端口组,把该组和一个 session 联系起来,该 session 就可以捆绑通过该组内多个端口建立的多个连接,再使它们一起协同工作以达到捆绑的目的。每一个该组的 session 并不需要包括该组的所有网络端口。一个 iSCSI 节点可能有一或者多个网络端口组,但是每一个 iSCSI 使用的网络端口只能属于 iSCSI 节点的一个组。
Target Portal Group Tag: 网络端口组标识。使用 16 比特的数标识一个网络端口组。在 一个 iSCSI 节点里,所有具有同样组标志的端口构成一个网络端口组。
iSCSI Task: 一个 iSCSI 任务是指一个需要响应的 iSCSI 请求。
I_T nexus: I_T nexus 是指一个 SCSI Initiator 的端口和一个 SCSI Target 端口之间 的关系。 对于 iSCSI, 这个关系对应一个 session, 它指 session 的 Initiator 端和 iSCSI Target 网络端口组之间的关系。I_T nexus 的标识是一对端口名称(iSCSI Initiator 名称+i+ISID,iSCSI Target 名称+t+网络端口组标识)。 PDU (Protocol Data Unit): Initiator 和 Target 之间通信时把信息分割为消息。这些 消息称为 iSCSI PDU。 SSID (Session ID): iSCSI Initiator 和 iSCSI Target 之间的 session 用 SSID 进行标识, 该标识由 Initiator 部分的 ISID 和 Target 部分的 TPGT 构成。
ISID(The Initiator part of the Session Identifier):发起方会话标识,由 Initiator 在 session 建立的时候明确给出,
TSIH (Target Session Identifying Handle): Target 分配给与特定名称 Initiator 建立的 session 的标识。 但是 0 值被保留着用于 Initiator 告知 Target 这是一个新 session。 在为一个 session 添加一个 connect 时,TSIH 已经隐含指明。
iSCSI Target入门指南
我们将使用SPDK开发工具包的 iscsi_tgt
程序来部署iSCSI,该程序位于 build/bin
前期准备
本指南首先假设您已经可以在平台上构建标准SPDK发行版。
构建完成后,二进制文件将位于 build / bin
中。
如果要通过信号杀死应用程序,请确保使用SIGTERM,然后应用程序将在退出前释放所有共享内存资源,SIGKILL将使共享内存资源没有机会被应用程序释放,您可能需要手动释放资源。
介绍
下图显示了本文档中描述的iSCSI结构的不同部分之间的关系.
![image-20210305102234994](spdk-iscsi/iSCSI structure.png)
将 CPU 和 iSCSI Target 绑定
SPDK使用DPDK环境抽象层来访问硬件资源,例如大内存页和CPU内核。 DPDK EAL提供了将线程分配给特定内核的功能。 为确保SPDK iSCSI目标具有最佳性能,请将NIC和NVMe设备放在同一NUMA节点上,然后将目标配置为在与该节点关联的CPU内核上运行。 以下命令行选项用于配置SPDK iSCSI Target:
1 | -m 0xF000000 |
在此示例中,将使用CPU内核24、25、26和27。
通过RPC方法配置iSCSI Target
iSCSI目标是通过JSON-RPC调用配置的,SPDK在 spdk/scripts/rpc.py
提供了一个python脚本用来简化配置。 有关详细信息,请参见JSON-RPC。
以下列出常用的几个命令:
Portal groups
- iscsi_create_portal_group – Add a portal group.
- iscsi_delete_portal_group – Delete an existing portal group.
- iscsi_target_node_add_pg_ig_maps – Add Initiator group to portal group mappings to an existing iSCSI Target node.
- iscsi_target_node_remove_pg_ig_maps – Delete Initiator group to portal group mappings from an existing iSCSI Target node.
- iscsi_get_portal_groups – Show information about all available portal groups.
1 | $ sudo scripts/rpc.py iscsi_create_portal_group 1 10.0.0.1:3260 |
注意,这里的ip地址时你的taget主机的ip地址,端口是一个未被占用的端口
Initiator groups
- iscsi_create_initiator_group – Add an Initiator group.
- iscsi_delete_initiator_group – Delete an existing Initiator group.
- iscsi_initiator_group_add_initiators – Add initiators to an existing Initiator group.
- iscsi_get_initiator_groups – Show information about all available Initiator groups.
1 | $ sudo scripts/rpc.py iscsi_create_initiator_group 2 ANY 10.0.0.2/32 |
注意,这里的ip地址是你的client主机的ip地址
Target nodes
- iscsi_create_target_node – Add an iSCSI Target node.
- iscsi_delete_target_node – Delete an iSCSI Target node.
- iscsi_target_node_add_lun – Add a LUN to an existing iSCSI Target node.
- iscsi_get_target_nodes – Show information about all available iSCSI Target nodes.
1 | $ sudo scripts/rpc.py iscsi_create_target_node target3 target3_alias MyBdev:0 1:2 64 -d |
配置iSCSI启动器
Linux启动器是open-iscsi。
1 | # 安装open-iscsi |
发现
假设taget主机的ip地址是 10.0.0.1
1 | $ iscsiadm -m discovery -t sendtargets -p 10.0.0.1 |
连接到Target
1 | $ iscsiadm -m node --login |
此时,iSCSI目标应显示为SCSI磁盘。检查dmesg以查看它们出现的情况。
断开与Target的连接
1 | $ iscsiadm -m node --logout |
删除Target节点缓存
1 | $ iscsiadm -m node -o delete |
这将导致启动器忘记所有先前发现的iSCSI目标节点。
查找iSCSI LUN的/ dev / sdX节点
1 | $ iscsiadm -m session -P 3 | grep "Attached scsi disk" | awk '{print $4}' |
这将显示所有已登录iSCSI会话中每个SCSI LUN的/ dev节点名称。
示例: 配置简单的iSCSI Target
本示例演示挂载nvme磁盘,如果没有磁盘的话可以参考官方教程挂载内存模拟的块设备。
假设我们在Target端拥有一块nvme磁盘,位于192.168.0.22,现在想通过配置iSCSI让192.168.0.21主机访问到该磁盘。
前期准备
通过VMware在Target端挂载一块5GB的NVMe硬盘,并将控制权移交给SPDK
![nvme ssd](spdk-iscsi/nvme ssd.png)
- 在Target端查看挂载情况
1 | $ ls /dev | grep nvme |
- 启动SPDK,指示操作系统放弃控制设备,让SPDK控制设备
1 | $ cd spdk |
配置iSCSI Target
- 启动
iscsi_tgt
应用
1 | $ sudo ./build/bin/iscsi_tgt |
- 创建ID为1的新的端口组,地址为 192.168.0.21:3111
1 | $ sudo ./scripts/rpc.py iscsi_create_portal_group 1 192.168.0.22:3111 |
- 创建一个ID为2的启动器组以接受来自0.0.0.0/0的任何连接:
1 | $ sudo ./scripts/rpc.py iscsi_create_initiator_group 2 ANY 0.0.0.0/0 |
- 在SPDK中基于NVMe设备创建块设备(bdev)
也可以基于其他设备创建bdev,详见 https://spdk.io/doc/bdev.html
1 | # 获取NVMe设备的地址 |
- 使用先前创建的bdev构建一个目标,如LUN0(NVMe1n1),名称为“myNVMeDisk1”,别名为“My NVMe Disk1”,使用portal group 1和Initiator group 2。
1 | $ sudo ./scripts/rpc.py iscsi_create_target_node myNVMeDisk1 "My NVMe Disk1" "NVMe1n1:0" 1:2 64 -d |
配置 Initiator
- 发现 Target
1 | $ sudo iscsiadm -m discovery -t sendtargets -p 192.168.0.22:3111 |
- 连接Target
1 | $ sudo iscsiadm -m node –T iqn.2016-06.io.spdk:myNVMeDisk1 --login |
此时,iSCSI Target应该显示为SCSI磁盘。
- 使用 dmesg 命令以查看它们的状态。 在此示例中,它可能如下所示:
1 | $ dmesg |
- 还可以使用简单的bash命令在所有记录的iSCSI会话中为每个iSCSI LUN查找 /dev/sdX 节点:
1 | $ sudo iscsiadm -m session -P 3 | grep "Attached scsi disk" | awk '{print $4}' |
Reference
[1]: https://zhuanlan.zhihu.com/p/60986068
[2]: https://spdk.io/doc/iscsi.html