1. 项目概述:从本地硬盘到网络存储的进化
如果你还在为服务器扩容需要关机、插拔硬盘而烦恼,或者觉得NAS的SMB/NFS共享在虚拟机、数据库这类对磁盘性能有极致要求的场景下有点“力不从心”,那么是时候重新认识一下iSCSI了。这个诞生于21世纪初的技术,在今天依然焕发着强大的生命力,尤其是在追求高性能、低延迟和集中化存储管理的场景里。简单来说,iSCSI(Internet Small Computer System Interface)就是把SCSI指令“装进”TCP/IP包里,让客户端可以通过普通的以太网,像使用本地SCSI硬盘一样,去访问远端的存储设备。你得到的不是一个共享文件夹,而是一整块“赤裸裸”的、未经格式化的原始磁盘。这对于需要直接管理文件系统的应用,比如VMware ESXi的虚拟机磁盘、微软Hyper-V的虚拟硬盘、Oracle数据库的裸设备,或者任何需要稳定、低延迟块级存储的服务,都是绝佳的选择。
最近,随着像“飞牛”这类新兴NAS系统的流行,其内置的iSCSI配置功能也成为了讨论热点。同时,在稳定的Debian 10系统上部署iSCSI服务,也是很多技术爱好者构建家庭实验室或小型企业存储方案的首选。无论是想在你的飞牛NAS上划出一块高速空间给ESXi,还是在闲置的Debian老机器上搭建一个iSCSI存储服务器,其核心逻辑都是一致的:服务端(Target)提供存储“靶子”,客户端(Initiator)发起连接“射箭”。接下来,我将以一个资深运维的视角,带你从零开始,彻底搞懂iSCSI网络磁盘的部署、优化和排错,分享那些只有踩过坑才知道的实战细节。
2. iSCSI核心架构与方案选型深度解析
2.1 为什么是iSCSI?场景与协议对比
在决定使用iSCSI之前,我们必须清楚它解决的是什么问题,以及和NFS、SMB/CIFS这些更常见的文件级共享协议有什么区别。这决定了你的技术选型是否精准。
块存储 vs. 文件存储:这是最根本的区别。想象一下,NFS/SMB给你的是一个已经装修好的“房间”(目录),你只能在这个房间里放家具(文件)。而iSCSI给你的是一块“毛坯地皮”(裸设备),你需要自己决定这块地皮上盖什么房子(格式化为什么文件系统),怎么隔间(分区)。因此,iSCSI提供的磁盘,在客户端操作系统看来,就是/dev/sdb、/dev/sdc这样的物理磁盘设备,你可以对它进行fdisk、mkfs、mount等所有本地磁盘能做的操作。这种特性使得它在以下场景无可替代:
- 虚拟化平台:ESXi、Hyper-V、Proxmox VE等需要将虚拟机磁盘文件(VMDK, VHD)存放在高性能共享存储上,以实现vMotion、HA等高可用功能。
- 数据库服务器:像MySQL、PostgreSQL等数据库,将数据目录放在iSCSI磁盘上,可以获得接近本地SSD的I/O性能,同时便于集中备份和扩容。
- 磁盘密集型应用:如视频编辑、科学计算等需要连续大块读写的工作负载。
- 无盘工作站/服务器引导:客户端可以从iSCSI磁盘直接启动操作系统,实现集中化管理。
与FC(光纤通道)的对比:在企业级领域,iSCSI常被拿来与FC-SAN对比。FC性能极致(低微秒级延迟、高带宽),但成本高昂,需要专用的HBA卡和光纤交换机。iSCSI最大的优势就是以太网。它跑在廉价的、技术普及的千兆/万兆以太网上,管理和维护门槛大大降低,对于中小型环境而言,是性价比最高的SAN(存储区域网络)解决方案。
方案选型考量:在Linux世界里,iSCSI的实现主要有两大阵营:LIO(Linux-IO Target)和SCST(SCSI Target Subsystem)。从主流发行版(如RHEL/CentOS、Debian/Ubuntu)的默认选择来看,LIO已经成为事实上的标准(通过targetcli工具管理)。它内核原生支持,性能稳定,功能完整。因此,我们的实战也将基于LIO来展开。对于客户端,Linux系统自带open-iscsi软件包,它是标准的Initiator实现。
2.2 环境规划与硬件网络建议
在动手之前,合理的规划能避免后期很多性能瓶颈和管理混乱。
- 网络隔离(强烈建议):iSCSI流量应该与你的业务网络(如Web访问、数据库连接)分离开。最佳实践是使用独立的网卡和交换机,组建一个专用的存储网络。即使条件有限,也应在交换机上为iSCSI流量划分独立的VLAN。这能有效避免网络拥塞导致的存储延迟飙升,影响所有连接的客户端。
- MTU与巨帧(Jumbo Frames):这是提升iSCSI性能最关键的网络调优项。标准以太网MTU是1500字节。启用巨帧(如设置为9000)后,一个TCP包可以承载更大的数据块,显著降低协议开销和CPU中断次数,从而提升吞吐量、降低延迟。注意:这需要存储服务器、客户端以及中间所有交换机的对应端口都启用相同的MTU值,否则会导致分片或丢包。
# 在服务端和客户端临时设置MTU sudo ip link set eth1 mtu 9000 # 永久配置需修改 /etc/network/interfaces 或 Netplan/NetworkManager 配置 - 磁盘选择:服务端的存储后端至关重要。对于性能要求高的场景,SSD(尤其是NVMe SSD)是不二之选。如果容量需求大,用多块HDD组建RAID(如RAID 10)也能提供不错的性能和冗余。避免使用单块机械硬盘作为关键业务的iSCSI后端,其随机IOPS可能成为整个系统的瓶颈。
- 命名规范:提前规划好Target名称(IQN)、LUN编号等。清晰的命名有助于后期维护。IQN格式通常为:
iqn.YYYY-MM.com.example:storage:diskarraysn-123456。你可以将其中的com.example替换为你自己的域名倒序。
3. 服务端(Target)部署与核心配置实战
我们将以Debian 10/11系统为例,部署基于LIO的iSCSI Target服务。这个过程在“飞牛”等NAS系统的后台,本质上也是类似的封装。
3.1 软件安装与基础服务搭建
首先,更新系统并安装必要的软件包:
sudo apt update sudo apt upgrade -y sudo apt install -y targetcli-fb dbus这里安装的是targetcli-fb,它是targetcli的一个功能分支,提供了更友好的交互式Shell。安装完成后,启动并启用服务:
sudo systemctl start target sudo systemctl enable target sudo systemctl start targetcli sudo systemctl enable targetcli现在,运行sudo targetcli命令,你会进入一个交互式的配置Shell。所有配置改动都会实时生效并保存。
3.2 使用targetcli创建后端存储与Target
进入targetcliShell后,你会看到一个树形结构。我们按步骤操作:
步骤1:创建后端存储对象(Backstore)后端存储决定了iSCSI“虚拟磁盘”的数据实际存放在哪里。有多种类型:
- fileio:在现有文件系统上创建一个镜像文件作为磁盘。灵活方便,适合测试和小规模使用。
- block:直接使用一个块设备(如
/dev/sdb1或/dev/mapper/vg0-lv_iscsi)。性能最好,是生产环境首选。 - pscsi:直通物理SCSI设备(不常用)。
- ramdisk:使用内存,速度极快但断电丢失(用于特殊测试)。
我们以创建一个1GB的fileio为例:
/> cd /backstores/fileio /backstores/fileio> create disk01 /var/lib/iscsi_disk/disk01.img 1G Created fileio disk01 with size 1073741824注意:生产环境强烈建议使用block类型,并指向一个LVM逻辑卷或RAID设备,便于后期扩容。例如,如果你有一个LVM卷/dev/vg_iscsi/lv_data,可以这样做:
/> cd /backstores/block /backstores/block> create block_disk01 dev=/dev/vg_iscsi/lv_data步骤2:创建iSCSI TargetTarget就是客户端要连接的目标。
/> cd /iscsi /iscsi> create iqn.2024-08.com.yourdomain:server.target01 Created target iqn.2024-08.com.yourdomain:server.target01. Created TPG 1.系统会自动创建一个TPG(Target Portal Group,目标门户组)1。
步骤3:创建LUN并关联存储LUN(Logical Unit Number)是Target内部给存储单元的逻辑编号。我们将之前创建的disk01关联到这个Target的LUN 0上。
/iscsi> cd iqn.2024-08.com.yourdomain:server.target01/tpg1/luns /iscsi/iqn.20...t01/tpg1/luns> create /backstores/fileio/disk01 Created LUN 0.步骤4:设置访问控制(ACL)默认情况下,Target拒绝所有Initiator连接。我们必须设置ACL,允许特定的客户端连接。首先需要知道客户端的Initiator名称。 在客户端机器上,查看或初始化Initiator名称:
sudo cat /etc/iscsi/initiatorname.iscsi # 如果文件不存在或内容为空,可以生成一个 sudo echo "InitiatorName=iqn.2024-08.com.yourdomain:client.initiator01" > /etc/iscsi/initiatorname.iscsi假设客户端的IQN是iqn.2024-08.com.yourdomain:client.initiator01,回到服务端的targetcli:
/iscsi/iqn.20...t01/tpg1> cd acls /iscsi/iqn.20...t01/tpg1/acls> create iqn.2024-08.com.yourdomain:client.initiator01 Created Node ACL for iqn.2024-08.com.yourdomain:client.initiator01步骤5:创建门户(Portal)并监听IP门户定义了服务端在哪个IP和端口上监听连接。默认会在所有IP(0.0.0.0)的3260端口监听。如果你有多个网卡,建议绑定到存储网络的专用IP上。
/iscsi/iqn.20...t01/tpg1> cd portals /iscsi/iqn.20...t01/tpg1/portals> delete 0.0.0.0 3260 # 先删除默认的 Deleted network portal 0.0.0.0:3260 /iscsi/iqn.20...t01/tpg1/portals> create 192.168.100.10 # 绑定到存储网络IP Using default IP port 3260 Created network portal 192.168.100.10:3260.步骤6:设置CHAP认证(可选但推荐)为了安全,强烈建议启用CHAP双向认证。这需要为Target设置一个“密码”,并为每个允许的ACL设置一对用户名密码。
/iscsi/iqn.20...t01/tpg1> set attribute authentication=1 demo_mode_write_protect=0 generate_node_acls=0 cache_dynamic_acls=1 # 开启认证 /iscsi/iqn.20...t01/tpg1> cd / /> cd /iscsi/iqn.2024-08.com.yourdomain:server.target01/tpg1/acls/iqn.2024-08.com.yourdomain:client.initiator01 # 为该ACL设置CHAP密码 /> set auth userid=myclientusername Parameter userid is now 'myclientusername'. /> set auth password=YourStrongClientPassword123 Parameter password is now 'YourStrongClientPassword123'. # 设置反向CHAP(Target对Initiator的认证) /> set auth mutual_userid=mytargetusername Parameter mutual_userid is now 'mytargetusername'. /> set auth mutual_password=YourStrongTargetPassword123 Parameter mutual_password is now 'YourStrongTargetPassword123'.最后,输入ls查看整个配置树,确认无误后,输入exit退出。targetcli会自动保存配置到/etc/target/saveconfig.json。
实操心得:在
targetcli里,所有路径都支持Tab补全,这能极大提高配置效率。另外,生产环境中,建议将/etc/target/saveconfig.json纳入版本控制或定期备份,因为它是所有iSCSI Target配置的载体。
4. 客户端(Initiator)连接与磁盘挂载全流程
服务端配置好后,我们切换到客户端(同样是Debian系统)进行操作。
4.1 安装与发现目标
首先安装客户端软件:
sudo apt update sudo apt install -y open-iscsi确保/etc/iscsi/initiatorname.iscsi文件中的名称与服务端ACL里设置的一致。然后,启动服务并让服务端发现(Discovery)我们:
sudo systemctl start open-iscsi sudo systemctl enable open-iscsi # 执行发现,指向服务端的IP sudo iscsiadm -m discovery -t st -p 192.168.100.10如果配置正确,你会看到类似输出:192.168.100.10:3260,1 iqn.2024-08.com.yourdomain:server.target01。这表示客户端已经发现了服务端上的Target。
4.2 登录与建立连接
接下来,登录到发现的Target:
sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 --login如果服务端配置了CHAP认证,需要在登录前将认证信息写入节点配置:
sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 -o update -n node.session.auth.authmethod -v CHAP sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 -o update -n node.session.auth.username -v myclientusername sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.100.100.10 -o update -n node.session.auth.password -v YourStrongClientPassword123 sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 -o update -n node.session.auth.username_in -v mytargetusername sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 -o update -n node.session.auth.password_in -v YourStrongTargetPassword123 # 然后再执行登录 sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 --login登录成功后,使用lsblk或fdisk -l命令,你应该能看到一个新的磁盘设备,例如/dev/sdb。它现在就是一块纯粹的“网络物理硬盘”。
4.3 分区、格式化与自动挂载
现在,你可以像对待本地硬盘一样操作它:
# 1. 分区 (使用fdisk或parted) sudo fdisk /dev/sdb # 在fdisk交互界面中,按 n 创建新分区,然后一路默认或按需设置,最后按 w 写入。 # 2. 创建文件系统 sudo mkfs.ext4 /dev/sdb1 # 假设创建了第一个分区sdb1,格式化为ext4 # 3. 创建挂载点并挂载 sudo mkdir -p /mnt/iscsi_data sudo mount /dev/sdb1 /mnt/iscsi_data为了让系统开机自动连接iSCSI磁盘并挂载,需要多做一些配置:
- 设置节点自动登录:
sudo iscsiadm -m node -T iqn.2024-08.com.yourdomain:server.target01 -p 192.168.100.10 -o update -n node.startup -v automatic - 配置自动挂载:修改
/etc/fstab文件,添加一行。这里有个大坑:不能直接用/dev/sdb1,因为设备名可能在每次启动时变化。必须使用磁盘的唯一标识符,如UUID或磁盘路径ID。
关键参数# 首先查看分区的UUID sudo blkid /dev/sdb1 # 输出示例:/dev/sdb1: UUID="a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8" TYPE="ext4" # 然后在 /etc/fstab 中添加 UUID=a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8 /mnt/iscsi_data ext4 _netdev,defaults 0 2_netdev:这个选项告诉系统,这个文件系统位于网络设备上,必须在网络就绪之后再尝试挂载。没有这个选项,系统启动时会因为网络未就绪而挂载失败,导致系统启动卡住。
注意事项:对于数据库或关键服务,不建议在
fstab中使用_netdev后就简单了事。更可靠的做法是编写一个Systemd服务单元,该服务After=network-online.target和iscsi.service,并在其中执行挂载命令,这样可以更精确地控制依赖关系和挂载重试逻辑。
5. 性能调优、监控与日常维护指南
配置完成只是第一步,要让iSCSI稳定高效地运行,调优和监控必不可少。
5.1 关键性能参数调优
在客户端(Initiator)端,可以调整/etc/iscsi/iscsid.conf中的参数来优化性能:
node.session.timeo.replacement_timeout = 120:增加替换超时,在网络不稳定时避免过早断开。node.conn[0].timeo.noop_out_interval = 10和node.conn[0].timeo.noop_out_timeout = 30:调整心跳检测间隔和超时,保持连接活跃。node.session.iscsi.InitialR2T = No和node.session.iscsi.ImmediateData = Yes:启用立即数据,减少小型写操作的延迟。node.session.iscsi.FirstBurstLength = 262144和node.session.iscsi.MaxBurstLength = 16776192:增大突发长度,提升大块连续读写的吞吐量。这些值需要根据网络MTU调整,通常设置为MTU的整数倍减开销。
关于多路径(Multipathing):如果客户端有多个网络路径连接到Target(例如两张网卡绑定或两个独立IP),配置多路径I/O(使用multipath-tools)可以同时提供负载均衡和故障切换,这是生产环境高可用的标配。配置稍复杂,需要服务端和客户端共同设置不同的门户,并使用相同的多路径标识符。
5.2 状态监控与日志排查
- 查看会话状态:
这个命令会打印出详细的会话信息,包括连接状态、传输的字节数、当前IQN等,是检查连接健康度的首选。sudo iscsiadm -m session -P 3 - 服务端查看连接:在服务端的
targetcli中,进入对应Target的TPG,可以查看connections信息。 - 日志文件:
- 服务端:
/var/log/syslog或journalctl -u target - 客户端:
/var/log/syslog或journalctl -u open-iscsi当连接出现问题时,首先查看这些日志,通常会有明确的错误信息。
- 服务端:
5.3 扩容与备份策略
扩容:如果后端存储是LVM,这是最优雅的方式。在服务端,直接扩展LVM逻辑卷的大小,然后在targetcli中,进入对应的block存储对象,使用set attribute dev_size=new_size_in_bytes命令更新大小。客户端需要重新扫描SCSI总线(sudo rescan-scsi-bus.sh或echo 1 > /sys/class/block/sdb/device/rescan),然后使用growpart和resize2fs(针对ext4)等工具在线扩展分区和文件系统。
备份:iSCSI磁盘是块设备,不能像文件一样简单复制。可靠的备份方法包括:
- 在客户端使用LVM:将iSCSI磁盘作为物理卷加入VG,然后对LV做快照,备份快照。
- 在服务端使用存储快照:如果后端是ZFS、Btrfs或支持快照的硬件RAID,可以在服务端创建存储级快照,然后将其以只读方式导出为新的LUN,供备份服务器挂载。
- 使用
dd或rsync文件级备份:在客户端挂载文件系统后,使用rsync进行增量备份。对于需要崩溃一致性的数据库,务必先将其置于热备份模式或停止服务。
6. 常见问题与故障排查实录
即使配置再仔细,在实际运行中也可能遇到各种问题。这里记录几个我踩过的坑和解决方法。
问题1:客户端登录失败,提示“Login failed with status 0x0200000b”或“initiator reported error (24 - iSCSI login failed due to authorization failure)”
- 排查:这几乎总是CHAP认证问题。
- 解决:
- 仔细核对服务端ACL里设置的
userid/password和客户端节点配置里的username/password,确保完全一致,包括大小写。 - 检查服务端Target的
authentication属性是否已设置为1。 - 在客户端,可以尝试先删除节点配置重新发现:
sudo iscsiadm -m node -T [TARGET_IQN] -p [SERVER_IP] --op delete,然后重新执行发现和配置登录信息。
- 仔细核对服务端ACL里设置的
问题2:连接不稳定,偶尔断线,系统日志中出现“connection timeout”或“dropping connection”
- 排查:网络问题或参数不匹配。
- 解决:
- 首先用
ping -s 8972 [对端IP](假设MTU=9000)测试大包连通性,检查是否因巨帧配置不一致导致分片。 - 检查交换机端口是否有错误计数(error counter)。
- 适当增加客户端的
noop_out_interval和replacement_timeout值,给网络波动留出容错空间。 - 如果使用了绑定(bonding)网卡,确认模式(如mode=4 LACP)是否配置正确。
- 首先用
问题3:客户端重启后,iSCSI磁盘挂载失败,系统进入紧急模式
- 排查:
/etc/fstab配置错误,最可能的原因是缺少_netdev参数,或者使用了易变的/dev/sdX设备名。 - 解决:
- 进入单用户模式或救援模式。
- 检查
/etc/fstab,确保使用UUID或磁盘ID,并已添加_netdev选项。 - 检查网络和
open-iscsi服务是否正常启动,手动执行iscsiadm --login测试。 - 可以考虑将挂载动作移至一个自定义的Systemd服务中,依赖关系更清晰。
问题4:写入性能远低于预期,尤其是小文件随机写入
- 排查:可能是由于同步写入(Barrier)或日志模式导致。
- 解决:
- 在客户端挂载文件系统时,可以尝试添加
nobarrier(针对ext4)和data=writeback(针对ext4,牺牲一些安全性换取性能)等选项。注意:这会在断电时增加数据损坏风险,请根据业务容忍度评估。 - 确保服务端后端存储(如HDD)没有处于节能模式或存在严重瓶颈。
- 使用
fio或ioping工具进行基准测试,隔离网络延迟和磁盘IO延迟。
- 在客户端挂载文件系统时,可以尝试添加
问题5:在服务端删除了一个LUN或Target,但客户端依然能看到旧设备
- 排查:客户端有缓存。
- 解决:
- 在客户端登出并删除节点:
sudo iscsiadm -m node -T [TARGET_IQN] -p [SERVER_IP] -u(登出),然后sudo iscsiadm -m node -T [TARGET_IQN] -p [SERVER_IP] -o delete。 - 有时需要刷新SCSI设备列表:
sudo rescan-scsi-bus.sh -r。 - 最彻底的方法是重启客户端的
open-iscsi服务。
- 在客户端登出并删除节点:
iSCSI的配置就像搭积木,每一层(网络、服务端、客户端)都需要稳固。我的经验是,在任何一个复杂系统里,清晰的文档记录和变更管理比技术本身更重要。每次修改服务端配置前,不妨用targetcli的saveconfig [filepath]命令备份一下当前配置。对于客户端,将那些复杂的iscsiadm命令写成脚本,并附上详细的注释。当你在凌晨三点被叫起来处理存储故障时,这些记录就是你最好的救星。最后,在将任何iSCSI存储用于生产数据库或虚拟化之前,务必在测试环境中进行长时间的压力测试和故障模拟(如拔网线、重启服务端),真正理解其行为边界和恢复流程,这比任何理论都来得实在。