坑边闲话:iSCSI 块共享协议在数据中心里应用非常广泛,许多 NAS 玩家也仅仅只会在群晖、TrueNAS 等系统上使用 GUI 进行配置。其实在标准的通用 Linux 上配置 iSCSI server 非常简单,理解了原理之后,配置所需的实际步骤其实非常少。本文详细介绍如何在 Debian 12 系统上配置 iSCSI target.

iSCSI 服务端被称为 target,在 Linux 生态中有不同的 target 代码实现,本文推荐使用现代内核支持的 LIO(Linux-IO Target),这是官方主流方案,稳定、灵活、内核级支持。

常见 target 实现的特性如下表所示。

实现方式 服务名称 管理工具 备注
LIO (Linux-IO Target) 内核模块,服务名 rtslib-fb-targetctl targetcli / targetcli-fb 默认、内核集成、现代系统首选
TGT (SCSI Target Framework) tgt 服务 tgtadm, tgt-admin 老牌项目,用户态,简单轻量,但不再积极维护
SCST scst 内核模块 + 用户空间管理工具 scstadmin 高性能、支持更复杂的 IO 策略,但配置复杂
IET (iSCSI Enterprise Target) 已废弃 iscsitarget 编辑 /etc/ietd.conf Debian 已弃用,不推荐使用

从功能深度、性能调优能力上来说,SCST 确实比 LIO 更强一些,但也更复杂、更偏向专业/高性能场景。然而 SCST 仅以内核模块形式提供,由于笔者的 ZFS 已经是内核模块形式,因此笔者不打算引入过多的存储内核模块。

有关 iSCSI, ISER (iSCSI Extensions for RDMA), SRP (SCSI RDMA Protocol) 客户端的区别,参加下图。

1
2
3
4
5
6
7
8
普通 iSCSI: 基于 TCP/IP 传统网络的 iSCSI
App → SCSI → iSCSI → TCP/IP → NIC

iSER: 对 iSCSI 的网络部分用 RDMA 网络做了替换
App → SCSI → iSCSI → **RDMA** → RDMA NIC

SRP: 直接用 RDMA 网络传输 SCSI 指令
App → **SCSI over RDMA** → RDMA NIC

1. 安装必要组件·

执行下列命令即可完成 target 所需组件的安装。

1
sudo apt install targetcli-fb

2. 配置 target·

2.1 术语概览·

  • target: 连接目标,即 iSCSI 服务器
  • initiator: 连接发起人,即 iSCSI 客户端

2.2 配置具体的 target·

配置 LIO 的 target 需要使用 targetcli 命令行工具,该工具可以支持

  • targetcli 提供的环境里交互式执行;
  • 也可以通过 targetcli 后缀指令的方式在 shell 中逐条执行。

本文以交互式方式展示。执行下列代码进入交互式环境。

1
sudo targetcli

随后按照注释分别执行各个步骤,完成后端存储存储创建、target 创建、门户监听、认证、ACL 鉴权等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# --------------------------------------------------------------------------------------
# 步骤 1: 配置后端存储 (Backstore)
# --------------------------------------------------------------------------------------

# 创建一个名为 "dropbox" 的块设备后端存储,并关联到指定的 ZFS 卷。
/backstores/block create name=dropbox dev=/dev/zvol/Samsung_990Pro_Stripe/dropbox

# --------------------------------------------------------------------------------------
# 步骤 2: 配置 iSCSI Target
# --------------------------------------------------------------------------------------

# 创建一个 iSCSI Target,并为其指定全局唯一的 IQN 名称 (服务器的身份标识)。
/iscsi create iqn.2019-08.cn.littlenewton:gtr7-debian

# --------------------------------------------------------------------------------------
# 步骤 3: 在 Target 中创建 LUN、Portal 和 ACL
# --------------------------------------------------------------------------------------

# 在 Target 的 TPG1 中创建一个 LUN (默认为 LUN 0),并将其链接到之前创建的 "dropbox" 后端存储。
/iscsi/iqn.2019-08.cn.littlenewton:gtr7-debian/tpg1/luns create /backstores/block/dropbox

# 创建一个网络门户 (Portal),让 Target 在所有 IPv4 地址的 3260 端口上监听连接请求。
/iscsi/iqn.2019-08.cn.littlenewton:gtr7-debian/tpg1/portals create 0.0.0.0 3260

# 创建一个访问控制列表 (ACL),只允许来自指定 IQN (客户端 "gtr7-win10") 的连接。
/iscsi/iqn.2019-08.cn.littlenewton:gtr7-debian/tpg1/acls create iqn.2019-08.cn.littlenewton:gtr7-win10

# 设置 TPG 的属性:关闭 CHAP 认证,意味着连接验证完全依赖于上面的 ACL (IQN 白名单)。
/iscsi/iqn.2025-07.com.example:dropbox/tpg1 set attribute authentication=0

# 将 TPG1 中的 LUN 0 映射给这个特定的 ACL,这样授权的客户端才能真正看到这个磁盘。
/iscsi/iqn.2019-08.cn.littlenewton:gtr7-debian/tpg1/acls/iqn.2019-08.cn.littlenewton:gtr7-win10 create mapped_lun=0 tpg_lun=0

# --------------------------------------------------------------------------------------
# 步骤 4: 保存配置
# --------------------------------------------------------------------------------------

# 保存当前配置,使其在系统重启后依然生效。
saveconfig

2.2.1 准备后端存储·

后端存储一般指的是本地的某个块设备,比如

  • 磁带机
  • ZFS 的某个 ZVol
  • LVM 的某个 LV
  • 本地的某个具体的 HDD, SSD 等

只要该设备是块设备,即可通过 iSCSI 共享出去。

然而,在 targetcli 的上下文中,backstore 是一个关联到某个具体块设备的独立抽象概念,它有自己的名字。

2.2.2 设置 iSCSI target·

我们先想象一个更复杂的、高可用的存储环境:

  • 你有一台存储服务器,但它有两个控制器(Controller A 和 Controller B),以防其中一个坏掉。
  • 每个控制器都有自己的网络端口。
  • 客户端(Initiator)可以看到通往同一个 LUN(磁盘)的多条路径(Path),一条通过 Controller A,另一条通过 Controller B。

这时问题来了:客户端应该使用哪条路径?两条路径的性能和状态一样吗?

ALUA 就是用来解决这个问题的。 它允许存储目标器(target)告诉客户端(initiator)每一条路径的状态。常见的状态有:

  • Active/Optimized (活动/优化): 这是首选路径。读写速度最快,延迟最低。
  • Active/Unoptimized (活动/非优化): 这条路径也能用,但是性能较差(例如,数据需要通过控制器之间的内部链接转发)。它通常作为备用路径。
  • Standby (备用): 这条路径当前不可用,但如果主路径失效,它可以被激活。
  • Unavailable (不可用): 路径已断开或有故障。

而 Target Port Group (目标端口组) 就是实现这个机制的工具。 服务器将所有具有相同路径状态的目标端口(Portals)放到同一个组里。例如:

  • tg_pt_gp_A (我们自己命名的组) 可能包含 Controller A 上的所有端口,状态为 Active/Optimized。
  • tg_pt_gp_B 可能包含 Controller B 上的所有端口,状态为 Active/Unoptimized。

当客户端连接时,它会查询这些组的状态,然后智能地选择最优的路径(Active/Optimized)来发送 I/O 请求,同时知道如果主路径失效,可以切换到次优路径(Active/Unoptimized)。

即使在本文描述的如此简单的单路径环境中:

  • 只有一台服务器。
  • 只有一个 iSCSI Target。
  • 只有一个 TPG (tpg1)。
  • 只有一个 Portal (0.0.0.0:3260)

LIO Target(Linux 的 iSCSI 内核模块)仍然使用 ALUA 框架来描述路径状态。

2.2.3 设置 iSCSI ACL·

ACL(Access Control List,访问控制列表)用于控制哪些 initiator(发起端)有权限访问指定的 target(目标端)。iSCSI 默认采用“白名单”策略:只有被明确列入 ACL 的 initiator 名称,才被允许连接到对应的 target. 若 ACL 为空,则代表拒绝所有 initiator 连接该 target(即默认拒绝)。为了增强安全性,通常需要结合 CHAP(Challenge-Handshake Authentication Protocol)认证机制共同使用。

需要注意的是,这里的 ACL 控制 并不涉及身份验证,仅仅是基于 Initiator IQN 的访问限制。这意味着安全性有限,因为 initiator 名称是可以在客户端随意伪造或修改的,因此依赖 ACL 并不能提供真正的安全隔离。建议在生产环境中始终搭配 ACL 和 CHAP 双重机制,以避免伪造 initiator 名称所带来的潜在风险。

2.2.4 最终效果展示·

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
sudo targetcli ls
o- / ......................................................................................................................... [...]
o- backstores .............................................................................................................. [...]
| o- block .................................................................................................. [Storage Objects: 1]
| | o- dropbox ........................................... [/dev/zvol/Samsung_990Pro_Stripe/dropbox (2.0TiB) write-thru activated]
| | o- alua ................................................................................................... [ALUA Groups: 1]
| | o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
| o- fileio ................................................................................................. [Storage Objects: 0]
| o- pscsi .................................................................................................. [Storage Objects: 0]
| o- ramdisk ................................................................................................ [Storage Objects: 0]
o- iscsi ............................................................................................................ [Targets: 1]
| o- iqn.2019-08.cn.littlenewton:gtr7-debian ........................................................................... [TPGs: 1]
| o- tpg1 .................................................................................................. [gen-acls, no-auth]
| o- acls .......................................................................................................... [ACLs: 1]
| | o- iqn.2019-08.cn.littlenewton:gtr7-win10 ............................................................... [Mapped LUNs: 1]
| | o- mapped_lun0 ............................................................................... [lun0 block/dropbox (rw)]
| o- luns .......................................................................................................... [LUNs: 1]
| | o- lun0 ..................................... [block/dropbox (/dev/zvol/Samsung_990Pro_Stripe/dropbox) (default_tg_pt_gp)]
| o- portals .................................................................................................... [Portals: 1]
| o- 0.0.0.0:3260 ..................................................................................................... [OK]
o- loopback ......................................................................................................... [Targets: 0]
o- vhost ............................................................................................................ [Targets: 0]
o- xen-pvscsi ....................................................................................................... [Targets: 0]

总结·

本文详细介绍了在 Linux 上部署 Linux-IO 类型的 iSCSI target 的全过程。

由于服务器性能比较复杂而且不需要特别高的性能,因此本文忽略了 benchmark 展示部分。实际上,本文所使用的软硬件架构非常复杂,不属于常规操作。

  • 宿主机:零刻 GTR7
  • CPU & Mem: AMD 7840HS, 32GB DDR5 5600MHz SODIMM *2
  • 硬盘:Samsung 990 Pro 4TB
  • 宿主机系统 & 虚拟化方案:Windows 10 Pro, Hyper-V
  • 虚拟机:Debian 12
  • 虚拟机磁盘:使用 Hyper-V 物理磁盘,将 Samsung 990 Pro 4TB 映射给虚拟机使用。

在该场景下,Windows 10 宿主机通过 Hyper-V 网络连接虚拟机的 iSCSI targe,存储吞吐可以达到 1.1GB/s 以上,足以满足 Dropbox 网盘的文件存储需求。不过后来在升级了 ZFS、宿主机之后,吞吐性能有很大下降,由于缺乏控制变量的条件,所以暂且不做深入分析