Linux Multipath Configuration: multipath.conf for iSCSI SAN - 夜莺博客

Linux Multipath Configuration: multipath.conf for iSCSI SAN

A SAN LUN is only as reliable as its path count: with a single HBA or cable, one failure takes down the filesystem. Device-mapper multipath solves this by presenting one logical device (/dev/mapper/xxx) over many physical paths, failing over and load-balancing between them. This guide covers Linux multipath configuration for iSCSI and FC SANs: discovering the multiple paths, writing /etc/multipath.conf, choosing the path grouping policy, and verifying with multipathd.

Why Multiple Paths Appear as Multiple Disks

Each portal/HBA path to the same LUN shows up as a separate sd device (sdc, sdd, sde...). Writing directly to one of them bypasses failover and risks corruption if two paths are used simultaneously. Multipath detects that all these sd devices share one WWID (World Wide Identifier) and merges them into a single dm-X/mpatha device.

Confirm the paths are visible before configuring anything:

iscsiadm -m session -P3        # show sessions, portals and attached sd devices
ls -l /dev/disk/by-id/         # multiple wwn-* entries -> same WWID
multipath -ll                  # after setup: current multipath topology

For real redundancy, iSCSI paths should use at least two dedicated NICs on separate networks and switches, so a single switch or NIC failure does not take down every path.

Writing /etc/multipath.conf

If the SAN vendor has no specific template, start from a minimal configuration:

defaults {
    user_friendly_names yes
    find_multipaths yes
}

multipaths {
    multipath {
        wwid  36001405f01c2a3b4c5d6e7f8a9b0c1d2
        alias  san-lun01
    }
}

Key parameters that matter in production:

  • uid_attribute - how the WWID is read (default ID_SERIAL for SCSI; ID_WWN for NVMe).
  • path_grouping_policy - failover (one active path) or multibus (all paths active).
  • prio alua - on active/passive arrays, path priority is driven by SCSI-3 ALUA; with prio_args "exclusive_pref_bit" the preferred controller path group gets top priority.
  • path_checker tur - Test Unit Ready is the safe checker for SCSI devices; do not use a checker that sends I/O on active/passive arrays.
  • failback - immediate or a delay, for returning to the preferred path.
  • no_path_retry - how long to queue I/O when every path is down (e.g. queue or a number of retries).

Reload and Verify

systemctl enable --now multipathd
multipath -r                 # reload configuration / re-detect
multipath -ll                # list devices, paths and their states
multipathd show paths format "%d %P"    # per-path: device and protocol
multipathd show maps

In multipath -ll output each path shows active/ready or failed/ghost; ghost is normal for the passive side of an ALUA array. After wiring multipath, format and mount /dev/mapper/alias (or use the WWID symlink in fstab) - never the raw sd device - and verify failover by pulling one path and watching multipath -ll rebalance.

Related Reading

Multipath is the host side of the SAN story; the array and fabric sides are covered in our Brocade FC zoning guide (for FC fabrics), the HPE 3PAR CLI administration reference and the NetApp ONTAP SnapMirror setup for replication on top of the LUNs.

原文链接:https://pve.proxmox.com/wiki/Multipath

Installing Device-Mapper Multipath

Multipath ships as a userspace package plus a kernel module. Install it before wiring any SAN LUNs, because the tools also decide whether devices get claimed in the first place:

# RHEL / Rocky / AlmaLinux
dnf install -y device-mapper-multipath
# Debian / Ubuntu
apt-get install -y multipath-tools

mpathconf --enable --with_multipathd y   # RHEL: writes a starter multipath.conf
lsmod | grep dm_multipath
systemctl enable --now multipathd

On Debian-family systems there is no mpathconf; the package ships a working default configuration and you edit /etc/multipath.conf directly. Either way, confirm the module is loaded and the daemon is running before you attach storage, so the first LUN is claimed on discovery rather than left as bare sd devices.

Blacklisting Devices You Do Not Want Claimed

Blind claiming is dangerous: on a host with local NVMe, RAID virtual disks or a boot SSD, you do not want multipath merging unrelated devices that happen to share a serial pattern. Blacklist by WWID or by device node, then use blacklist_exceptions to re-include the SAN devices you do want:

blacklist {
    wwid 26353900f02796769
    devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
    devnode "^hd[a-z]"
    device {
        vendor  "COMPAQ  "
        product "HSV1[01]1"
    }
}

blacklist_exceptions {
    device {
        vendor  "NETAPP"
        product "LUN.*"
    }
}

Getting the blacklist right is what prevents the classic symptom of a device showing up as both mpatha and a raw sd device, or two unrelated disks being merged because user_friendly_names reassigned the same alias.

Path Grouping Policies in Detail

The grouping policy is the single most consequential setting, because it decides how many paths carry I/O at once:

Policy Behaviour When to use
failover One active path per group; others standby Active/passive arrays without ALUA
multibus All paths active, I/O across all of them Active/active arrays
group_by_prio Group by ALUA/prio value, active per group ALUA active/passive (most common)
group_by_node_name Group by target node name Targets with distinct node names

On a modern ALUA array, group_by_prio with prio alua is almost always correct: the array reports a preferred controller path group, multipath marks those paths active and keeps the other controller's paths as a standby group, and a controller failure triggers a failback to the preferred group as soon as it returns.

Path Selectors, Queueing and Timeouts

Within an active path group, the selector decides which path takes the next I/O. A production defaults block usually looks like this:

defaults {
    path_grouping_policy    group_by_prio
    prio                    alua
    path_selector           "service-time 0"
    path_checker            tur
    failback                immediate
    no_path_retry           30
    dev_loss_tmo            60
    fast_io_fail_tmo        5
}
  • path_selector - round-robin 0 rotates strictly; service-time 0 and queue-length 0 are adaptive and usually give better throughput on mixed workloads.
  • no_path_retry - 30 retries then fails the I/O; queue queues indefinitely, which prevents a filesystem from being unmounted during a long path loss but risks a hung application if the array never returns.
  • fast_io_fail_tmo - how quickly the kernel stops retrying on a known-bad port and fails over, so applications do not block for the full SCSI timeout.
  • dev_loss_tmo - how long the transport waits before removing a lost path entirely; keep it longer than the array's own failover time.

The interaction between queue_if_no_path (via features or no_path_retry queue) and a multi-hour maintenance window is the difference between a cluster that pauses and one that fences and reboots. Test it before production.

Open-iSCSI: Making the Paths Persistent

For iSCSI, the initiator side must keep its sessions logged in across reboots and set sane timeouts, or the paths vanish before multipath ever sees them:

# /etc/iscsi/iscsid.conf
node.startup = automatic
node.session.timeo.replacement_timeout = 120
node.conn[0].timeo.noop_out_interval = 5
node.conn[0].timeo.noop_out_timeout  = 10
node.session.auth.authmethod = CHAP
node.session.auth.username   = initiator-name
node.session.auth.password   = ********

iscsiadm -m node -T iqn.2024-01.com.example:lun01 -p 10.0.0.10:3260 \
  --op update -n node.startup -v automatic
iscsiadm -m node --login

Set node.startup = automatic per node, not just in the defaults, because records created before the config change keep their old value. With CHAP enabled, verify that discovery and login both succeed - a discovery-only success leaves you with no LUNs.

Persistent Names vs User-Friendly Names

Two naming schemes coexist and are easy to confuse. user_friendly_names yes produces mpatha, mpathb and so on, assigned in discovery order and recorded in /etc/multipath/bindings; the WWID alias in the multipaths stanza produces the name you chose, such as san-lun01. For anything scripted, fstab, or shared documentation, prefer the explicit alias or the /dev/disk/by-id/wwn-* symlink. Names assigned by discovery order can shift when a new array is added, and a shifted alias in fstab mounts the wrong filesystem - a failure that is silent and destructive.

Testing Path Failover

A multipath configuration is only proven by breaking it. Bring one path down and watch the topology rebalance:

multipathd show paths format "%d %t %o %T"
multipath -ll

# take one path offline (example sd device) and re-check
echo offline > /sys/block/sdc/device/state
multipathd show paths
echo running > /sys/block/sdc/device/state   # bring it back

During the failure, I/O should continue on the surviving paths with no application-visible error. In multipath -ll the failed path drops out of the active group and the device stays usable. Reverse the test afterwards and confirm the preferred path is reclaimed, which proves failback is working the way the design intends.

Performance Tuning and Benchmarking

for i in /sys/block/dm-*/queue/scheduler; do echo none > "$i"; done
for i in /sys/block/dm-*/queue/nr_requests; do echo 1024 > "$i"; done

fio --name=seqread --rw=read --bs=1M --direct=1 --size=1G \
    --filename=/dev/mapper/san-lun01 --ioengine=libaio --iodepth=32

Benchmark the mapper device, never a raw sd device, or all paths will not be exercised and the numbers will be wrong. Getting identical throughput with one path offline and all paths online points at a bottleneck in the array or fabric rather than in multipath itself.

Troubleshooting Common Problems

  • Duplicate devices - one LUN appears as both mpatha and sdX: the device was claimed before multipathd started, so rescan or reboot with the daemon enabled.
  • All paths marked ghost - normal for the passive side of an ALUA array, but if every path is ghost, the array is not reporting an active controller; check zoning and LUN presentation.
  • Aliases changed after adding a LUN - discovery-order naming shifted; pin names with explicit alias entries.
  • I/O queues forever during maintenance - no_path_retry queue is in effect; set a bounded retry count for hosts that must fail fast.
  • Filesystem not mounted after reboot - the iSCSI session is not marked automatic, so the mapper device never appeared.
  • Wrong device in fstab - a raw /dev/sdX entry; replace it with the mapper alias or WWID symlink.

Check dmesg | grep -i multipath and journalctl -u multipathd when a device is claimed but behaves oddly; the messages usually name the exact path and state transition.

Choosing Between Active/Active and Active/Passive

The array's port behaviour, not the host's preference, decides this. If both controllers can serve a LUN concurrently, an active/active array rewards multibus or group_by_prio with real aggregate bandwidth. If only one controller nodes a LUN at a time, as many midrange arrays do, forcing all paths active produces sent LUN resets and intermittent I/O errors. Ask the array vendor for the host-attach profile for your model and firmware, apply their multipath template, and only deviate from it with a documented reason - vendor templates already encode the timeout and checker values that the array's own failover logic expects.

Related Reading on This Site

Multipath is the host side of the SAN story: for the transport decision behind it, see FC vs iSCSI SAN and FC vs iSCSI vs NVMe-oF. If you are building the target side yourself, the Linux iSCSI target with targetcli guide pairs directly with this one.