2021-03-04 使用SPDK部署iSCSI

iSCSI

简单的说,iSCSI是一种存储设备远程映射技术,它可以将一个远程服务器上的存储设备映射到本地,并呈现为一个块设备(大白话就是磁盘)。从普通用户的角度,映射过来的磁盘与本地安装的磁盘毫无差异。iSCSI 这个架构主要将储存装置与使用的主机分为两个部分,负责连接的软件成为启动器。而提供存储服务的计算机成为服务端,其中的软件成为目标器

  • iSCSI Target:储存设备端,存放磁盘或 RAID 的设备。
  • iSCSI Initiator:能够使用 Target 的客户端,通常是服务器。

与iSCSI类似的是NFS技术,它们都是为了解决存储资源共享的方案,只不过工作层次不一样,前者在客户机呈现的是一个块设备,后者呈现的是一个目录树。

在这篇文章中,我们将使用SPDK开发工具包的 iscsi_tgt 程序来部署iSCSI。

本文在第二章对部署步骤和常用命令进行介绍 ,第三章将演示一个完整的部署过程。

如果您想获取更详细的信息,请参考官方文档

基本概念

此部分参考了https://zhuanlan.zhihu.com/p/60986068的描述
在这里插入图片描述

  • 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结构的不同部分之间的关系.

在这里插入图片描述

将 CPU 和 iSCSI Target 绑定

SPDK使用DPDK环境抽象层来访问硬件资源,例如大内存页和CPU内核。 DPDK EAL提供了将线程分配给特定内核的功能。 为确保SPDK iSCSI目标具有最佳性能,请将NIC和NVMe设备放在同一NUMA节点上,然后将目标配置为在与该节点关联的CPU内核上运行。 以下命令行选项用于配置SPDK iSCSI Target:

 -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.
$ 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.
$ 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.
$ sudo scripts/rpc.py iscsi_create_target_node target3 target3_alias MyBdev:0 1:2 64 -d

配置iSCSI启动器

Linux启动器是open-iscsi。

# 安装open-iscsi

# 软件包Fedora: 

$ yum install -y iscsi-initiator-utils 

# Ubuntu: 

$ apt install -y open-iscsi 

发现

假设taget主机的ip地址是 10.0.0.1

$ iscsiadm -m discovery -t sendtargets -p 10.0.0.1

连接到Target

$ iscsiadm -m node --login

此时,iSCSI目标应显示为SCSI磁盘。检查dmesg以查看它们出现的情况。

断开与Target的连接

$ iscsiadm -m node --logout

删除Target节点缓存

$ iscsiadm -m node -o delete

这将导致启动器忘记所有先前发现的iSCSI目标节点。

查找iSCSI LUN的/ dev / sdX节点

$ 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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqWmwLor-1615253524598)(spdk-iscsi/nvme ssd.png)]

  • 在Target端查看挂载情况
$ ls /dev | grep nvme
nvme0
nvme0n1
  • 启动SPDK,指示操作系统放弃控制设备,让SPDK控制设备
$ cd spdk

# 运行脚本转让设备控制权给SPDK
$ sudo /scripts/setup.sh
0000:03:00.0 (15ad 07f0): nvme -> uio_pci_generic

# 查看设备状态
$ sudo scripts/setup.sh status
Hugepages
node     hugesize     free /  total
node0   1048576kB        0 /      0
node0      2048kB     1024 /   1024

Type     BDF             Vendor Device NUMA    Driver           Device     Block devices
NVMe     0000:03:00.0    15ad   07f0   0       uio_pci_generic  -          -

# 此时设备将从/dev目录下消失
$ ls /dev | grep nvme
# 无输出信息

配置iSCSI Target

  • 启动 iscsi_tgt 应用
$ sudo ./build/bin/iscsi_tgt
  • 创建ID为1的新的端口组,地址为 192.168.0.21:3111
$ sudo ./scripts/rpc.py iscsi_create_portal_group 1 192.168.0.22:3111
  • 创建一个ID为2的启动器组以接受来自0.0.0.0/0的任何连接:
$ 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

# 获取NVMe设备的地址
$ sudo ./scripts/setup.sh status
Hugepages
node     hugesize     free /  total
node0   1048576kB        0 /      0
node0      2048kB      655 /   1024

Type     BDF             Vendor Device NUMA    Driver           Device     Block devices
NVMe     0000:03:00.0    15ad   07f0   0       uio_pci_generic  -          -

# 连接本地PCIe驱动器,在系统中创建物理设备的NVMe bdev
$ sudo ./scripts/rpc.py bdev_nvme_attach_controller -b NVMe1 -t PCIe -a 0000:03:00.0
NVMe1n1

# 查看块设备
$ sudo ./scripts/rpc.py bdev_get_bdevs
...
    "name": "NVMe1n1",
    "aliases": [],
...

  • 使用先前创建的bdev构建一个目标,如LUN0(NVMe1n1),名称为“myNVMeDisk1”,别名为“My NVMe Disk1”,使用portal group 1和Initiator group 2。
$ sudo ./scripts/rpc.py iscsi_create_target_node myNVMeDisk1 "My NVMe Disk1" "NVMe1n1:0" 1:2 64 -d

配置 Initiator

  • 发现 Target
$ sudo iscsiadm -m discovery -t sendtargets -p 192.168.0.22:3111
192.168.0.22:3111,1 iqn.2016-06.io.spdk:myNVMeDisk1
  • 连接Target
$ sudo iscsiadm -m node –T iqn.2016-06.io.spdk:myNVMeDisk1 --login

此时,iSCSI Target应该显示为SCSI磁盘。

  • 使用 dmesg 命令以查看它们的状态。 在此示例中,它可能如下所示:
$ dmesg
...

[ 3032.069633] Loading iSCSI transport class v2.0-870.
[ 3032.096151] iscsi: registered transport (tcp)
[ 3096.810163] scsi host33: iSCSI initiator over TCP/IP
[ 3096.819259] scsi 33:0:0:0: Direct-Access     INTEL    NVMe disk        0001 PQ: 0 ANSI: 5
[ 3096.820165] sd 33:0:0:0: Attached scsi generic sg3 type 0
[ 3096.822238] sd 33:0:0:0: [sdb] 10485760 512-byte logical blocks: (5.37 GB/5.00 GiB)
[ 3096.822470] sd 33:0:0:0: [sdb] Write Protect is off
[ 3096.822472] sd 33:0:0:0: [sdb] Mode Sense: 83 00 00 08
[ 3096.822814] sd 33:0:0:0: [sdb] Write cache: disabled, read cache: disabled, doesn't support DPO or FUA
[ 3096.823122] sd 33:0:0:0: [sdb] Optimal transfer size 4194304 bytes
[ 3096.829189] sd 33:0:0:0: [sdb] Attached SCSI disk

...
  • 还可以使用简单的bash命令在所有记录的iSCSI会话中为每个iSCSI LUN查找 /dev/sdX 节点:
$ sudo iscsiadm -m session -P 3 | grep "Attached scsi disk" | awk '{print $4}'
sdb

Reference
[1]: https://zhuanlan.zhihu.com/p/60986068
[2]: https://spdk.io/doc/iscsi.html

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPDK(存储性能开发套件)官方文档中文版。 第一章 简介 1 1.1.什么是SPDK? 1 1.2.入门 1 1.3. Vagrant开发环境 3 1.4.更新日志(略) 6 第二章 概念 6 2.1. 用户空间驱动程序** 6 2.2. 来自用户空间的DMA** 7 2.3. 消息传递和并发** 9 2.4. NAND Flash SSD内部 13 2.5. 将I / O提交到NVMe设备** 15 2.5.1 NVMe规范 15 2.5.2 SPDK NVMe驱动程序I / O路径 15 2.6. 使用Vhost-user进行虚拟化I / O. 16 2.6.1 介绍 16 2.6.2 QEMU 17 2.6.3 设备初始化 18 2.6.4 I / O路径 19 2.6.5 SPDK优化 20 2.7. SPDK目录结构概述 20 2.8. SPDK移植指南 22 第三章 用户指南 22 3.1. 系统配置用户指南 22 3.1.1 IOMMU配置 22 3.2. SPDK应用程序概述 23 3.2.1 配置SPDK应用程序 23 3.3. iSCSI Target 26 3.3.1. iSCSI Target入门指南 26 3.3.2. 通过配置文件配置iSCSI Target 27 3.3.3. 通过RPC方法配置iSCSI Target 28 3.3.4. 配置iSCSI启动器 29 3.3.5. rpc配置示例*** 30 3.3.6. iSCSI 热插拔 32 3.4. NVMe over Fabrics Target 32 3.5. Vhost Target(略) 37 3.6 块设备用户指南 38 3.6.1 bdev介绍 38 3.6.2 通用RPC命令 38 3.6.3 Ceph RBD 39 3.6.4 压缩虚拟Bdev模块 40 3.6.5 加密虚拟Bdev模块 41 3.6.6 延迟vbdev模块 41 3.6.7 GPT(GUID分区表) 42 3.6.8 iSCSI bdev 43 3.6.9 Linux AIO bdev 43 3.6.10 OCF虚拟bdev 43 3.6.11 Malloc bdev 44 3.6.12 NULL bdev 44 3.6.13 NVMe bdev 44 3.6.14 逻辑卷Lvol 45 3.6.15 RAID 46 3.6.16 Passthru 46 3.6.17 Pmem 46 3.6.18 Virtio Block 47 3.6.19 Virtio SCSI 47 3.7 BlobFS(Blobstore文件系统) 48 3.7.1 RocksDB集成 48 3.7.2 FUSE插件 49 3.8 JSON-RPC方法(略) 49 第四章 程序员指南 49 4.1. Blobstore程序员指南 49 4.1.1 介绍 50 4.1.2 运作理论 50 4.1.3 设计注意事项 52 4.1.4 例子 54 4.1.5配置 54 4.1.6 组件细节 54 4.2. 块设备层编程指南 56 4.3 编写自定义块设备模块 58 4.3.1 介绍 58 4.3.2 创建一个新模块 59 4.3.3创建虚拟Bdev 60 4.4 NVMe over Fabrics目标编程指南 61 4.4.1 介绍 61 4.4.2 原语结构体 61 4.4.3 基础函数 62 4.4.4访问控制 62 4.4.5发现子系统 62 4.4.6 传输 63 4.4.7选择线程模型 63 4.4.8 跨CPU核心扩展 63 4.4.9 零拷贝支持 63 4.4.10 RDMA 63 4.5 Flash传输层 64 4.5.1 术语 64 4.5.2 使用方法 67 4.6 GDB宏用户指南 69 4.6.1 介绍 69 4.6.2 加载gdb宏 71 4.6.3 使用gdb数据目录 72 4.6.4 使用.gdbinit加载宏 72 4.6.5 为什么我们需要显式调用spdk_load_macros 72 4.6.6 以上可用的宏总结 73 4.6.7 添加新宏 73 4.7 SPDK “Reduce”块压缩算法 73 4.7.1 介绍 73 4.7.2 例子 74 4.8 通知库 78 第五章 基本信息 79 5.1 事件框架 79 5.1.1 事件框架设计注意事项 80 5.1.2 SPDK事件框架组件 80 5.1.3 应用框架 80 5.2 逻辑卷 81 5.2.1 术语 81 5.2.2 配置逻辑卷 84 5.3 矢量数据包处理(略) 86 第六章 杂项 86 6.1 介绍 86 6.2 NVMe的P2P API 86 6.3 确定设备支持 87 6.4 P2P问题 87 第七章 驱动程序 88 7.1 NVMe驱动程序*** 88 7.1.1 介绍 88 7.1.2 例子 88 7.1.3 公共接口 89 7.1.4 NVMe驱动程序设计 89 7.1.5 NVMe over Fabrics主机支持 91 7.1.6 NVMe多进程 91 7.1.7 NVMe Hotplug 92 7.2 I/OAT驱动程序 93 7.2.1 公共接口 93 7.2.2 关键功能 93 7.3 Virtio驱动程序 93 7.3.1 介绍 93 7.3.2 2MB大页面 93 第八章 工具 94 8.1 SPDK CLI 94 8.1.1 安装所需的依赖项 94 8.1.2 运行SPDK应用程序实例 94 8.1.3 运行SPDK CLI 94 8.1.4 可选 - 创建Python虚拟环境 94 8.2 nvme-CLI 95 8.2.1 nvme-cli with SPDK入门指南 95 8.2.2 使用场景 95 第九章 性能测试报告(略) 96 第十章NVMe-oF Target跟踪点*** 96 10.1 介绍 96 10.2 启用跟踪点 97 10.3 捕获事件的快照 97 10.4 捕获足够的跟踪事件 98 10.5 添加新的跟踪点 99
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值