
iSCSI这个协议在存储圈子里算不上新东西但直到今天它依然是用普通服务器普通网卡构建共享存储的最务实方案。我最近又完整搭建了一次iSCSI服务器从targetcli手工配置到虚拟机接入再到一次典型的initiator failed to login排查踩了不少坑也攒了不少经验。这篇就把整个过程拆开讲清楚适合刚接触存储、想把多台服务器或虚拟化宿主机接入统一存储池的朋友参考。1. 为什么我最终选了iSCSISAN平民化与适用边界1.1 一个网线连硬盘的协议凭什么能撑起虚拟化存储池先理解iSCSI的底层逻辑。它的全称是Internet Small Computer System Interface翻译成人话就是把SCSI指令封装进TCP/IP包在以太网上跑存储。本质上它让服务器上的initiator发起端通过网络访问target目标端上的块设备表现为一个独立的磁盘。这个块设备的语义非常关键它和NFS、SMB这些文件级共享完全不同iSCSI给上层的是一个裸设备需要自己格式化、自己分区就像一块真正插在机器里的硬盘。我选择iSCSI而不是NFS或SMB很大程度上就是因为这个块设备的语义。虚拟机磁盘镜像qcow2、raw、vmdk直接放在一个由NFS导出的目录上确实也能跑但一旦涉及多路径、快照一致性、文件锁这类底层需求文件级共享就会变得非常别扭。iSCSI把所有SCSI层的机制原封不动地搬过来包括预留、锁定、错误恢复等对上层应用来说它是透明的——你不用改任何现有工具链它就是一块本地盘。值得说明的是iSCSI本身并不做去重、压缩、快照等高级功能。如果你需要这些得靠target所在的文件系统或存储软件去实现。这里有一个常见的认知误区很多人把iSCSI当成自己搭一个SAN就完事了实际上iSCSI只是提供了块传输这个底层通道上层的数据保护、性能分层、容灾策略还得自己设计。就我的经验而言iSCSI的适用模型是用最少的成本把现有服务器的闲置磁盘聚合成统一的块存储池让多台主机共用。它不取代高端存储阵列但足以应付中小型虚拟化集群、实验室环境、备份暂存空间等大多数场景。1.2 画一张使用场景对照表iSCSI、NFS、SMB、FC到底怎么选很多人一上来就问哪个协议好这个问题本身没有标准答案要看场景。我习惯用下面这张表来判断维度iSCSINFSSMBFC传输语义块级ISCSI文件级文件级块级网络要求普通以太网建议万兆普通以太网普通以太网专用FC网络虚拟化支持原生块设备兼容性好支持但需注意文件锁与快照Windows场景支持好存储阵列场景最佳部署成本低无额外硬件低低高需专门交换机与HBA适合规模中小型集群、实验室、备份池文件共享、无状态应用办公共享、Windows环境企业级核心业务1.3 选型前必须先算清的链路预算链路预算是我自己经常提醒别人的概念它决定了iSCSI服务器能用多大规模。iSCSI走的毕竟是网络瓶颈往往不在硬盘而在网络链路。简单算一下如果target上放了一块数据盘写入速度能跑到接近200MB/s那么千兆网卡的极限大约是112MB/s这就会成为瓶颈。所以搭建前先看两点——交换机端口是什么速率、网线是否支持万兆、initiator服务器的网卡是否支持offload。如果条件有限比如只有千兆环境那就要在容量规划上降低预期一个千兆的iSCSI服务器跑轻量级虚拟机是可以的跑大规模数据库就够呛。另外还有一种常见的假万兆问题服务器网卡标称万兆但中间交换机没有万兆模块或者用了旧的Cat5e网线实际协商速率只有千兆。查链路速率最好的办法是登录交换机看端口协商状态或者直接用iperf3打流测试。这一步看起来很基础但很多莫名其妙的慢都是从这里开始的。提示选型阶段最容易被忽略的是存储网络是否独立。iSCSI流量如果和业务流量共用普通交换机一旦有内存占用型任务或突发大流量就会影响存储延迟。有条件的情况下单独划一个VLAN或独立交换机是非常划算的隔离手段。2. 服务器端配置targetcli的完整手工搭建实录2.1 环境与工具选型为什么官方工具是targetcli而不是tgt和SCSTLinux上做iSCSI target主流方案有三类tgt、SCST和内核自带的LIO。我这次用的是内核原生LIO配套的targetcli工具。LIO是把iSCSI target能力直接编进内核的框架知名度和维护性都更好。targetcli则是它官方推荐的配置Shell语法做得像文件系统导航会cd、ls、create就能上手。至于为什么不选tgt和SCST我的理由是维护成本。tgt是用户态实现安装简单但性能和内核态的LIO相比在并发场景下有明显差距SCST性能不错但补丁加载和版本适配比较麻烦在普通发行版上维护成本太高。targetcli优势在于配置文件统一写在/etc/target/下工具自身有rootfs风格的交互界面出问题能把配置导出来排错。配置内核模块前先确认系统是否加载了target模块。如果没加载需要手动加载并设置开机自动加载modprobe target_core_mod modprobe target_core_user modprobe ib_srpt # 如有需要加载RDMA相关支持 systemctl enable targetcli # 让target服务开机启动 systemctl start targetcli这里有个容易忽略的细节targetcli其实是一个命令行管理前端真正的服务常驻进程是target有些发行版上服务名是target或target.service。配置过程中如果系统重启后发现target没有自动监听多半是服务没设开机自启而不是配置丢失。2.2 从零开始创建backstore、target、LUN和ACL进入targetcli后配置流程可以概括为四步创建backstore、创建target、给target加LUN、设置ACL。我用的是文件模拟块设备fileio也就是在一块正常的文件系统上建一个大文件作为整个iSCSI的虚拟磁盘。相比直接暴露物理分区blockfileio的好处是灵活、快照方便、不需要单独划分裸设备性能损失在实际应用中可以接受targetcli / backstores/fileio create namedisk01 file_or_dev/data/iscsi/disk01.img size500G注意size参数大小写敏感单位支持G和T。如果file_or_dev指定的路径不存在targetcli会尝试创建空文件但最好还是事先把存储目录准备好避免权限问题。接下来创建iSCSI target节点。target的名字采用的是IQN格式iSCSI Qualified Name一般写成iqn.2025-05.local.storage:target01这种风格。IQN的命名规则其实很自由但强烈建议沿用企业命名的规范习惯把时间、机构名、设备名都包含进去避免后期设备多了分不清谁是谁/ /iscsi create iqn.2025-05.local.storage:target01创建后必须把客户端initiator的名字加入ACL列表否则即使网络通、IP对得上target也会直接拒绝登录。ACL匹配的就是客户端主动上报的initiator IQN而不是IP地址/ /iscsi/iqn.2025-05.local.storage:target01/tpg1/acls create iqn.2025-05.local.client:initiator1然后把前面创建的backstore挂成LUN这里建议把LUN编号从0开始做多块盘时保持LUN编号和用途对应/ /iscsi/iqn.2025-05.local.storage:target01/tpg1/luns create /backstores/fileio/disk012.3 用一张表盯住配置我把每次rebuild要检查的项目列成了清单手工配置最大的风险不是步骤不会而是配置项太多容易漏。尤其是ACL端口、LUN编号和CHAP参数这三项出问题时排查很费时间。我给自己总结了一个重建配置必查清单每次搭完直接用这6项核一遍确认无误再连客户端检查项命令正确状态监听端口ss -tlnpgrep 3260target存在targetcli ls /iscsi能看到刚创建的target与tpg1ACL条目targetcli ls /iscsi/iqn.../tpg1/acls能看到initiator IQNLUN映射targetcli ls /iscsi/iqn.../tpg1/lunsLUN 0指向正确的backstoreCHAP认证targetcli ls /iscsi/iqn.../tpg1确认认证参数生效防火墙放行firewall-cmd --list-all3260/tcp 已开放这类检查看起来繁琐但真能省下大量为什么客户端连不上的排查时间。尤其在第4项上我遇到过因为把LUN编号设成1而客户端只扫描LUN 0导致磁盘看不到的情况从此就养成了先看映射表的习惯。3. 客户端接入与虚拟化场景配置VMware/Proxmox双案例3.1 Linux initiator的登录流程与配置要点target准备好以后客户端要用open-iscsi这个包来发起登录。安装后核心操作就是发现target再登录systemctl enable --now iscsid iscsiadm -m discovery -t sendtargets -p 192.168.100.10discovery之后iscsiadm -m session如果显示登录成功就能看到对应的session。但很多时候discovery成功不代表能正常使用真正决定能不能用的是一个容易被忽视的细节——node.startup参数。它控制着系统重启时是否自动重新登录target。默认值可能是manual这意味着每次重启都要手动登录一遍。建议选在建立连接后改成automaticiscsiadm -m node -T iqn.2025-05.local.storage:target01 -p 192.168.100.10 -o update -n node.startup -v automatic紧接着确认系统确实识别到了新磁盘lsblk或fdisk -l。需要注意的是Linux的磁盘设备名如/dev/sdb在每次重启后可能变化跟UUID没关系。所以只要涉及文件系统挂载强烈建议用UUID或者文件系统label而不是直接用/dev/sdb。3.2 虚拟化平台接入的两种典型玩法虚拟化是iSCSI最常见的使用场景。我这次身边的机器分别跑的是VMwareESXi和Proxmox VE两种平台的接入方式不太一样正好一起说。ESXi那边要在存储适配器里添加一个软件iSCSI适配器填入target IP然后做动态发现。做动态发现之前先确认vSwitch/VMkernel端口上开启了软件iSCSI的通信选项并且选了正确的VMkernel网卡。我踩过的坑是ESXi装好后默认没有为iSCSI配置VMkernel端口即使物理网络全通也发现不了target。需要在网络VMkernel网卡里给vSwitch添加一个专门用于存储的端口分配一个独立网段。Proxmox VE这边就简单得多它是基于Linux内核的open-iscsi直接按Linux initiator的方式登录target然后到数据中心存储里添加LVM-LVM-thin或目录类型把iSCSI设备作为PV物理卷在上面创建LVM卷组作为虚拟机的磁盘存放池。我建议在Proxmox上用LVM-thin而不是普通目录存储因为thin卷支持快照而且不容易出现虚拟机删除后空间不释放的问题。这里的关键在于虚拟机平台通过iSCSI访问的是块设备但必须在其之上再建立自己的存储管理机制VMware的VMFS、Proxmox的LVM而不是直接把裸盘挂给虚拟机。很多人刚接触时会把LUN直接挂成数据盘这样也行但意味着你没有应用到平台的自有快照、克隆能力后面维护会很麻烦。3.3 关于CHAP认证别嫌麻烦它替你挡住过很多误操作CHAPChallenge Handshake Authentication Protocol是iSCSI的常用认证机制它不加密数据但能确保只有知道密钥的initiator才能登录target。CHAP配置需要两侧都设置target侧在tpg1里配置客户端侧在open-iscsi的node配置里设置相同参数。而且要注意CHAP有单向和双向两种。单向CHAP是target校验initiator双向CHAP是target校验initiator的同时initiator也校验target。如果没有特殊安全需求单向CHAP就够了。第一次配CHAP时一个非常容易踩的坑是target的user配置的是IncomingUser而客户端如果没有正确设置node.session.auth.authmethod为CHAP就会抛出authentication failure。我习惯把CHAP用户名密码统一放到一个文档里并在targetcli配置完成后立即用iscsiadm在客户端侧验证一遍登录验证通过再部署到其他机器这样能少走很多弯路。4. initiator failed to login专题最完整的排查链路热搜词里那条initiator [pdmserver] failed to login to iSCSI target [discovery] due to cha我看了很有感触因为我确实被类似的问题折磨过。后来总结出的规则是登录失败不要一个个猜按顺序检查九成能定位。4.1 从日志看端倪别急着改配置第一次排查登录失败时我先登到target服务器上看日志dmesg | tail -30 journalctl -u target -n 50日志里会出现的常见字样各有意义Login failed due to authentication代表CHAP认证不过No matching ACL表示ACL里没有这个initiatorConnection closed可能来自网络层或防火墙。先把日志和ACL列一下会比在initiator端反复重试有效。4.2 根因一portal/ACL错位我最常遇见的情况是discovery成功但login失败。discovery能成功说明网络是通的3260端口能被访问到。但discovery仅做发现login才是正式的认证握手。如果login失败且日志里有类似No matching ACL的报错基本是ACL里没写好客户端的IQN。有些客户端软件会在一台机器上有多个IQN比如同时装了open-iscsi和某厂商的存储插件你看到的IQN和实际用来发起登录的IQN未必是同一个。查客户端实际IQN用cat /etc/iscsi/initiatorname.iscsi也可以在targetcli的ACL里直接加一条宽松匹配再逐步收紧。但生产环境不建议长久用宽松ACL临时验证可以最终还是要精确匹配。4.3 根因二CHAP认证参数不一致日志里出现auth相关的关键词基本就是CHAP配置不一致。target侧配置在tpg1/attributes/authentication和tpg1/acls/iqn/下客户端侧在iscsiadm的配置文件里。最容易配错的有两个地方用户名大小写、密码是否带特殊字符导致被转义。我建议测试阶段先用无认证跑通链路再加CHAP。每加一层安全就验证一次好过一步到位然后对着满屏报错乱猜。4.4 根因三IP/网络层面的硬伤如果日志干净无比客户端看起来没有错误但就是连不上就要怀疑网络本身了。我用iperf3打流时遇到过一次状况两台机器都在内网Ping也通但iSCSI登录始终超时。后来查了交换机端口配置发现客户端所在网口被封了VLANPing能通是因为走了其他路径而3260端口被ACL挡住。所以说即使测试阶段Ping通也不能代表3260端口放行了需要用nc -vz或nmap -p 3260直接做端口探测。还需要注意链路速率协商。网卡和交换机有时会协商到1000M但如果出现半双工或大量冲突登录表现就是时好时坏错误信息又很模糊。这个场景下先固定速率和双工模式比如千兆环境就强制ethtool -s eth0 speed 1000 duplex full再测。4.5 看一眼就能用的排查命令集我每次排查登录问题时基本就来回敲这几条命令# 在target服务器上 ss -tlnp | grep 3260 # 看监听 targetcli ls /iscsi/.../tpg1 # 看ACL、LUN、认证 # 在initiator服务器上 cat /etc/iscsi/initiatorname.iscsi # 看IQN iscsiadm -m discovery -t sendtargets -p 192.168.100.10 # 重复发现 iscsiadm -m session -P 3 # 看连接详情 nc -vz 192.168.100.10 3260 # 测端口 dmesg | grep -i iscsi # 看内核相关输出这套命令组合起来可以在几分钟内把问题范围压缩到网络、CHAP、ACL、防火墙四个层面中的某一个比乱试要高效得多。5. iSCSI BIOS与无盘/裸机启动一个经常被问但其实没那么玄的话题5.1 iSCSI BIOS到底解决什么问题iSCSI BIOS这个热搜词让很多人误以为它是iSCSI实现的一部分。严格说iSCSI BIOS是网卡尤其是板载网卡或HBA固件里嵌入的启动引导功能。这台机器在没有本地系统盘、需要从远程target引导操作系统时才轮到iSCSI BIOS出场。它的工作方式很像是传统PXE引导的逻辑机器加电后BIOS/UEFI初始化网卡固件里的iSCSI initiator主动去连接指定的target、发起启动请求从远程磁盘引导操作系统。这样一来客户机就可以完全不用本地硬盘整个盘都在服务器端。但我的建议是除非你确实在做无盘工作站、瘦客户机集群或者远程启动类的特殊场景否则别轻易启用iSCSI BIOS。原因有三点每次开机都要做远程引导启动时间变长而且依赖存储网络先就绪。如果系统本身有本地盘iSCSI BIOS的存在反而可能让系统从错误设备引导。排查难度高。本地引导失败顶多查一下本地盘远程引导失败得同时检查存储、网络、DHCP、责任链路上的认证。5.2 启用iSCSI BIOS之前的三道检查如果真的要用iSCSI BIOS启动前至少要过三道检查检查项作用网卡固件是否支持iSCSI Boot不是所有网卡都带这个功能要先确认存储target服务必须提前可用iSCSI BIOS启动时没有完整的网络栈它直接按固件配置连接targetCHAP认证信息是否固化在固件里固件里的CHAP配置通常没有操作系统里那么直观容易遗留过期凭据我自己实际用过的场景是做远程测试机所有测试虚拟机镜像都放在target上哪台机器要做测试就通过iSCSI BIOS引导对应的LUN。这种方式省了逐个装盘的功夫但也让我吃够了固件配置不易管理的苦头——所以现在只要允许我还是倾向于优先用软件initiator把无盘引导留给真正的无盘场景。6. 性能调优与踩坑备忘6.1 网络层面MTU、多队列、多路径iSCSI的性能受网络影响最大所以我给的第一个建议就是优先上MTU 9000巨型帧。开启巨型帧需要target服务器和initiator服务器以及中间所有交换机同步支持并启用。只要有一跳不支持结果就是数据包分片甚至丢包反而更慢。修改MTU后记得用ping -M do -s 8972来测试路径是否支持巨型帧。-M do的意思是禁止分片-s 8972是取9000MTU减去IP和ICMP头的标准载荷大小。Ping通之后再跑一轮iperf3确认实际吞吐不要只看协商值。多路径MPIO是另外一个常被忽略的方向。如果服务器有两块网卡可以用Linux的multipath工具将多个路径合并为一个设备既做冗余又提升吞吐。配置多路径前需要注意target侧要创建多个portal每个IP对应一个portal并且initiator侧安装device-mapper-multipathmpathconf --enable systemctl enable multipathd iscsiadm -m node -T iqn... --opupdate -n node.session.timeo.replacement_timeout -v 1206.2 存储层面队列深度和设备参数对Linux initiator/sys/block/sdX/device/queue_depth的默认值可能偏保守增大它能让磁盘并发提上来。但我建议慢慢调别一下子拉满。我遇到过把queue_depth调到256后target侧硬盘直接处于IO饱和状态延迟反而飙升的情况。target侧也要注意backstore类型。fileio如果底下的文件系统是ext4做大量小随机IO时性能一般如果你要追求更好的随机性能可以考虑用块设备backstore或ZFS上的zvol。zvol走的是ZFS的块设备接口做iSCSI target底层非常合适既能拿到ZFS的快照/压缩能力又让iSCSI以块设备方式访问比我之前用普通文件模拟的效果好不少。调试性能的基本思路是先保障网络千兆以上、巨型帧、无丢包再看队列和调度器最后再考虑是否换底层存储方案。不要一上来就怀疑target工具本身。6.3 我保留的三个后悔药脚本搭建过程中我习惯把一些反复操作写成脚本核心就是出事能快速回滚。我的做法是维护三份小脚本脚本作用iscsi_target_backup.sh导出targetcli的配置文件targetcli saveconfig后备份到独立目录iscsi_target_rollback.sh根据备份文件恢复整个targetcli配置iscsi_session_audit.sh轮询所有initiator session记录在线状态到日志文件其中最值得强调的就是targetcli saveconfig。它会把target的所有配置、ACL、认证参数一个不落导成文件恢复时直接加载即可。一旦把CHAP密码、ACL搞乱了脚本恢复比手工改省太多时间。我建议把备份文件放到独立的存储位置最好不在target本机的唯一一块盘上否则连target所在系统都崩了就谈不上恢复。最后还想提一个容易被忽略的事iSCSI链路一旦跑起来它会长时间占用网络连接服务器维护网络时要小心。比如交换机上做端口聚合调整、重启某个网卡都会影响正在运行的iSCSI会话。如果确实要做这类操作先把相关的虚拟机和数据库停掉或迁移走否则等待你的就是一阵IO错误风暴。经历过一次之后我现在都会在设备维护计划里给iSCSI网络单独留一个窗口这大概就是上了年纪的存储运维和年轻时候最大的区别。