1. 从一个存储整合需求说起,为什么是iSCSI
搞IT运维的这几年,我被问过最多的问题之一就是“怎么把分散在几台服务器上的硬盘空间统一利用起来”。前几年某公司上了虚拟化平台,二十几台虚拟机跑在五台物理机上,每台物理机都塞了几块数据盘,互相不通,管理起来想死的心都有。有人提出上存储阵列,一打听价格,几路销售报完价直接劝退;也有人建议上分布式文件系统,但结合当时的业务复杂度,运维团队评估下来,维护成本明显超过收益。最后我们选了iSCSI,用几台普通服务器加万兆网卡,搭了一套网络存储服务,把存储整合、虚拟机磁盘迁移、备份存储三大需求一次解决,效果到今天都很稳。
实际上iSCSI(Internet Small Computer System Interface)的核心思路很简单:把SCSI命令封装进TCP/IP数据包,让服务器可以像使用本地SCSI/FC磁盘一样,通过网络去使用远端存储设备上的逻辑卷。换句话说,它是把“存储网络”和“局域网”合二为一的技术,底层用的就是大家再熟悉不过的以太网和IP协议,不需要昂贵的光纤交换机、专用的HBA卡,也不需要单独建一套存储网络。
这篇文章的受众,我想应该是三类人:一是刚接触网络存储的系统工程师,需要快速搭建一套可以落地的共享存储;二是虚拟化平台的维护人员,想理解磁盘迁移和虚拟机热迁移背后的存储逻辑;三是对分布式存储没有强需求,但希望用低成本、标准化的方式完成存储整合的中小规模场景负责人。全文从原理讲起,逐步拆解服务端和客户端的完整配置,最后附上我实践过程中踩过的一些坑和调优经验,保证你能从零开始搭出一套可用的iSCSI网络存储服务。
需要说明的是,实践部分我以Linux环境(服务端用Linux发行版自带的LIO/Linux-IO Target,客户端覆盖Windows和Linux两种)作为主线,因为这是目前最灵活、最不依赖商业授权、也最容易理解全流程的方案。
2. 真正理解iSCSI:几个名词和一次完整的数据流转
2.1 你必须先搞懂的六个关键名词
在动手敲命令之前,我习惯先把名词理顺,因为期初不搞懂这些,配置时极易混。iSCSI涉及的概念不算多,但每个都和配置项对应。
Initiator(发起端):主动发起存储访问请求的一端,通常是应用服务器或虚拟化宿主机。它相当于“客户端”,把远端的一块盘当成自己的本地盘来使用。
Target(目标端):存储服务的提供方,就是真正保存数据的那一端,通常是一台存储服务器或者带存储功能的服务器。它把本地的一块物理磁盘、一个分区、一个RAID卷或者一个LVM逻辑卷,通过iSCSI协议共享出去。
IQN(iSCSI Qualified Name):类似身份证号,用于在网络上唯一标识一个发起端或目标端。格式一般是iqn.年份-月份.反向域名:设备标识,比如iqn.2024-12.com.example:storage-target-01。你在配置连接时要用的这个字符串必须保证全局唯一,不能瞎编。
LUN(Logical Unit Number):目标端导出的可访问存储单元,发起端看到并格式化使用的就是LUN。通常一个被共享出去的卷就是一个LUN。LUN既可以是整块物理磁盘,也可以是一个逻辑卷,还可以是文件模拟出来的镜像文件。对于虚拟化场景,我们一般把LUN直接映射给虚拟机作为数据盘或系统盘。
Portal(门户):可以简单理解为Target的“门牌号”,是IP加端口的组合。默认端口是3260,发起端通过发现Portal来找到Target,然后发起连接。
MPIO(Multipath I/O,多路径输入输出):当一台服务器同时有多块网卡连接存储时,通过MPIO建立多条数据会话,让I/O在多条路径上分担负载或故障切换。这是在低成本硬件上实现存储链路高可用的重要手段。
2.2 一次完整的iSCSI数据流转,到底发生了什么
如果只是配置完就直接用,很多问题会藏在细节里。我一直建议学生或者团队成员先画一条数据链路图,搞明白每一步到底发生了什么。
假设一台Web服务器(Initiator)要读取数据库存储服务器(Target)上的一个数据块:
- Web服务器上的应用程序调用了
read()系统调用,文件系统根据逻辑地址偏移量,把请求转换为对块设备的一个SCSI READ命令。 - 系统内的iSCSI驱动层把SCSI命令封装为iSCSI协议数据单元(iSCSI PDU),然后交给TCP/IP协议栈,走以太网发出去。
- PDU在网络中经过交换机(甚至多跳路由)到达目标端服务器的网卡。
- 存储服务器的iSCSI Target服务(LIO等)接收到PDU后,把它还原成SCSI命令,由本地SCSI层向真实块设备发起I/O操作。
- 数据从磁盘读上来后,Target把数据连同状态返回的信息一起封装成新的iSCSI PDU,回传给发起端。
这一来一回,就是一次完整的读操作。这也就解释了一个很关键的点:iSCSI的性能高低,既取决于存储磁盘本身,也取决于网络时延、TCP/IP协议栈开销、网卡中断处理和PDU封装解封装的效率。这也是为什么很多人换了万兆网卡后性能飞升,因为瓶颈常常在网络,而非磁盘。
2.3 iSCSI、FC SAN、NFS到底怎么选
聊完基本概念,我忍不住说一下方案选型的问题。网上很多文章喜欢把iSCSI直接定义为“便宜货”,事实并非如此。在我做过的项目中,大多数场景下iSCSI的综合性价比远远高于FC SAN,而且生态成熟程度不比FC差多少。
给你一个我当时用来给团队做决策的对比表:
| 维度 | iSCSI | FC SAN | NFS/CIFS |
|---|---|---|---|
| 传输层 | TCP/IP,标准以太网 | 专用光纤通道协议 | TCP/IP,标准以太网 |
| 硬件成本 | 低(仅需服务器+普通交换机/网卡) | 高(FC交换机、HBA卡、光纤) | 低 |
| 单机性能 | 中高(万兆下接近本地盘) | 非常高 | 中 |
| 使用方式 | 块设备,可做文件系统、裸设备 | 块设备 | 文件共享,有文件锁和权限语义 |
| 适合场景 | 虚拟化磁盘、数据库数据盘、备份库 | 高端核心业务数据库 | 文件共享、跨平台访问、备份归档 |
如果你只是想让几台Linux服务器共享一堆文件,NFS可能更合适,因为它自带文件锁定机制;如果预算充足、核心数据库的响应时间必须低到微秒级别,FC有它的价值;但如果你要把磁盘直接交给虚拟机做数据盘,需要它能被格式化为任意文件系统,甚至要作为裸设备跑Oracle RAC这类场景,那iSCSI几乎是性价比最优解——它提供的是标准块设备,语义上和本地SCSI盘一致。
3. 部署前的规划和环境准备,这一步不能省
3.1 存储架构怎么划,网络怎么隔离
很多新手一上来就在生产服务器上直接做实验,踩了坑才回头补课。我在正式部署前,一般会用一张架构草稿图把存储网络理清楚,我这里用文字描述一下这个架构:
整个环境分为两段网络。业务网络是服务器集群的上联网络,负责对外提供服务,用普通千兆或者万兆交换机。存储网络是连接应用服务器和存储服务器的专属VLAN,只跑iSCSI流量,隔离掉业务广播包和用户流量。这样隔离有两个好处:第一,iSCSI的TCP流不会受到业务突发流量的干扰,性能更稳定;第二,安全层面上,非授权设备无法直接访问存储网络。如果条件允许,iSCSI流量应当走独立的物理交换机,双机冗余则用链路聚合或者MPIO。
存储侧的规划,我建议直接用LVM管理,将多块物理盘组成卷组,按需切割逻辑卷作为不同的LUN。原因很简单:LVM支持在线扩容、快照,后续做存储裁剪和迁移都非常灵活。不要直接把裸块设备共享给iSCSI Target,那样后续一个LUN想缩容或者扩展,会痛苦无比。
3.2 硬件的四个建议,尤其是网卡和交换机
我在多次实践中吃过硬件配置不够的亏,有些建议虽然基础,但实用:
第一,网卡必须选支持TCP卸载引擎(TOE)或iSCSI HBA的型号,尽量减少CPU在中高负载下的抢占冲突。如果预算紧张,退而求其次选Intel或Broadcom的服务器网卡(芯片方案常见品牌即得),驱动的稳定性和多队列(RSS)支持都会影响iSCSI性能。
第二,万兆网卡如果配的是千兆交换机,那纯属浪费。iSCSI要想获得接近本地盘的体验,存储网络的底线是万兆,哪怕是二手的万兆交换机,性能和千兆完全两个世界。实测数据我自己跑的:在千兆链路下,顺序读大约110 MB/s,而万兆链路下能到800 MB/s以上(同样的磁盘和Target配置)。
第三,强烈建议给网卡开启巨型帧(Jumbo Frame),MTU从1500调到9000。这里有个容易被忽略的细节:交换机上每个端口和存储服务器的网卡MTU必须全部一致,任何一跳没改,巨型帧就会失效,严重的会导致大包被丢弃、连接时断时续。我遇到过网络大部分正常但偶尔卡一下的诡异问题,最后发现是交换机上有一个uplink口没开巨型帧。
第四,磁盘组建议用RAID或者硬件阵列卡,不要多块单盘直接裸奔做Target。因为iSCSI Target一旦性能或故障出现问题,会直接传导到所有使用它的应用上。数据安全性和稳定性的优先级永远最高。
3.3 软件方案选型说明
服务端我推荐Linux环境的LIO。选它有三个理由:内核自带、开源免费、生态成熟。LIO从Linux 2.6.38开始逐渐合入内核主线,现在各大发行版默认就带,不需要额外的用户态守护进程支撑,性能上也有保障。它比老旧的iscsi-target-utils(基于用户态STGT)更现代,也更稳定。
在Windows环境,Windows Server自带的“iSCSI目标服务器”角色也很好用,鼠标点击就能完成基本的Target和LUN创建,适合完全没有Linux经验的人。macOS目前基本没有合适的目标端方案,一般不考虑做存储服务器。
客户端方面,Linux标配open-iscsi,Windows则自带iSCSI发起程序。虚拟机场景下,VMware ESXi也内置了软件iSCSI适配器,用起来大同小异。文章后面主要用LIO加open-iscsi作为演示对象。
4. 目标端搭建全流程:从磁盘到LUN,再共享出去
4.1 准备存储池,用LVM创建一个逻辑卷
假设目标端Linux服务器有一块独立的1TB数据盘/dev/sdb。先把这块盘做成LVM:
# 安装LVM工具(如果没装) yum install -y lvm2 # RHEL/CentOS/Rocky apt install -y lvm2 # Debian/Ubuntu # 创建物理卷 pvcreate /dev/sdb # 创建卷组,命名为 vg_storage vgcreate vg_storage /dev/sdb # 创建一个 500G 的逻辑卷,命名为 lv_webdata lvcreate -L 500G -n lv_webdata vg_storage这块逻辑卷以后就作为第一个LUN的底层存储。我给它的命名比较直白,webdata一眼能看出是给Web应用用的数据盘。实际项目中,我建议你按照业务模块命名,否则时间一长,你根本记不住哪个LUN是干什么的。
硬盘分区之前需要检查一件事,用lsblk确认/dev/sdb是整块盘,如果它之前被分区过,可能有/dev/sdb1这样的分区表残留,需要用wipefs -a /dev/sdb清掉。
4.2 用targetcli创建iSCSI Target和LUN
在大多数发行版中,targetcli是一个带Tab补全和交互式提示的管理工具。进入交互界面后,命令结构本身和对象层级高度对应,我用过一次之后就基本离不开了。
先安装并启动服务:
yum install -y targetcli # RHEL系列 apt install -y targetcli # Debian/Ubuntu systemctl enable --now target然后创建Target和LUN,我直接给出一个完整命令序列:
targetcli # 进入 backstores/block 子目录,创建后端存储 cd /backstores/block create block_dev_web /dev/vg_storage/lv_webdata # 进入 iSCSI 配置区,创建一个target cd /iscsi create iqn.2024-12.com.example:storage.webdata # 在target下创建LUN映射 cd iqn.2024-12.com.example:storage.webdata/tpg1/luns create /backstores/block/block_dev_web # 配置访问控制,允许某台应用服务器访问 cd ../acls create iqn.2024-12.com.example:initiator.web01 # 设置CHAP认证,用户名和密码按需求填 cd ../ set auth/userid=webinitiator set auth/password=secretpass123 set attribute authentication=1每一步做完都可以用ls查看当前层级结构,targetcli的路径和对象模型非常清晰,这里不重复贴输出。记住一点:创建LUN时使用的路径是/backstores/block/xxx,这是后端存储的设备路径,不是Linux设备名。
4.3 端口、监听地址和持久化配置
Target创建好之后,默认监听在0.0.0.0:3260,也就是所有网卡都会响应。生产环境里我建议收紧监听范围,只监听存储网卡的IP:
targetcli cd /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1/ set portal/tcp listen_ip=192.168.100.10如果你有多块业务网卡,不想让iSCSI在业务网络里暴露,这一步非常必要。
配置完成后,用saveconfig保存配置:
targetcli saveconfig它会生成一个JSON格式的配置文件,一般在/etc/target/saveconfig.json。有了这份配置,重启机器后LIO会自动加载Target和LUN映射。这一点比很多用户态Target要省心得多。
顺便提一个我反复强调的坑:绝对不要在配置完targetcli之后直接reboot,然后发现LUN全部消失。我记得有一回给某测试环境做完配置,重启后Target确实丢了,排查了半天发现是忘了saveconfig。targetcli默认配置确实会提示你需要保存,但很多人在交互界面里根本没注意那个提示。
4.4 目标端需要的额外检查
为了让iSCSI Target服务稳定运行,还需要开防火墙端口。如果用了firewalld:
firewall-cmd --permanent --add-port=3260/tcp firewall-cmd --reload如果开的是iptables,也要放行TCP 3260。另外确认target服务和rtsadmin相关服务已正常启动:
systemctl status target此时Target端基本就绪。
5. 发起端配置,让Windows和Linux都能用上远端的盘
5.1 Linux发起端:open-iscsi从安装到挂载
以CentOS/Rocky为例,先安装客户端:
yum install -y iscsi-initiator-utils systemctl enable --now iscsid然后设置发起端名称,这个名称必须和目标端配置的ACL对应。编辑/etc/iscsi/initiatorname.iscsi:
InitiatorName=iqn.2024-12.com.example:initiator.web01注意,这个名称必须和目标端ACL里设置的完全一致,一个字符都不能差。
接着发起发现:
iscsiadm -m discovery -t sendtargets -p 192.168.100.10:3260如果一切正常,它会输出类似:
192.168.100.10:3260,1 iqn.2024-12.com.example:storage.webdata然后登录:
iscsiadm -m node -T iqn.2024-12.com.example:storage.webdata -p 192.168.100.10:3260 --login如果配置了CHAP,需要编辑/etc/iscsi/iscsid.conf,找到并修改节点配置段:
node.session.auth.authmethod = CHAP node.session.auth.username = webinitiator node.session.auth.password = secretpass123登录成功后,你会看到一个新的磁盘设备。用lsblk确认设备名,比如/dev/sdc,然后照常分区、格式化、挂载:
mkfs.xfs /dev/sdc mkdir /mnt/iscsi_webdata mount /dev/sdc /mnt/iscsi_webdata5.2 Windows发起端:三分钟搞定连接
Windows自带iSCSI发起程序,操作上比Linux简单很多,但注意的细节也不少。
打开“控制面板-管理工具-iSCSI发起程序”(Windows 10/11和Server系列都自带),首次打开会提示“Microsoft iSCSI发起程序服务未运行,是否启动?”选“是”。
然后在“目标”标签页填入存储服务器IP,点击“快速连接”。如果Target配置了CHAP,需要先点击“高级”,填写“用户名”和“密码”,也就是我们在目标端设置的那两组值。
连接成功后,打开“磁盘管理”,会发现一块新磁盘,处于“未初始化”状态。右键初始化,然后新建简单卷,就能像本地硬盘一样使用了。这里有个坑:Windows对多路径磁盘的默认超时时间比较长,如果你在存储端把LUN删错了,Windows可能会卡住很久才报错。平时操作时务必谨慎,在iSCSI Target端删除LUN前,先在客户端卸载磁盘。
5.3 开机自动挂载和挂载异常处理
Linux端的自动挂载,不能直接在/etc/fstab里写设备名(比如/dev/sdc),因为设备名可能在重启后发生变化。正确做法是用UUID或者/dev/disk/by-path/路径。更稳妥的方案是分两步。
第一步,确保iscsi服务开机自启并自动登录:
systemctl enable iscsid iscsi iscsiadm -m node -T iqn.2024-12.com.example:storage.webdata -p 192.168.100.10:3260 --op update -n node.startup -v automatic第二步,在/etc/fstab里写入fstab条目。先查UUID:
blkid /dev/sdc输出类似:
/dev/sdc: UUID="a1b2c3d4-..." TYPE="xfs"然后在fstab中写:
UUID=a1b2c3d4-... /mnt/iscsi_webdata xfs defaults,_netdev 0 0_netdev选项非常关键,它告诉系统这个文件系统依赖网络,需要在网络就绪后再挂载,否则开机时网络还没启动完成就尝试挂载会失败。
6. 多路径和高可用,两块网卡才是企业级的门槛
6.1 启用MPIO:为什么两条路径不等于双倍性能
如果存储服务器只有一块网卡,那它就是单点故障。企业里至少要用两块网卡做冗余。iSCSI的多路径通过MPIO(Multipath I/O)实现,Linux内核里就是device-mapper-multipath。
先安装:
yum install -y device-mapper-multipath然后编辑/etc/multipath.conf,做一个基础配置:
defaults { user_friendly_names yes find_multipaths yes } blacklist { devnode "^sda" devnode "^sdb" }blacklist里要把本地系统盘排除掉,否则multipath会尝试对系统盘做合并,导致启动异常。
重启multipath服务:
systemctl enable --now multipathd重新执行iSCSI发现和登录(确认iscsi会话已建立),然后用multipath -ll查看路径状态。如果一切正常,会显示一条聚合设备,比如/dev/mapper/mpatha,下面有两条路径,状态都是active。
挂载时使用聚合设备:
mkfs.xfs /dev/mapper/mpatha mount /dev/mapper/mpatha /mnt/iscsi_data这时你去拔掉一条网线,数据服务不会中断,multipath -ll会显示剩余路径仍处于active状态。这就是MPIO带来的故障切换能力。
但请注意,MPIO并不会让单条I/O变快。如果你测试顺序读,可能发现性能只和单路径差不多,因为它要保证I/O的有序性。只有当多个应用并发产生大量I/O时,它才会把不同I/O分布到不同路径上。期望双网卡就能获得双倍性能,这个预期需要调整。
6.2 网卡绑定还是MPIO,这是一个选择题
另一个常见的冗余方案是网卡绑定(Bonding)。两种思路我都用过,总结一下取舍。
Bonding在交换机侧需要配置链路聚合(LACP),配置复杂度高一些。它的模式多样,比如mode 4(802.3ad)需要交换机支持,配置错误会有报错甚至网络中断风险。而MPIO是纯主机侧方案,交换机无需任何配置,只要两块网卡IP不同、路由可达即可。显然MPIO在中小企业环境里更容易落地,这也是我优先推荐MPIO的原因。
但MPIO也有一个缺点:它需要在每台使用存储的应用服务器上都安装和配置multipath,虚拟机数量多的时候,这个工作会重复很多遍。如果虚拟机通过模板分发,记得把multipath配置固化到模板里。
6.3 存储服务端高可用的现实做法
iSCSI Target本身是否有冗余方案?有,但实现方式要务实。主流做法是用存储集群,比如LIO配合DRBD(Distributed Replicated Block Device)做数据双写,再配合Pacemaker做故障切换。这个方案复杂度较高,一般适合有一定Linux集群经验的人。对于大多数中小环境,我的建议是:把存储服务器自身做成双机热备的“主动-被动”模式,数据层用DRBD实时同步,服务层用Pacemaker管理VIP(虚拟IP)和target资源。这个方向能写一整本书,这里我只提醒一点:如果你把存储做成双机,iSCSI的Initiator端要调整连接参数,设置较长的超时和重试次数,否则故障切换时会话会因为短暂断流而被主动断开,切换就白做了。
7. 性能调优实战:从能用到好用的差距
7.1 网络层面的三个关键参数
iSCSI性能的口诀:先看网络,再看磁盘,最后看参数配置。在很多实测中,网络层面的收益最明显。
首先是巨型帧。前面已经说过,这里再强调一下检查方式。在Linux发起端上执行:
ping -M do -s 8972 192.168.100.10-M do表示不分片,-s 8972是数据包大小(9000 MTU减去IP和ICMP头部)。如果通,说明巨型帧链路OK。如果timeout或报错,则要检查交换机端口和网卡MTU设置。
其次是TCP缓冲区调优。iSCSI是长连接、大块数据传输,默认的TCP窗口可能偏小。可以适当调大发送和接收缓冲区,我一般改到1MB左右:
# 在/etc/sysctl.conf中追加 net.core.rmem_max = 1048576 net.core.wmem_max = 1048576 net.ipv4.tcp_rmem = 4096 87380 1048576 net.ipv4.tcp_wmem = 4096 65536 1048576最后是队列深度(Queue Depth)。发起端和Target端都有限制并发的I/O队列。LIO默认的cmd_depth值通常够用,但高并发虚拟化场景下可以适当加大:
targetcli cd /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1/ set attribute cmdsn_depth=128这里的原理是:在阵列磁盘繁忙时,太大的队列深度反而导致排队超时,太小则无法压满磁盘的IOPS能力。需要根据实际压测结果反复调整。
7.2 磁盘层面:提前规划RAID和文件系统
如果用了多块磁盘组RAID,RAID级别对性能影响非常大。RAID 5的随机写性能因为每次写入要计算校验、读改写,表现明显弱于RAID 10。虚拟化场景我建议直接用RAID 10,虽然容量利用率只有50%,但换来的是更稳定的时延和更好的故障容忍。这里属于经典取舍,不再展开。
文件系统选择上,服务端LUN底层是块设备,不用刻意做文件系统;但客户端挂载后的文件系统建议优先选择XFS(Linux)或者ReFS(Windows Server),它们的扩展性更好、元数据操作效率更高,也是虚拟化平台顺位推荐的选择。ext4当然也能用,但如果有得选,XFS长期下来更省心。
7.3 实测数据:一次典型的性能验证
为了让你有直观感知,我贴一次简短的测试数据。环境是两台普通服务器直连万兆,Target端是四块SATA SSD组成RAID10,发起端用fio测顺序读和随机读:
fio --filename=/dev/mapper/mpatha --direct=1 --rw=read --bs=128k --size=4G --numjobs=8 --runtime=60 --group_reporting --name=seq_read fio --filename=/dev/mapper/mpatha --direct=1 --rw=randread --bs=4k --size=4G --numjobs=8 --runtime=60 --group_reporting --name=rand_read实测顺序读稳定在每秒850MB左右,随机读4K大约每秒12000 IOPS。瓶颈其实已经不在网络,而在SSD本身的随机读能力。如果用机械盘,瓶颈会明显落在磁盘寻道上,网络怎么调都补不回来。
这个测试提示我们:在给iSCSI存储规划硬件时,先想想业务场景。如果是数据库在线交易类业务,随机读写多,SSD是必选项;如果是备份、归档类业务,顺序读写多,大容量机械盘性价比更高。
8. 安全加固与访问控制,不能只求能跑
8.1 CHAP双向认证配置流程
iSCSI默认不加密,数据以明文在网络中传输。在隔离的存储VLAN中,这个问题相对可控;但生产环境尤其是跨机房场景,至少要启用CHAP进行身份验证,有条件还要考虑IPsec加密。
CHAP双向认证的配置需要两端一起做,流程是:目标端先启用认证并设置密码,发起端设置相同的用户名密码。注意,iSCSI的CHAP密码长度有要求,至少12个字符。
在目标端继续用targetcli:
targetcli cd /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1/ set auth/userid=webinitiator set auth/password=MyStr0ngPass12 set attribute authentication=1发起端修改/etc/iscsi/iscsid.conf:
node.session.auth.authmethod = CHAP node.session.auth.username = webinitiator node.session.auth.password = MyStr0ngPass12然后重新登录即可。注意,修改完这些参数后,原来已经建立的会话需要先登出再重新登录:
iscsiadm -m node -T iqn.2024-12.com.example:storage.webdata -p 192.168.100.10:3260 --logout iscsiadm -m node -T iqn.2024-12.com.example:storage.webdata -p 192.168.100.10:3260 --login8.2 网络隔离和ACL双重保险
光有CHAP还不够。CHAP能防止未授权的发起端登录,但一旦密码泄露,攻击者依然能访问存储。所以我在生产环境里始终把网络隔离放在第一位。
如前所述,建立独立的存储VLAN,只放行TCP 3260端口。如果交换机支持,再做端口级别的MAC绑定或802.1X认证。这套组合拳下来,非授权设备连不到存储网络,存储风险就降得很低。
在目标端,还可以按每台发起端做不同的ACL,每个LUN只放行对应的服务器。例如数据库服务器只能访问数据库LUN,Web服务器只能访问Web数据LUN,不要图省事给所有ACL配同一个LUN集合。最小权限原则在存储访问这里非常适用。
8.3 记住备份和快照的边界
LIO本身支持LVM快照,你可以利用LVM的快照功能给LUN做近实时备份。我通常的做法是:
- 在客户端卸载文件系统(或者使用文件系统快照)。
- 在目标端创建LVM快照逻辑卷。
- 把快照卷挂载出来,用
rsync或dd备份到另一台机器或磁带库。 - 备份完成后删除快照。
注意,LVM快照一旦空间耗尽就会失效甚至损坏。创建快照时,快照卷大小通常为原数据卷的10%到20%,并且要监控快照使用率,满了及时处理。
9. 常见问题排查实录,收藏这些案例能少走弯路
9.1 问题一:连接超时、发现不到Target
这种情况十有八九是网络隔离或者防火墙问题。我的排查顺序是:
- 先确认发起端能否ping通目标端IP。
- 检查目标端防火墙有没有放行3260端口。
- 在发起端执行
iscsiadm -m discovery -t sendtargets -p IP:3260,看有没有输出。 - 查看是否需要CHAP认证,发现阶段有时候也能感知认证要求,如果没有正确配置,会在登录而不是发现阶段报错。
还有一次,我发现发现成功但登录失败,原因是ACL里的IQN和发起端initiatorname不匹配。检查目标端targetcli ls看ACL列表,再对发起端的cat /etc/iscsi/initiatorname.iscsi,两串字符必须一字不差。
9.2 问题二:性能上不去,是不是万兆链路有问题
性能问题排查,先用最原始的手段排除网络层。我用iperf3测两个节点间的带宽,排除物理链路外因:
iperf3 -s # 目标端 iperf3 -c 192.168.100.10 -P 4 -t 60 # 发起端如果iperf3能跑到900Mbps以上,说明链路没问题;如果只有几百兆,查网卡、交换机端口协商速率、MTU等。网卡协商到千兆了,多半就是网线或者交换机端口的问题,换线、换端口、检查模块。
网络没问题再查磁盘。直接在目标端本地跑fio,对比“本地磁盘IOPS和吞吐”和“通过iSCSI获取的性能”,目标端本地的成绩单几乎没差别,说明iSCSI不是瓶颈。如果本地磁盘本身就慢,那Target端换盘或者换RAID策略才是出路。
最后再检查多路径负载是否均衡。使用multipath -ll看每条路径的I/O计数,如果一条路径计数器不增长,可能有路径故障或者在用的path checker配置不对。
9.3 问题三:开机后磁盘挂载失败
这个问题在Linux客户端场景出现概率很高。我碰到过两种情况。
第一种,iscsi服务启动太慢,fstab挂载先执行了,导致找不到设备。解决方法是fstab里必须有_netdev选项,同时确认iscsi服务已设为开机自启。
第二种,multipath聚合设备名变化。如果用/dev/mapper/mpatha这种名称,重启后如果发现顺序变化(如变成mpathb),挂载点就找不到了。解决办法是用multipath -ll查WWID,然后通过/etc/multipath.conf给聚合设备起一个稳定的别名:
multipaths { multipath { wwid 3600000000000000000000000000000000 alias mpath_webdata } }WWID可以从multipath -ll的输出里获取。改成别名后,挂载路径写/dev/mapper/mpath_webdata,一劳永逸。
9.4 问题四:Target端删了LUN,客户端出现IO错误
这个问题在测试环境里经常见到,删LUN之前没有在客户端卸载。生产环境务必遵守流程:先卸载客户端文件系统,再登出iSCSI会话,最后在目标端删除LUN映射。万一已经出问题,客户端出现持续IO错误,重启应用或重启机器可能恢复,但也有可能直接引发文件系统损坏,只能从备份恢复。所以删除LUN前,务必检查是否有会话还在使用它。
9.5 问题五:CHAP配置后客户端一直认证失败
排查CHAP认证失败,首先看密码长度。iSCSI要求CHAP密码至少12个字符,如果用短密码,在Target端配置时会报错或者默默启用失败。其次检查两边用户名密码是否完全匹配,一字不差。最后确认发起端的CHAP配置是否生效,iscsiadm -m node -T xxx -p xxx --op show可以看到当前节点的认证参数。
10. 一套完整的可落地配置模板
10.1 服务端配置汇总
为了便于你直接参考,我把上面所有内容整合成一份目标端的“配置清单”:
# 0. 准备逻辑卷 pvcreate /dev/sdb vgcreate vg_storage /dev/sdb lvcreate -L 500G -n lv_webdata vg_storage # 1. 安装targetcli yum install -y targetcli # 2. 配置targetcli targetcli <<EOF /backstores/block create block_dev_web /dev/vg_storage/lv_webdata /iscsi create iqn.2024-12.com.example:storage.webdata /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1/luns create /backstores/block/block_dev_web /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1/acls create iqn.2024-12.com.example:initiator.web01 /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1 set auth/userid=webinitiator /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1 set auth/password=MyStr0ngPass12 /iscsi/iqn.2024-12.com.example:storage.webdata/tpg1 set attribute authentication=1 saveconfig EOF # 3. 防火墙 firewall-cmd --permanent --add-port=3260/tcp firewall-cmd --reload这份模板对应的是单Target、单ACL的场景。业务复杂后,你可以复制类似结构增加多个Target和ACL,彼此互不干扰。
10.2 客户端配置汇总
Linux发起端:
yum install -y iscsi-initiator-utils device-mapper-multipath # 设置initiator name echo "InitiatorName=iqn.2024-12.com.example:initiator.web01" > /etc/iscsi/initiatorname.iscsi # 配置CHAP sed -i 's/#node.session.auth.authmethod = CHAP/node.session.auth.authmethod = CHAP/' /etc/iscsi/iscsid.conf sed -i 's/#node.session.auth.username = username/node.session.auth.username = webinitiator/' /etc/iscsi/iscsid.conf sed -i 's/#node.session.auth.password = password/node.session.auth.password = MyStr0ngPass12/' /etc/iscsi/iscsid.conf systemctl enable --now iscsid multipathd # 发现并登录 iscsiadm -m discovery -t sendtargets -p 192.168.100.10:3260 iscsiadm -m node -T iqn.2024-12.com.example:storage.webdata -p 192.168.100.10:3260 --login登录成功后,创建文件系统并挂载:
mkfs.xfs /dev/mapper/mpath_webdata mkdir /mnt/iscsi_webdata echo "/dev/mapper/mpath_webdata /mnt/iscsi_webdata xfs defaults,_netdev 0 0" >> /etc/fstab mount -a10.3 上线前建议做五件事
一套存储服务配置完成,我觉得还不算结束。上线前我建议按以下清单做一次全面检查:
- 测试两路网卡分别拔线,确认MPIO故障切换生效,业务不中断。
- 测试存储服务器重启后,Target自动恢复、客户端自动重连。
- 验证CHAP配置确实阻止了未授权的其他IQN登录。
- 确认监控服务能够告警存储网卡流量、磁盘空间、Target状态。
- 在业务低峰期做一次性能基线测试,记录顺序读、随机读、随机写的数据,方便后续对比性能劣化。
最后,分享一点个人的实操心得
做iSCSI服务这几年,最大的体会是:它并不神秘,但也不是“装个软件就能跑”那么简单。真正拉开差距的,往往是对底层协议的理解、对故障场景的预判,以及细节处的一丝不苟。大多数运维事故,不是技术难度造成的,而是配置遗漏和测试不足。比如忘了saveconfig、忘了配CHAP、忘了开巨型帧、忘了做multipath aliases,这些都是小得不能再小的事,却能在关键时刻给你颜色看。
另外一个容易被忽视的非技术因素是文档习惯。哪怕你现在只是搭一套测试环境,我也强烈建议把目标端、发起端的IQN、IP、LUN映射关系、CHAP密码、多路径配置整理成一张表格存档。一段时间后你再维护这套系统,你会发现这份表格比任何“记忆”都可靠。
如果你后续要把这套iSCSI存储接入Kubernetes的存储类或者纳管到虚拟化平台,思路也是完全一样的:把Target当作外部块设备,通过CSI插件或者虚拟机直通的方式映射给工作负载。能够把这篇文章里的内容吃透,再往容器化、云原生存储方向走,阻力会小很多。