2026/10/22 5:11:24

iSCSI多路径实战:从原理到配置,彻底解决链路故障与性能瓶颈

iSCSI多路径实战:从原理到配置,彻底解决链路故障与性能瓶颈 1. 为什么我要折腾 iSCSI 多路径这套东西存储这摊事儿单线走久了迟早要撞墙。我最早接触 iSCSI 是在一台跑数据库的机器上当时图省事存储和主机之间就一条千兆链路直连跑了大半年没出过岔子直到某天业务高峰期磁盘 IO 直接卡成幻灯片一查才发现那条链路带宽早就被打满了而且交换机端口还偶发丢包。那次之后我就明白一个道理iSCSI 这种基于 IP 网络的块存储链路本身就是最大的不确定性来源。网线会松、网卡会坏、交换机会抽风、端口会协商降速任何一环出问题上层业务感受到的就是 IO hang 甚至文件系统只读。多路径multipath就是冲着这个痛点来的。它的核心思路很朴素主机和存储之间同时建立多条物理或逻辑通路操作系统层面把这些通路聚合成一个逻辑设备IO 分发时按策略走不同的路。一条路断了流量自动切到其他路业务几乎无感。听起来简单但真到落地的时候坑一个接一个——设备名乱跳、路径状态识别错误、策略选错导致单边压满、LUN 重复识别、开机自动挂载顺序错乱这些我都踩过。这篇东西我打算把 iSCSI 多路径这套实验从头到尾捋一遍包括为什么要这么设计、内核和用户态组件各自负责什么、multipath.conf 里每个参数到底在管什么、怎么验证路径切换真的生效、以及那些文档里不会写但生产环境一定会遇到的坑。适合已经懂基本 Linux 存储操作、想把这套东西真正跑通并且敢往生产上放的人看。如果你只是想知道“多路径是啥”那随便搜一篇科普就够了但如果你想自己搭一套能扛住链路抖动的 iSCSI 多路径环境那接下来的内容应该能帮你少走不少弯路。我这次实验的环境是两台虚拟机加一个模拟存储端主机侧两块网卡分别接到两个不同的网段存储端也对应两个 IP 提供同一个 LUN。这样做的目的是让每条路径真正独立避免两块网卡走同一个交换机端口导致“假多路径”。下面我会按设计思路、组件拆解、实操配置、验证排查这个顺序来讲中间穿插我自己踩过的坑和实测数据。2. iSCSI 多路径的整体设计与组件拆解2.1 多路径到底解决的是哪几类问题很多人一提到多路径就只想到“冗余”其实它解决的是三个层面的问题而且优先级不一样。第一层是高可用。这是最刚需的。单条 iSCSI 链路里任何一个环节故障都会导致 IO 中断。多路径让主机同时看到同一个 LUN 的多条通路某条路 down 掉之后内核的 multipath 层会把 IO 重新路由到存活路径上。这里的关键是切换要快最好在业务超时之前完成否则应用层还是会报错。第二层是负载均衡。多条路径如果只用来做备份那平时就浪费了带宽。多路径可以把 IO 分散到多条链路上提升整体吞吐。但这里有个陷阱不同的负载均衡策略效果差异巨大选错了不但不提升反而会因为路径切换开销导致性能下降。第三层是路径管理可视化。多路径工具会维护一张路径状态表哪条 active、哪条 failed、哪条处于 ghost 状态一目了然。这对排障太重要了没有这套东西你只能靠猜。我这次实验主要验证前两层第三层是顺带观察。设计上我采用双网卡双网段的拓扑主机侧两张网卡分别配置在不同子网存储端两个 portal 也对应不同子网。这样每条路径经过的物理链路、交换机端口、甚至网段都是独立的最大程度模拟真实的多路径场景。2.2 内核层与用户态的分工iSCSI 多路径在 Linux 上其实是两套机制配合dm-multipath和iSCSI 会话管理。dm-multipath 是 device-mapper 的一个 target工作在内核态负责把多个底层块设备这里就是多个 iSCSI 会话对应的 sd 设备聚合成一个 dm 设备。它维护路径组path group、优先级priority、路径状态active/failed/ghost并根据策略决定 IO 走哪条路。iSCSI 会话管理则分两部分内核态的 iscsi_tcp或 iscsi_iser 等负责实际的 TCP 传输和 SCSI 命令封装用户态的 iscsid 和 iscsiadm 负责会话建立、发现、登录、登出。多路径要生效前提是主机能同时登录到同一个 target 的多个 portal并且这些会话对应的 LUN 被正确识别为“同一设备的不同路径”。这里有个关键点multipath 判断两个 sd 设备是不是同一个 LUN靠的是 SCSI 设备标识具体来说是 WWIDWorld Wide Identifier通常来自 LUN 的 page 0x83 或 0x80。如果存储端没有正确返回这些标识multipath 就会把它们当成不同设备多路径直接失效。我实验里用的模拟存储端一开始就没配好导致主机看到两个独立的 sd 设备差点以为是多路径没生效后来查了multipath -ll的输出才发现 WWID 不一样。2.3 为什么选 dm-multipath 而不是其他方案Linux 上做多路径其实不止一种选择。早期有人用 md-raid 把多个设备做成 raid1但那玩意儿对块设备的语义理解不对iSCSI 路径切换时容易出问题。还有用 LVM 做条带的那更偏向性能聚合而不是冗余。dm-multipath 是专门为多路径块设备设计的它理解 SCSI 路径状态支持多种负载均衡策略还能和 udev 配合做持久化命名是目前最成熟的选择。我选它的另一个原因是可观测性好。multipath -ll能直接看到每条路径的状态、优先级、dm 设备名multipathd show paths还能实时刷新。相比之下自己用脚本拼凑的方案在排障时基本抓瞎。2.4 拓扑设计与 IP 规划实验拓扑我画个文字版主机侧两块网卡 eth1、eth2分别配 192.168.10.10/24 和 192.168.20.10/24存储侧两个 portal192.168.10.100 和 192.168.20.100提供同一个 target 的同一个 LUN中间两个独立的二层网络模拟两条物理隔离的链路IP 规划上我特意让两个网段完全独立避免路由表里出现等价路由导致流量走同一条路。如果你用同一个网段配两个 IP那多路径虽然也能建起来但实际流量可能都从一张网卡出去那就失去意义了。这一点在实验环境里特别容易被忽略因为虚拟机默认可能只挂一个虚拟交换机。提示做多路径实验前先用ip route get 存储IP确认去往每个 portal 的出口网卡是不是符合预期。如果两个 portal 的路由都指向同一张网卡那多路径就是摆设。3. 核心配置细节与实操要点3.1 存储端 target 配置的关键参数存储端我用的是 Linux 上常见的 targetcli 来模拟。配置 target 的时候有几个点直接决定多路径能不能成。首先是portal 的绑定。target 要监听两个不同的 IP每个 IP 对应一个 portal。命令大概是targetcli /iscsi create iqn.2024-01.com.example:storage.target01 targetcli /iscsi/iqn.2024-01.com.example:storage.target01/tpg1/portals create 192.168.10.100 targetcli /iscsi/iqn.2024-01.com.example:storage.target01/tpg1/portals create 192.168.20.100注意这里两个 portal 都挂在同一个 tpg 下这样它们共享同一个 LUN 配置。如果你建了两个 tpg那 LUN 要分别配而且 WWID 可能不一致多路径就认不出来了。其次是LUN 的 WWID 配置。targetcli 里可以通过alua和inquiry相关设置影响返回的标识。默认情况下 backstore 的 WWID 是基于存储对象生成的两个 portal 返回的应该一致。我实验里用的是 fileio backstoreWWID 默认就一样没出问题。但如果你用 block backstore 或者某些硬件存储一定要确认两个 portal 返回的 page 0x83 内容一致。第三是ACL 配置。主机的 initiator IQN 要加到 target 的 ACL 里否则登录会被拒。这个基础操作就不展开了但要注意两个 portal 都要能接受同一个 initiator 登录。3.2 主机侧 iSCSI 发现与登录主机侧第一步是发现 targetiscsiadm -m discovery -t sendtargets -p 192.168.10.100 iscsiadm -m discovery -t sendtargets -p 192.168.20.100这两条命令会分别向两个 portal 发起发现返回的 target 信息会记录在/etc/iscsi/nodes/下。这里有个细节发现记录是按 portal 分开存的所以两个 portal 的发现结果会各自生成一份节点配置。登录的时候iscsiadm -m node -T iqn.2024-01.com.example:storage.target01 -p 192.168.10.100 -l iscsiadm -m node -T iqn.2024-01.com.example:storage.target01 -p 192.168.20.100 -l两条都登录成功后iscsiadm -m session应该能看到两个会话。这时候lsblk或cat /proc/partitions会看到两个新的 sd 设备比如 sdb 和 sdc。如果存储端 WWID 配置正确这两个设备其实就是同一个 LUN 的两条路径。注意登录顺序不影响多路径识别但如果你先登录一个等 multipath 把设备聚合了再登录第二个multipathd 可能需要手动触发一次 reconfigure 才能发现新路径。我一般习惯两个都登录完再启动 multipathd省得来回折腾。3.3 multipath.conf 的核心参数逐条拆解multipath 的配置文件在/etc/multipath.conf。默认这个文件可能不存在或者全是注释需要自己写。我实验里用的配置大概长这样defaults { user_friendly_names yes path_grouping_policy multibus path_selector round-robin 0 failback immediate no_path_retry 5 rr_min_io_rq 1000 } blacklist { devnode ^sd[a]$ } multipaths { multipath { wwid 360014050000000000000000000000001 alias iscsi_lun0 } }逐条说。user_friendly_names yes会让 dm 设备用mpathX这种名字而不是一长串 WWID。方便是方便但有个坑mpathX 的编号是动态分配的重启或者设备增减后可能变。生产环境我建议用alias显式绑定或者干脆用 WWID 做持久化。我实验里图省事开了 friendly names结果重启后 mpatha 变成了 mpathb挂载脚本直接失败后来改成 alias 才稳。path_grouping_policy multibus是关键。它决定路径怎么分组。multibus把所有路径放在一个组里所有路径都能同时承载 IO适合负载均衡。failover则是每组只有一条 active 路径其他待命适合主备模式。我实验里要验证负载均衡所以选 multibus。但要注意multibus 下如果存储端不支持并发访问同一个 LUN可能会出数据一致性问题。iSCSI 场景下一般没问题因为 SCSI 层有命令队列和锁机制。path_selector round-robin 0是轮询策略IO 依次分发到各条路径。这是最常用的负载均衡策略。还有个queue-length策略按队列深度分发适合路径性能不均的场景。我实测下来 round-robin 在两条对等链路下效果最稳。failback immediate表示路径恢复后立即切回。如果设成某个延迟值路径恢复后会等一段时间再切回避免抖动。生产环境如果链路不稳定可以设个 30 秒左右的延迟减少来回切换的开销。no_path_retry 5是路径全挂之后重试几次再报错。设成queue会一直排队等路径恢复适合不能丢 IO 的场景但可能导致进程 hang 住。我实验里设 5意思是重试 5 次后返回错误避免无限等待。rr_min_io_rq 1000是轮询粒度表示每条路径连续处理 1000 个请求后切换到下一条。这个值太小会导致频繁切换增加开销太大则负载不均。1000 是个比较中庸的值实测在 SSD 存储上表现不错。3.4 设备黑名单与白名单的取舍blacklist那块我写了devnode ^sd[a]$意思是把 sda 排除掉因为那是系统盘。如果不排除multipath 可能会把本地盘也纳入管理导致启动时找不到根文件系统。这个坑我踩过一次当时没配黑名单重启后系统直接进 emergency mode因为 multipath 把根盘聚合了但没正确挂载。更稳妥的做法是用blacklist_exceptions白名单模式只让 iSCSI 设备进多路径。但白名单要写 WWID 或者 devnode 正则配置起来麻烦一点。实验环境用黑名单够了生产环境我建议白名单避免误伤。4. 完整实操流程与验证方法4.1 从零搭建的完整步骤我把整个流程按顺序列一遍方便你照着做。第一步存储端配置 target 和两个 portal创建 backstore 和 LUN配置 ACL 允许主机 initiator 登录。完成后用targetcli ls确认 portal 和 LUN 都在。第二步主机侧安装必要软件包。不同发行版包名不一样常见的是iscsi-initiator-utils、device-mapper-multipath。装完后启动iscsid和multipathd服务。第三步配置主机网卡和路由确保两个 portal 可达且走不同网卡。用ping -I eth1 192.168.10.100和ping -I eth2 192.168.20.100分别验证。第四步发现并登录两个 portal。登录后用iscsiadm -m session -P 3查看会话详情确认两个会话都处于 logged in 状态。第五步写 multipath.conf启动 multipathd用multipath -ll查看聚合结果。正常的话应该看到一个 mpath 设备下面挂着两个 sd 设备状态都是 active。第六步在 mpath 设备上创建文件系统并挂载。注意要挂/dev/mapper/mpathX而不是/dev/sdb否则多路径就白配了。第七步验证负载均衡和故障切换。这部分下面单独讲。4.2 验证多路径是否真正生效配完之后最怕的就是“看起来生效了其实没有”。我一般用三个手段交叉验证。第一个是multipath -ll的输出。正常应该类似iscsi_lun0 (360014050000000000000000000000001) dm-2 LIO-ORG,FILEIO size10G features1 queue_if_no_path hwhandler0 wprw -- policyround-robin 0 prio1 statusactive |- 3:0:0:0 sdb 8:16 active ready running - 4:0:0:0 sdc 8:32 active ready running关键看两点两个 sd 设备是否都在同一个 mpath 下状态是否都是 active ready running。如果只有一个或者状态是 failed那就有问题。第二个是实际 IO 测试。我用 fio 对 mpath 设备做顺序读同时在两个网卡上用sar -n DEV 1观察流量。如果 round-robin 生效两张网卡的接收流量应该大致相当。如果只有一张网卡有流量那说明多路径没真正分发。第三个是故障切换测试。手动把一条路径 down 掉比如ip link set eth1 down然后观察multipath -ll里对应路径是否变成 failed同时 fio 是否还在正常跑。理想情况下 fio 会有短暂卡顿但不断流。我实测下来round-robin 策略下切换时间大概在几百毫秒到一秒之间取决于 IO 队列深度。4.3 路径切换的实测数据与观察我做了几组对比测试数据如下场景平均 IOPS平均延迟切换耗时单路径120000.8ms不适用双路径 round-robin230000.45ms不适用双路径手动 down 一条115000.9ms约 600ms双路径路径恢复225000.47ms约 200ms从数据看双路径 round-robin 的 IOPS 接近单路径的两倍说明负载均衡确实生效了。切换耗时在 600ms 左右对于大多数业务来说可以接受但如果你的应用超时设置很短可能需要调优no_path_retry和队列参数。路径恢复后切回很快200ms 左右因为failback immediate让 multipathd 立即重新评估路径组。4.4 持久化挂载与开机自动生效实验环境重启后多路径要能自动恢复这需要几个配置配合。首先是 iSCSI 会话自动登录。iscsiadm的节点配置里有个node.startup参数设成automatic就会开机自动登录。可以用iscsiadm -m node -T target -p portal -o update -n node.startup -v automatic来设置。其次是 multipathd 开机自启。systemctl enable multipathd即可。第三是文件系统挂载。/etc/fstab里要写/dev/mapper/iscsi_lun0或者用 UUID。我建议用 UUID因为 mpath 的 alias 虽然稳定但万一 WWID 变了 UUID 也会变用 UUID 至少能保证挂载的是正确的文件系统。不过 UUID 在多路径场景下有个问题同一个 LUN 的两条路径对应的 sd 设备 UUID 是一样的所以用 UUID 挂载没问题。提示fstab 里最好加上_netdev选项让系统等网络就绪后再挂载避免开机时 iSCSI 还没登录就尝试挂载导致失败。5. 常见问题与排查技巧实录5.1 多路径不聚合的几种典型原因这是最常见的问题登录了两个 portal但multipath -ll只显示一个设备或者显示两个独立的 mpath 设备。原因一WWID 不一致。存储端两个 portal 返回的 SCSI 标识不同multipath 就认为是两个不同 LUN。排查方法是cat /sys/block/sdb/device/wwid和cat /sys/block/sdc/device/wwid对比是否一致。不一致的话要去存储端查 LUN 配置。原因二multipath.conf 黑名单误伤。如果 devnode 正则写得太宽把 iSCSI 设备也排除了就不会聚合。检查multipathd show blacklist的输出。原因三multipathd 没重新加载配置。改完配置文件要systemctl reload multipathd或者multipathd reconfigure否则还是用旧配置。原因四设备被其他层占用。比如 LVM 或者 mdraid 已经抓取了 sd 设备multipath 就插不进去。用dmsetup ls和cat /proc/mdstat检查。5.2 路径状态异常的处理有时候multipath -ll里路径状态是failed或者ghost但实际网络是通的。failed通常是 SCSI 层检测到 IO 错误。可能是存储端 LUN 有问题或者路径上的 MTU 不匹配导致大包被丢。检查dmesg里有没有 SCSI error 或者 iSCSI 连接重置的日志。ghost状态一般出现在 ALUA 场景表示这条路径暂时不可用但没完全失败。如果存储端不支持 ALUA一般不会出现这个状态。出现了的话检查存储端的 ALUA 配置。还有一种情况是路径状态在active和failed之间反复跳这叫路径抖动。通常是链路质量差或者存储端响应慢。可以调大polling_interval减少检测频率或者用failback延迟来抑制切换。5.3 性能不达预期的调优方向如果多路径配好了但性能没提升可以从几个方向查。第一确认 IO 真的走了多条路径。用iostat -x 1看每个 sd 设备的 util 和 r/s如果只有一块盘有负载那 round-robin 没生效。检查path_selector配置和rr_min_io_rq值。第二检查网卡和交换机是否有瓶颈。两条千兆链路理论总带宽 2Gbps但如果交换机上行端口只有千兆那聚合后还是受限。用ethtool确认网卡协商速率用交换机管理界面看端口利用率。第三看存储端是不是瓶颈。模拟存储端如果用的是单块机械盘做 backstore那多路径再厉害也快不了。我实验里用的是内存盘做 backstore排除了存储端瓶颈。第四检查 IO 调度器和队列深度。多路径设备默认可能用mq-deadline调度器对 iSCSI 来说none或者kyber可能更合适。队列深度nr_requests也要根据存储端能力调整。5.4 常见问题速查表现象可能原因排查命令解决方向只看到一个 sd 设备第二个 portal 未登录iscsiadm -m session重新登录两个 sd 设备未聚合WWID 不一致cat /sys/block/sdX/device/wwid检查存储端 LUN 配置mpath 设备名重启后变化未配 aliasmultipath -ll配置 alias 或改用 WWID路径状态反复 failed/active链路抖动dmesg、multipathd show paths调大 polling_interval性能无提升策略未生效iostat -x 1检查 path_selector开机挂载失败网络未就绪journalctl -bfstab 加 _netdev系统盘被多路径接管黑名单未配multipath -ll配置 blacklist5.5 我踩过的几个印象深刻的坑第一个坑是用 friendly names 导致挂载错设备。有次实验环境重启后 mpatha 和 mpathb 对调了fstab 里写的是 mpatha结果挂载到了错误的 LUN 上差点把测试数据写坏。后来全部改成 alias 显式绑定 WWID再没出过问题。第二个坑是两个 portal 走同一张网卡。虚拟机默认只有一个虚拟网卡我加了第二块但没配路由结果两个 portal 的流量都从第一块网卡出去。多路径看起来是两条实际是一条。用ip route get才发现问题。第三个坑是no_path_retry 设成 queue 导致进程 hang。有次测试把所有路径都 down 了结果 fio 进程一直卡着不退出因为 IO 在队列里无限等待。后来改成有限重试虽然会报错但至少不会 hang 死。第四个坑是multipathd 和 udev 的竞争。有次设备刚识别出来udev 还没处理完multipathd 就抢着去聚合结果生成了一个不完整的 mpath 设备。后来在 udev 规则里加了等待或者干脆延迟启动 multipathd问题就没了。6. 把这套东西放到真实环境里还要注意什么实验环境跑通只是第一步真往生产上放还有几个维度要考虑。监控。多路径的路径状态必须纳入监控否则路径悄悄 failed 了你都不知道等最后一条路也断了才告警就晚了。我一般用multipathd show paths raw format %d %t %o定期采集路径状态不是 active 就告警。另外 iSCSI 会话状态、dm 设备的 IO 错误计数也要监控。容量规划。多路径聚合的是带宽和冗余不是容量。同一个 LUN 的多条路径看到的还是同一个 LUN容量不会翻倍。别指望多路径能扩容。变更管理。改 multipath.conf 或者增删路径都要走变更流程因为一旦配错可能导致 IO 中断。我习惯先在测试环境验证再灰度到生产。改之前备份配置改之后用multipathd show config确认生效。和集群软件的配合。如果上层是集群文件系统或者数据库集群多路径的故障切换时间要和集群的心跳超时匹配。切换太慢可能导致集群误判节点故障触发不必要的 failover。固件和驱动版本。iSCSI initiator 和网卡驱动的版本对多路径稳定性影响很大。我遇到过老版本驱动在路径切换时丢包的问题升级后就好了。生产环境要保持固件和驱动在厂商推荐的版本上。这套 iSCSI 多路径的实验我前后折腾了大概两周从最开始的两个独立设备认不出来到后来能稳定跑 round-robin 并且故障切换在秒级完成中间查了无数日志和内核文档。现在回头看核心就三件事WWID 要一致、路由要分离、策略要匹配场景。把这三件事做对剩下的就是调参和验证的体力活了。如果你也在搭类似的环境建议先用虚拟机把流程跑通再上真实硬件能省不少排查时间。