iSCSI这个词,只要做过服务器运维或者数据中心相关工作,应该都不陌生。它本质上是把SCSI存储协议封装到TCP/IP网络里传输,让远端主机像插着一块本地硬盘一样使用网络上的存储设备。说白了,就是用网线把存储空间“拉”到服务器上,成本和复杂度都比传统光纤SAN低一大截。给虚拟化集群做共享存储、给数据库服务器扩盘、给备份系统挂大容量池,iSCSI都能派上用场。这篇文章从最基础的概念讲到生产环境的调优和排障,适合刚接触网络存储的新手,也适合已经在用但想再抠一抠细节的老手。我尽量把配置命令、参数含义、踩坑经验都写到,看完可以直接照着折腾。
1. 为什么选iSCSI:它到底解决了什么问题
1.1 从“买存储”和“用存储”的差别说起
很多刚接触存储的人会有个误区:存储不就是一块大硬盘嘛。真到业务侧其实完全两码事。虚拟化平台要求多台物理机共享同一份存储,数据库要求存储支持SCSI锁和原子写,备份系统要求容量能弹性扩展。这些东西不是拿个USB硬盘就能糊弄过去的。
iSCSI的切入点就在这里。它给网络上的服务器提供的是“块设备”,也就是LUN。从操作系统的角度看,这就是一块完整的磁盘,可以随便分区、格式化、做LVM、跑文件系统。本地磁盘能做的操作,它基本都能做,只不过数据通过网卡和交换机传输。这个特性让它和NFS、SMB这类文件共享协议有本质区别——文件共享给你的是一个目录,块存储给你的是整块磁盘。
那为什么不直接上光纤SAN?因为贵。光纤交换机、HBA卡、专用存储阵列,一套下来动辄几十万起。iSCSI只需要普通千兆/万兆以太网交换机和服务器自带网卡,软件方式就能把一台普通的Linux服务器变成存储目标端。部署成本可能只有光纤方案的十分之一。对于预算有限的实验室、中小公司集群、边缘机房,这是非常现实的方案。
1.2 iSCSI的适用场景与不适用场景
以我实际接触过的项目来看,iSCSI主要适合这几类场景:
- 虚拟化集群的共享存储。多台虚拟化宿主机通过iSCSI连接同一台存储服务器,配合集群文件系统或虚拟化平台自带的分布式文件系统使用,能实现虚拟机在线迁移和故障转移。
- 数据库服务器的远程磁盘扩展。数据库对块设备的随机读写能力要求高,服务器本地盘不够用时,通过iSCSI挂载一个性能足够的存储池,比迁移整个库简单得多。
- 备份系统的集中存储池。备份数据量大,但访问频率不高,对性能和时延要求宽泛,iSCSI挂个大容量存放数据非常合适。
不太适合的场景也得说清楚。如果主存储设备本身性能一般,千兆网络带宽又只有100MB/s出头,那整条链路的瓶颈会很明显,给数据库这种高IOPS业务用就有点勉强了。还有就是跨三层路由的远端挂载,延迟容易抖,SCSI协议本身对超时很敏感,乱序或丢包会导致磁盘报错甚至文件系统损坏。iSCSI推荐放在二层直连或同机房低延迟网络内,不要想着在公网或跨城域网上挂块盘,那是给自己挖坑。
1.3 与同类协议的横向对比
做过存储方案选型的人应该经常在这几个协议之间纠结。我简单整理了一张对照表:
| 协议 | 类型 | 客户端形态 | 典型场景 | 成本 |
|---|---|---|---|---|
| iSCSI | 块存储 | 磁盘 | 虚拟化、数据库、共享盘 | 低 |
| NFS | 文件存储 | 目录 | 文件共享、无状态应用 | 低 |
| SMB/CIFS | 文件存储 | 目录 | 办公共享、Windows文件服务 | 低 |
| FC SAN | 块存储 | 磁盘 | 核心数据库、高可靠存储 | 高 |
| NVMe-oF | 块存储 | 磁盘 | 高吞吐低延迟存储 | 高 |
NFS虽然用起来简单,但对数据库这类需要自己管理锁的应用不友好。FC SAN性能最稳,可“稳”的背后是昂贵的专用硬件。iSCSI处在中间位置,牺牲了一部分性能和绝对稳定性,换来了极低的部署门槛和不错的兼容性。尤其现在万兆网卡越来越便宜,iSCSI的性能已经不像早年那么拉胯,很多非核心生产环境都能扛得住。
2. 核心概念:Target、Initiator、LUN与IQN的梳理
2.1 三个角色名词一次搞清楚
iSCSI网络里有三个基本角色:目标端、发起端和LUN。
目标端就是提供存储的那台机器,通常叫Target。它把自己的一块磁盘、一个分区、一个LVM卷或者一个文件(作为块设备后端)发布到网络上,等待别人来连接。发起端是使用存储的那台机器,叫Initiator,比如正在跑虚拟化的物理服务器,只要系统里装了iSCSI发起程序,就能主动连上Target并把LUN识别成一块本地磁盘。LUN则是Target上实际对外提供的那块逻辑磁盘,一个Target可以包含多个LUN,每个LUN就是一个独立磁盘设备。
用生活化的方式理解,Target就是仓库管理员,Initiator就是取货的货主,LUN就是仓库里编号的货架。货主货车开到仓库门口,管理员把对应货架推到装货口,货主就觉得这是自己仓库的一部分,完全不用关心仓库里具体怎么摆放。操作系统看到LUN之后,也完全不关心这块盘在远端怎么组成的。
2.2 IQN命名规则与唯一性
IQN是iSCSI里用来标识目标端和发起端的名字,全称叫iSCSI Qualified Name。格式看起来有点古怪,比如:
iqn.2024-05.local.storage:target01拆开看也很简单:iqn是固定前缀,2024-05是域名注册时间的年份和月份,local.storage是反向写的域名或组织名,最后冒号后面是自定义的设备标识。这套规则借鉴了DNS反解的逻辑,目的是让名字在全球范围内尽量不冲突。
我的建议是,命名规则从一开始就定好。比如所有Target统一叫iqn.年份-月份.公司内部域名:role-用途-编号,所有Initiator统一叫iqn.年份-月份.公司内部域名:initiator-用途-编号。命名规则一旦乱了,后续几十台机器连来连去,你会疯掉的。我就见过有人随手起了iqn.test123这种名字,结果另一台设备也有一个类似的,两者直接在日志里互相干扰,排查了半天才明白是命名冲突。
2.3 LUN、Target与ACL的关系
一个Target上可以挂多个LUN,而一个Initiator可以连接多个Target。为了安全,Target上还必须有访问控制列表ACL。ACL里面记录哪些Initiator的IQN允许连进来,以及连接时使用的CHAP用户名密码。
ACL在iSCSI里的地位很容易被忽略。很多人图省事,把Target的认证设成“允许所有人”,结果在同一二层网络里的任何机器,只要装个iSCSI发起程序就能把整块盘挂走。这不是危言耸听,我真的见过某测试环境的存储被其他部门服务器误连,然后对方格式化分区,把整组数据盘抹了的惨案。所以ACL和CHAP这两样东西从第一天就必须开。
3. 环境准备与基础配置
3.1 底层存储规划:直接用磁盘还是文件模拟
搭建iSCSI Target之前,先解决最底层的存储从哪来的问题。常见做法有几种:
- 整块物理磁盘或分区共享给LUN。
- 用LVM逻辑卷做LUN后端,方便后续扩容。
- 用RAID卡先做好阵列再用整盘映射。
- 用稀疏文件模拟,测试环境常用,性能一般。
生产环境我最推荐LVM逻辑卷或物理磁盘。LVM的好处是以后扩容时,只需要扩展LV再让LUN变大,比重新建Target省事得多。文件模拟听起来简单,但性能损耗明显,而且文件系统本身的页缓存机制会导致数据先写缓存、异步落盘,这在某些数据库场景下会造成数据安全风险。测试玩可以,生产别这么干。
如果是用Linux系统做Target,内核自带的LIO引擎配合targetcli工具就足够用了。LIO是内核级Target实现,性能比早年的用户态方案好很多,而且是各大Linux发行版默认集成的,不需要买商业软件。targetcli则是一个命令行交互工具,能帮你管理target和LUN的配置。
3.2 目标端完整配置命令实录
假设你有一台Linux服务器,上面有一块空闲磁盘/dev/sdb,我们要把它发布成iSCSI Target。安装targetcli之后,进入交互界面:
sudo targetcli然后依次执行以下操作:
# 创建一个块设备后端的存储对象,名字叫disk1,指向 /dev/sdb cd /backstores/block create disk1 /dev/sdb # 查看一下当前状态,确认backend已经创建好了 ls # 创建Target,IQN按之前定的规则写 cd /iscsi create iqn.2024-05.local.storage:target01 # 进入这个Target的TPG (Target Portal Group) cd iqn.2024-05.local.storage:target01/tpg1 # 把disk1挂成这个Target下的LUN 0 luns create /backstores/block/disk1 # 设置该Target监听在哪些IP和端口上,默认3260 portals create 192.168.10.10 3260 # 设置允许连接的发起端IQN acls create iqn.2024-05.local.client:initiator01 # 查看当前完整配置 ls # 保存配置 saveconfig上面的操作看起来琐碎,但每一步都有意义。backstores是存储后端的池子,block类型表示真正的块设备;TPG是Target的配置组,里面的LUN、ACL、监听端口都归它管理;portals create指定了客户端要连接的IP和端口,一台机器尤其是多网卡的,这一步不指定的话,Linux会默认监听所有地址,存在一定的暴露风险。
配完Target,还不能忽略CHAP认证。在targetcli里做如下设置:
cd /iscsi/iqn.2024-05.local.storage:target01/tpg1/acls/iqn.2024-05.local.client:initiator01 set auth userid=storageuser set auth password=Str0ngP@ss2024这里设置的是一个单向CHAP:客户端连接Target时,要向Target证明自己知道这个用户名和密码。如果还想做双向CHAP,让Target也向客户端证明身份,还需要在Target的TPG级别配置:
cd /iscsi/iqn.2024-05.local.storage:target01/tpg1 set auth userid=targetuser set auth password=T@rgetP@ss2024 set attribute authentication=1配置完成后,用saveconfig把配置持久化到文件。很多新手漏了这一步,重启机器后配置全没,追悔莫及。targetcli的配置默认保存在/etc/target/saveconfig.json,建议保存完再cat一眼确认文件没问题。
3.3 防火墙与服务的启动细节
Target端的端口是TCP 3260。生产环境肯定有防火墙,别配置了Target发现客户端怎么都连不上,最后把防火墙关了才通,这种操作在运维现场不可取。正确做法是在防火墙上放行特定来源IP对3260端口的访问:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port protocol="tcp" port="3260" accept' sudo firewall-cmd --reload同时把Target服务设为开机自启,避免重启后没人去手动拉起来。这里我还想多说一句:尽量把存储流量隔离到独立网段,不要和业务网络、管理网络混在一起。原因后面性能部分我会细讲。
4. 发起端连接实操:Windows与Linux两条路线
4.1 Windows系统发起端配置步骤
Windows系统自带iSCSI发起程序,使用起来比大多数人想象中简单得多。打开“iSCSI发起程序”,第一次运行会提示是否要启动服务,选是即可。然后在“目标”标签页填入Target服务器的IP地址,点击“快速连接”,系统会自动发现该IP上的Target。
如果配置了CHAP认证,就需要在“连接”按钮的下拉菜单里选择“高级”,在弹出的窗口里勾选“启用CHAP登录”,填入用户名和密码。这里有个细节:某些场景下,Windows发起端要求填入Target侧名称并指定目标门户——但大多数情况下,只要用户名密码正确,连接是秒通的。
连接成功之后,你在“磁盘管理”里看不到盘的话,别慌张。打开“磁盘管理”,点击菜单栏的“操作”,选择“重新扫描磁盘”,新挂载的iSCSI LUN就会出现在磁盘列表里。接下来就是常规操作:初始化磁盘、新建卷、分配盘符、格式化文件系统。
还有一个关键点,Windows的iSCSI发起程序服务必须设为“自动”。如果没有设自动,机器重启后,服务没起来,挂载的盘符也不会自动恢复。虽然登录系统后可以手动连接,但跑业务的服务器哪有时间去手工干预。检查一下“服务”里的“Microsoft iSCSI Initiator Service”,确保启动类型是自动。
4.2 Linux发起端与持久化配置
Linux客户端最常用的工具是iscsiadm。包名叫什么不重要,发行版软件源里搜iscsi相关包名装好就行。客户端配置文件通常在/etc/iscsi/iscsid.conf,先确认里面默认的CHAP设置是不是符合你的环境。
先做发现:
sudo iscsiadm -m discovery -t sendtargets -p 192.168.10.10:3260如果CHAP已配置,执行之前要先改配置文件,或者在登录时用--interface、--op参数显式带上CHAP用户名密码。实际更推荐的做法是写进配置文件的node部分,这样后续自动登录时也能用上。
发现成功后,系统会生成一条node记录。登录目标:
sudo iscsiadm -m node -T iqn.2024-05.local.storage:target01 -p 192.168.10.10:3260 --login登录成功后,用lsblk查看新出现的磁盘。接下来分区格式化就直接操作。关键是持久化配置。Linux这边不设置的话,重启后还是不会自动连接。把node的启动方式设为自动:
sudo iscsiadm -m node -T iqn.2024-05.local.storage:target01 -p 192.168.10.10:3260 -o update -n node.startup -v automatic这样iscsi服务会在启动时自动登录并挂载。但如果使用了文件系统自动挂载,也就是写入/etc/fstab,挂载选项里必须加_netdev,告诉系统这个设备依赖网络,等网络就绪后再挂载。
UUID=xxxxxx /data ext4 _netdev,defaults 0 0别把_netdev漏了,否则启动顺序不对,系统会报“挂载设备不存在”,严重时Linux会在等设备超时期间卡很久。这个坑我踩过不止一次。
4.3 多路径挂载与高可用考虑
生产环境如果有多块网卡、多台存储,可以做多路径。多路径的意思是主机和存储之间有不止一条物理路径,操作系统把它们合并成一个虚拟磁盘设备,既能提高带宽,还能在单链路故障时自动切换。
Windows那边需要启用“多路径I/O”功能,然后在iSCSI发起程序里把目标门户地址都添加好,让同一个Target通过多个IP都能发现。在“磁盘管理”里确认新盘是否被识别为多路径磁盘。Linux则需要装multipath-tools并配置/etc/multipath.conf,把iSCSI设备加入黑名单过滤规则,让dm-multipath接管。
多路径配置不是必须的,但凡是跑虚拟化、数据库这种7x24业务,建议还是配上。毕竟单根网线、单个交换机、单台存储,任何一个节点挂了,服务都会断。多路径可以在不改变上层应用的情况下,把底层故障的感知降到最低。
5. 性能调优与安全加固:别让存储变成瓶颈
5.1 网络层优化与MTU设置
很多iSCSI性能问题,根本原因不在存储服务器,而是网络。千兆环境下iSCSI理论最大吞吐约125MB/s,去掉TCP/IP开销,实际跑到100MB/s就算不错。想突破这个上限,要么升级万兆,要么做链路聚合。万兆网卡这几年价格已经很低,值得投入。
开启巨型帧(MTU 9000)是提升性能的常见手段。注意,MTU必须端到端全链路支持:Target网卡、发起端网卡、所有交换机端口,统统设成9000。只要有一台交换机还停留在1500,就会触发分片重组,性能反而下降,甚至出现超时。配置前先确认交换机型号和端口支持情况,这种基础问题最容易忽略。
我在调优时习惯先做基准测试,用工具测一下存储吞吐和IOPS,再调整参数对比。没有基线数据,所谓的优化都是盲人摸象。
5.2 存储侧参数:缓存、对齐与调度
存储侧几个参数值得关注。
文件系统对齐。传统机械盘和现代SSD都要求分区对齐到4K边界。如果LUN在创建文件系统时没对齐,性能损失可能达到20%以上,这是最容易被忽略的隐性损耗。
文件系统IO调度器。SSD后端可以选择none或noop调度器来减少CPU开销,机械盘则保留mq-deadline。这个参数在/sys/block/sdX/queue/scheduler里可以临时改,生产环境建议通过内核引导参数或配置管理工具固化。
写缓存。如果LUN后端是真正的RAID卡阵列,硬件写缓存能大幅提升小文件写入性能。但服务器意外断电时,如果RAID卡电池或缓存保护模块状态不佳,就存在数据丢失风险。强烈建议定期检查阵列卡缓存状态,别让写缓存成为隐患。
还有iSCSI协议层的一个参数:MaxRecvDataSegmentLength,控制单次SCSI数据段的最大长度,默认值往往偏保守。在发起端和Target两侧都调大到256K,能减少传输次数,对大块顺序读写有明显改善。但注意这个参数不是所有网卡、驱动都完美兼容,修改后务必跑一遍读写测试。
5.3 安全加固:CHAP、ACL与网络隔离
安全这一块,字字都是经验教训换来的。
CHAP认证必须开。用户名密码不要用弱口令,密码长度至少12位以上,包含大小写字母、数字和特殊符号。更进一步可以做双向CHAP,让客户端也校验Target的身份,防止中间人伪造设备。
ACL白名单必须配。确保只有明确允许的IQN才能连入Target。IQN不要用默认的iqn.1993-08.org.debian:01:xxxx这类自动生成的名字,长期维护阶段你会分不清这是哪台机器。
存储专用VLAN。iSCSI流量和普通业务流量分开跑,配合交换机上的PVLAN或ACL规则,让存储网段和其他网段二层隔离。三层路由要严格控制,一般存储网段不应该对业务网段开放路由,只有同属存储系统的主机才能互相通信。
还有一点容易被忽略:管理接口安全。targetcli或者存储管理页面如果暴露在业务网段,一旦被攻破,存储系统直接沦陷。管理口单独走带外网络,或者用堡垒机跳转访问,是基本的安全底线。
6. 常见故障排查与避坑指南
6.1 连接失败:从防火墙到名称全梳理
连接失败是最常见的故障。我的排查顺序一般是:
- 网络连通性。发起端和目标端之间先
ping通不通,注意MTU大小的差距,必要时用ping -s 8972测试巨型帧链路。 - 防火墙。确认目标端3260端口对源IP放行。曾在客户现场排查半天,最终发现是云安全组规则没加。
- 发现命令执行结果。如果
sendtargets发现不到,重点检查Target是否在监听正确网卡IP,以及portals配置里填的地址是否有误。 - IQN和ACL。确认发起端的IQN确实在ACL列表里。大小写写错、末尾多了个冒号,这类低级错误真的经常发生。
- CHAP认证。确认用户名密码无误,特殊字符时注意shell转义问题。
6.2 连接后看不到磁盘或丢失磁盘
连接成功但系统里没有新盘,多半是磁盘扫描的问题。Windows里手动“重新扫描磁盘”,Linux里用partprobe或blockdev --rereadpt重新读取分区表,一般就能解决。
重启后掉盘又是另一个高频问题。Windows检查iSCSI服务是否自动启动;Linux检查node.startup是否为automatic,同时确认/etc/fstab的挂载项有没有_netdev。还有一个坑是网络和iscsi服务的启动顺序,某些发行版上需要开启iscsid和iscsi两个服务,漏一个都不行。
如果出现LUN“看起来连着,但读写就报IO错误”,多半是链路不稳定或者Target端存储后端出了状况。这时先看系统日志,dmesg里通常会有connection timed out或session recovery相关记录,同时关注Target端存储的磁盘健康状态。
6.3 性能不达标时从哪里查起
性能问题排查比连接问题复杂不少,我的经验是分层排查法。
网络层先测:用iperf跑一下Target和发起端之间裸吞吐。如果裸网络本身就跑不到预期,说明瓶颈在网卡、交换机或网线,存储层面背不了这个锅。测的时候注意多线程,单线程TCP流测出来的数值往往偏低。
存储层再测:在存储服务器本地对后端设备做读写测试,确认后端存储本身性能达标。本地都慢,那没必要查iSCSI了。
协议层最后查:确认MTU、QueueDepth、MaxRecvDataSegmentLength这些参数在两侧保持一致。不同厂商的实现细节有差异,别一边改了另一边没改,那样反而制造瓶颈。
我在实际调优时遇到过一种情况:测试工具单队列跑时吞吐很差,但多队列就正常。原因是发起端网卡没有开启多队列,或者RSS哈希配置不准,导致所有流量都压在一个CPU核上。这种问题不看mpstat的软中断信息很难发现。
6.4 扩容LUN与在线调整的注意点
业务跑着跑着空间不够了,扩容是绕不开的话题。如果LUN后端是LVM卷,扩容流程是:先在Target端把LV扩容,再让对应LUN也变大,最后在发起端执行磁盘重新扫描或文件系统扩容。
以targetcli为例,扩大LUN的办法是先在后端存储上扩容:
sudo lvextend -L +200G /dev/vg01/lun01然后重新设置backstore的size。targetcli里的/backstores/block下的条目通常会自动感知块设备变化,但保险起见还是显式执行一次resize。Linux发起端用rescan-scsi-bus.sh或blockdev --rereadpt让系统识别新容量,最后ext4用resize2fs在线扩张,xfs用xfs_growfs。整个过程强调一个原则:先扩后端,再扩LUN,最后扩文件系统,顺序不能乱。
扩LUN前强烈建议先做快照或备份。在线扩容本身有风险,断电、断网、操作失误都有可能让文件系统挂掉。别拿生产数据赌运气。
最后再聊几句
iSCSI这些年能一直有一席之地,靠的不是炫技,而是实用。它把一个企业级存储的概念,拉到了中小团队甚至个人实验室都能折腾的层次。我自己在实际操作中的体会是:iSCSI的上限不取决于协议本身,而取决于你对网络和存储基础的理解水平。网络不稳,再好的存储阵列也白搭;存储规划乱,再高的带宽都救不了延迟。刚开始折腾时不用追求一步到位的多路径、万兆、双活,先把一台存储、一个客户端、一条CHAP认证链路跑通,再慢慢往里加复杂度。等哪天真出了故障,你会发现,当初每一步打牢的基础,都是排障时的救命线索。