Представьте хранилище, к которому ведёт единственный физический путь. Один кабель, один порт HBA, один коммутатор. Такая схема работает ровно до первой аппаратной неисправности - и в этот момент хранилище просто пропадает. Все приложения, которые с ним работали, зависают в ожидании I/O, базы данных накапливают незавершённые транзакции, а администратор судорожно ищет запасной кабель. Multipath I/O - это ответ на этот сценарий: несколько независимых физических путей к одному LUN, объединённых в единое логическое устройство на уровне ядра Linux.
Но MPIO - это не просто "воткнуть два кабеля и наслаждаться". Неправильно настроенный multipath способен причинить больше вреда, чем его отсутствие: устройство будет видно через несколько путей как несколько разных дисков, и если файловая система окажется смонтирована на одном из них напрямую, а не через мультипатный маппер - данные будут испорчены. Понимание архитектуры здесь не менее важно, чем сами команды.
Архитектура dm-multipath и место в стеке хранения
Linux-реализация MPIO называется Device Mapper Multipath - dm-multipath. Она работает на уровне device mapper, того же слоя, на котором сидят LVM и dm-crypt. Демон multipathd следит за состоянием путей, обрабатывает события появления и пропадания устройств, а при отказе одного пути перенаправляет I/O на оставшиеся без участия приложения.
Физически один LUN на хранилище при наличии нескольких путей виден операционной системе как несколько отдельных блочных устройств - /dev/sdb, /dev/sdc, /dev/sdd. У каждого из них одинаковый WWID - World Wide Identifier, уникальный идентификатор, присвоенный самим хранилищем. Именно по WWID multipathd понимает, что три разных блочных устройства - это один и тот же LUN, доступный по трём путям, и объединяет их в одно устройство /dev/mapper/mpathX. С этим устройством и работают файловая система, LVM, база данных - всё, что выше в стеке хранения.
Прежде чем настраивать multipath.conf, нужно установить пакеты и убедиться, что демон запущен:
# Debian/Ubuntu
apt install multipath-tools multipath-tools-boot -y
# RHEL/Rocky/AlmaLinux
dnf install device-mapper-multipath -y
# Включить и запустить демон
systemctl enable --now multipathd
systemctl status multipathd
Сгенерировать базовый конфигурационный файл можно через встроенную утилиту - она опросит подключённые устройства и создаст шаблон с определёнными значениями по умолчанию:
mpathconf --enable --with_multipathd y
На RHEL-системах эта команда создаёт /etc/multipath.conf с минимально рабочей конфигурацией. На Debian и Ubuntu файл нужно создавать вручную - там mpathconf отсутствует, зато пакет multipath-tools уже содержит встроенные профили для распространённых СХД.
Fibre Channel - обнаружение HBA и зонирование
Для Fibre Channel работа начинается ещё до настройки multipathd. FC - это выделенная сеть хранения, где каждый HBA (Host Bus Adapter) имеет свой WWN (World Wide Name), аналог MAC-адреса в Ethernet. Зонирование на FC-коммутаторе определяет, какой инициатор (серверный HBA) видит какой таргет (порт СХД). Без правильного зонирования сервер либо не увидит хранилище вовсе, либо увидит больше, чем нужно.
Проверить состояние FC-адаптеров и их WWN на сервере:
# Список всех FC-портов и их состояние
ls /sys/class/fc_host/
# WWN каждого порта
cat /sys/class/fc_host/host*/port_name
# Состояние соединения с фабрикой
cat /sys/class/fc_host/host*/port_state
# Online - порт подключён к коммутатору
Эти WWN нужно сообщить администратору SAN для создания зон. Стандартная схема зонирования для двухпортового HBA и двухконтроллерной СХД выглядит так: каждый порт HBA зонируется с одним контроллером хранилища. Порт HBA0 видит Controller A, порт HBA1 видит Controller B. Это даёт два независимых пути к каждому LUN через физически разные компоненты.
После настройки зонирования и подключения LUN на хранилище можно просканировать FC-шину на наличие новых устройств - без перезагрузки:
# Принудительный ресканирование для каждого FC-хоста
for host in /sys/class/scsi_host/host*; do
echo "- - -" > $host/scan
done
# Проверить, что устройства появились
lsblk -o NAME,SIZE,TRAN,VENDOR,MODEL | grep -v loop
# Посмотреть SCSI-устройства с WWN
lsscsi -t
Если в выводе lsscsi -t один и тот же LUN виден несколько раз с одинаковым WWID через разные пути - всё идёт правильно. Именно эти несколько блочных устройств multipathd должен объединить в одно.
iSCSI - настройка инициатора и многосессионность
iSCSI работает поверх обычного Ethernet, что делает его доступнее FC с точки зрения стоимости инфраструктуры. Зато и уязвимостей у него больше: сетевые задержки, джиттер, конкуренция с другим трафиком. Для MPIO через iSCSI нужно как минимум два физических NIC на отдельных коммутаторах - иначе отказ коммутатора устраняет все пути одновременно, и multipath становится бесполезным.
Установка iSCSI-инициатора:
# Debian/Ubuntu
apt install open-iscsi -y
systemctl enable --now iscsid
# RHEL/Rocky
dnf install iscsi-initiator-utils -y
systemctl enable --now iscsid
IQN (iSCSI Qualified Name) инициатора находится в файле /etc/iscsi/initiatorname.iscsi. Это идентификатор, который СХД использует для авторизации - его нужно сообщить администратору хранилища для настройки ACL.
Для MPIO через iSCSI каждый путь создаётся как отдельная iSCSI-сессия через отдельный NIC к отдельному IP-адресу таргета. Обнаружить таргеты через первый интерфейс:
iscsiadm -m discovery -t sendtargets -p 192.168.10.100
# Вывод: 192.168.10.100:3260,1 iqn.2024-01.com.storage:target1
Затем войти в таргет через второй интерфейс, добавив второй путь:
iscsiadm -m discovery -t sendtargets -p 192.168.20.100
iscsiadm -m node --login
# Проверить активные сессии
iscsiadm -m session -P 3
Параметр -P 3 в последней команде выводит детальную информацию по каждой сессии, включая интерфейс, через который она установлена, и состояние подключения. Если обе сессии присутствуют и активны, а lsblk показывает по два блочных устройства одинакового размера - пути созданы.
Перед тем как передать устройства в управление multipathd, критически важно настроить тайм-ауты iSCSI так, чтобы при отказе пути ошибки немедленно передавались наверх в multipath-слой. Без этой настройки iSCSI будет несколько минут пытаться самостоятельно восстановить сессию, блокируя I/O вместо быстрого переключения на альтернативный путь.
В /etc/iscsi/iscsid.conf задаются ключевые тайм-ауты:
# Время ожидания замены сессии при использовании dm-multipath
node.session.timeo.replacement_timeout = 5
# Интервал между NOP-Out keepalive-пакетами
node.conn[0].timeo.noop_out_interval = 5
# Таймаут ответа на NOP-Out - если нет ответа, путь считается мёртвым
node.conn[0].timeo.noop_out_timeout = 5
# Таймаут входа в сессию
node.conn[0].timeo.login_timeout = 15
Значение replacement_timeout = 5 означает: если iSCSI не может восстановить сессию за 5 секунд, он немедленно поднимает ошибку I/O в SCSI-слой. SCSI передаёт её multipathd, и тот переключается на живой путь. Без этой настройки значение по умолчанию - 120 секунд, что в контексте MPIO совершенно неприемлемо.
Полная конфигурация multipath.conf для enterprise-среды
Конфигурационный файл /etc/multipath.conf состоит из четырёх секций с чётко определённым приоритетом: defaults задаёт глобальные параметры, devices переопределяет их для конкретных моделей СХД, blacklist исключает устройства из управления multipathd, multipaths позволяет настроить каждый LUN индивидуально по WWID.
Полная рабочая конфигурация для enterprise-среды с ALUA-совместимыми массивами:
defaults {
user_friendly_names yes # mpath0, mpath1 вместо WWID
find_multipaths yes # Автоматически обнаруживать пути
path_grouping_policy group_by_prio # Группировать по ALUA-приоритету
path_selector "service-time 0" # Выбирать путь с наименьшим временем отклика
path_checker tur # Test Unit Ready - универсальный checker
prio alua # Приоритет на основе SCSI-3 ALUA
hardware_handler "1 alua" # Обработчик для ALUA-переключения
failback immediate # Возврат на основной путь сразу после восстановления
no_path_retry queue # Ставить I/O в очередь при отсутствии путей
polling_interval 5 # Проверять пути каждые 5 секунд
fast_io_fail_tmo 5 # FC: секунды до объявления пути мёртвым
dev_loss_tmo 30 # Секунды до удаления устройства из системы
rr_min_io 128 # Минимум I/O перед переключением пути
}
blacklist {
# Исключить локальные диски сервера из управления multipath
devnode "^sda" # Первый диск - обычно системный
devnode "^nvme0" # Локальный NVMe (если есть)
# Исключить по типу протокола - не трогать ATA-устройства
protocol "scsi:ata"
}
devices {
# NetApp ONTAP - active-active через ALUA
device {
vendor "NETAPP"
product "LUN.*"
hardware_handler "1 alua"
prio alua
path_grouping_policy group_by_prio
failback immediate
no_path_retry queue
rr_weight uniform
}
# Pure Storage - active-active, все пути равнозначны
device {
vendor "PURE"
product "FlashArray"
path_grouping_policy multibus
path_selector "round-robin 0"
path_checker tur
hardware_handler "0"
failback immediate
no_path_retry queue
}
# EMC/Dell PowerStore - ALUA
device {
vendor "DellEMC"
product ".*"
hardware_handler "1 alua"
prio alua
path_grouping_policy group_by_prio
failback immediate
}
}
# Именованные псевдонимы для конкретных LUN по WWID
multipaths {
multipath {
wwid 3600508b4000156d70001200000010000
alias oracle_data
}
multipath {
wwid 3600508b4000156d70001200000020000
alias postgres_wal
}
}
Здесь несколько параметров заслуживают отдельного объяснения. path_grouping_policy group_by_prio в сочетании с prio alua - это правильный выбор для большинства современных СХД. ALUA (Asymmetric Logical Unit Access) - стандарт SCSI-3, который позволяет хранилищу сообщать о предпочтительных и непредпочтительных путях. Для active-passive массивов active-контроллер получает высокий приоритет, standby - низкий. Для active-active массивов все пути равнозначны.
fast_io_fail_tmo для Fibre Channel играет ту же роль, что replacement_timeout для iSCSI: ограничивает время, которое проходит между аппаратным отказом и переключением на резервный путь. Значение 5 секунд - разумный компромисс между скоростью реакции и устойчивостью к кратким флуктуациям канала.
После внесения изменений в конфигурацию её нужно валидировать и применить:
# Проверить синтаксис конфигурации
multipath -t
# Применить конфигурацию без перезапуска демона
multipathd reconfigure
# Или перечитать конфиг с полным сбросом состояния
multipathd -k"reconfigure"
Диагностика и проверка работы мультипатинга
Настроить MPIO и убедиться, что он работает правильно - разные задачи. Главный инструмент диагностики - команда multipath -ll, которая показывает текущее состояние всех мультипатных устройств со всеми их путями:
multipath -ll
Типичный вывод для здоровой конфигурации выглядит так:
oracle_data (3600508b4000156d70001200000010000) dm-2 NETAPP,LUN
size=500G features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| |- 1:0:0:1 sdb 8:16 active ready running
| `- 2:0:0:1 sdc 8:32 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
|- 1:0:1:1 sdd 8:48 active ready running
`- 2:0:1:1 sde 8:64 active ready running
Здесь видны две группы путей: основная с приоритетом 50 (active - текущий I/O) и резервная с приоритетом 10 (enabled - готова к работе). Четыре пути, два активных контроллера - типичная active-passive конфигурация с ALUA.
Ключевые слова в этом выводе - active ready running. Если вместо них появляется failed faulty или dm checker failed - путь нездоров. Проверить, что именно не так с конкретным путём:
# Статус отдельного пути
multipathd show paths format "%d %t %i %s %o"
# %d - устройство, %t - состояние, %i - приоритет, %s - SCSI-адрес, %o - статус I/O
# Проверить, есть ли ошибки в логе multipathd
journalctl -u multipathd --since "1 hour ago" | grep -E 'fail|error|down'
Симулировать отказ пути для проверки failover - обязательный шаг перед тем, как доверить систему продакшн-нагрузке. Для FC это делается физическим отключением кабеля или отключением зоны. Для iSCSI - блокировкой сетевого интерфейса:
# Заблокировать один из iSCSI-интерфейсов
ip link set eth1 down
# Убедиться, что multipath переключился на альтернативный путь
multipath -ll
# Один путь должен стать failed, I/O должен продолжиться через оставшиеся пути
# Восстановить интерфейс
ip link set eth1 up
# Убедиться, что путь вернулся в active
multipath -ll
Время переключения между моментом отказа и возобновлением I/O через альтернативный путь должно укладываться в несколько секунд - в зависимости от polling_interval и тайм-аутов. Если I/O висит дольше 30 секунд - что-то настроено неправильно, и это нужно найти до, а не во время аварии.
Интеграция с LVM и монтирование через fstab
Мультипатное устройство готово принимать файловые системы и тома LVM. Важное правило: всё, что создаётся поверх мультипатного устройства, должно ссылаться на /dev/mapper/имя, а не на /dev/sdb или другой отдельный путь. LVM при инициализации физического тома запоминает WWID устройства и при следующем старте системы сам найдёт правильный маппер.
# Создать PV на мультипатном устройстве
pvcreate /dev/mapper/oracle_data
# Создать VG
vgcreate vg_oracle /dev/mapper/oracle_data
# Создать LV
lvcreate -L 400G -n lv_data vg_oracle
# Создать файловую систему
mkfs.xfs /dev/vg_oracle/lv_data
В /etc/fstab устройства монтируются через UUID или по пути к LV - никогда напрямую через /dev/sdb:
/dev/vg_oracle/lv_data /mnt/oracle xfs defaults,_netdev 0 2
Опция _netdev сигнализирует systemd, что устройство зависит от сети или сетевого хранилища и должно монтироваться только после того, как сетевые сервисы запущены. Без этой опции на серверах с iSCSI загрузка может подвиснуть, если MPIO не успел инициализироваться к моменту монтирования корня.
Правильно настроенный MPIO - это не просто техническое требование enterprise-окружений. Это философия отношения к отказоустойчивости: хранилище обязано переживать потерю любого одного компонента пути без видимых последствий для приложений. Два кабеля, два коммутатора, два контроллера - каждый из них может выйти из строя в любой момент, и система продолжит работу так, словно ничего не произошло. Это и есть цель всей этой конфигурации.