多路径基本原理

Linux下多路径软件主要有三个部分组成:

  1. 守护进程multipathd,状态可通过systemctl status multipathd.service命令进行查看;
  2. 用户工具multipath,可用于刷新当前系统中的多路径设备等;
  3. 多路径的DeviceMapper驱动dm-mpath.ko以及路径选择器插件dm-queue-length.ko和dm-service-time.ko,源码在内核中。

多路径内部运行的基本过程:

  1. 内核加载多路径驱动模块dm-mpath.ko、dm-queue-length.ko、dm-service-time.ko,可使用modprobe dm-multipath命令进行加载,运行时可通过lsmod | grep dm命令确认是否被加载成功。
  2. 多路径服务启动multipathd进程,读取/etc/multipath.conf配置文件,进行初始化。
  3. 扫描/sys目录下的块设备,并根据配置文件,排除黑名单中设备,建立块设备列表。
  4. 根据配置文件,为WWID相同的块设备建立优先级组,形成设备树。
  5. 以设备树为参数使用libdevicemapper库调用内核接口,创建多路径设备,此时会用到多路径的驱动。
  6. 创建基于netlink的uevent套接字,监听内核中块设备增减的消息,并以此更新设备树和多路径设备状态。
  7. 另外创建独立线程根据配置文件定时检测(比如使用DirectIO方式定时读取块设备第一扇区)块设备是否正常,如果不正常则通知驱动,设置相应的路径为无效,驱动根据之前配置的参数切换到可用的路径(切换方法根据配置来确定)。
  8. 执行multipath –F命令可以让multipathd清空之间的设备树,并删除多路径设备。
  9. 执行multipath –v3命令可以让multipathd重新扫描系统中的块设备,并建立多路径设备。

其中路径切换的方法跟存储厂商的硬件相关,如果默认配置无法使用则需要参考存储设备用户手册。其中的路径检测方法默认为使用DirectIO方式定时读取块设备的第一个扇区是否正常,这是通用处理方法,不排除个别厂商有更好的处理方法,出问题时同样需要参考存储设备用户手册。路径状态发生变化的情况有且仅有以下三种:

  1. 用户程序读写多路径设备时出错,多路径驱动会使该路径无效,同时通知multipathd进程;
  2. multipathd进程定时检测,发现某条路径无法正常访问,会通知驱动设置此条路径无效;
  3. 块设备驱动的增加、删减或故障会通过uevent进行消息广播,multipathd监听线程进程接收到后,会更新自己的设备树,并通知驱动进行路径增加、删除或设置为无效。

因此在多路径出问题时,首先检查multipathd进程是否正常运行、配置文件是否正确设置、是否使用multipath –v3命令刷新设备树、使用dd命令确认各条路径是否正常。

配置文件的组成

Multipath的配置文件/etc/multipath.conf由节(section)、属性(attribute)和值(value)组成,其结构如下:

<section> {
	<attribute> <value>
	...
	<subsection> {
	<attribute> <value>
	...
	}
}

允许使用的节的关键字有:

defaults                  默认的全局属性设置。
blacklist                 黑名单,这里的设备将会被忽略。
blacklist_exceptions	  免除黑名单,加入黑名单内,但包含在这里的设备不会被忽略。
multipaths                路径特定配置。
devices                   存储设备特定配置。

默认配置文件的位置:/usr/share/doc/device-mapper-multipath-0.X.Y/multipath.conf(把0.X.Y换成实际的版本号),可以复制到/etc目录下修改后使用。

defaults配置

polling_interval         路径检查的时间间隔,以秒为单位。
max_polling_interval     最大路径检查的时间间隔,默认为polling_interval的4倍。
multipath_dir            多路径共享库路径,系统相关,默认为/lib/multipath或者/lib64/multipath。
find_multipaths          默认值是no,会为黑名单以外的所有设备创建多路径设备。如果设置为yes,则在三种情况下会创建多路径设备:只要有两个不在黑名单的路径的wwid相同;用户手动强制创建;一个路径的wwid与之前已经创建的多路径设备相同。
verbosity                额外信息输出等级,最低位0,最高位6,默认为2。
path_selector            路径选择算法:
round-robin 0            在多个路径中不断循环;
queue-length 0           选择当前正在处理IO个数最少的路径;
service-time 0           选择正在处理的IO字节数与相对吞吐量比值最小的路径。
path_grouping_policy     路径分组方法:
failover                 一条路径一个组(默认值);
multibus                 所有路径在一个组;
group_by_serial          根据序列号分组;
group_by_prio            根据优先级分组;
group_by_node_name       根据名称分组。
uid_attribute            使用哪个udev的属性唯一标识一个设备,默认值为ID_SERIAL。
prio                     路径优先级获取方法:
const                    返回1(默认值);
emc                      为emc阵列生成优先级;
alua                     基于SCSI-3 ALUA配置生成优先级;
ontap                    为NetAPP阵列生成优先级;
rdac                     为LSI/Engenio/NetApp E-Series RDAC控制器生成优先级;
hp_sw                    根据Compaq/HP控制器active/standby模式生成优先级;
hds                      为日立HDS模块化存储阵列生成优先级;
random                   随机优先级,在1到10之间;
weightedpath             根据正则表达式和prio_args参数值生成优先级。
prio_args                优先级计算函数的参数。
features                 指定要使用的DeviceMapper特性:
queue_if_no_path         如果没有一个可用路径时,把请求加入队列;
no_partitions            禁止使用kpartx生成分区。
path_checker             路径检查方法:
readsector0              读取设备的第一扇区来决定路径状态,已经废弃,请使用directio来替代;
tur                      执行TEST UNIT READY命令来决定路径状态;
emc_clariion             执行EMC Clariion specific EVPD page 0xC0 来决定路径的状态;
hp_sw                    检查惠普Active/Standby存储阵列;
rdac                     检查LSI/Engenio/NetApp E-Series RDAC存储控制器状态;
direction                使用DirectIO读取设备第一扇区。
failback                 如何恢复路径:
Immediate                立即恢复到包含活动路径的高优先级组;
manual                   手动恢复(默认值);
followover               只有路径组的第一条路径可用时恢复;
values                   > 0 延迟恢复。
rr_min_io                切换到下一条路径前进行IO的次数,默认值为1000。
rr_min_io_rq             切换到下一条路径前进行IO的最小次数,默认值为1。
no_path_retry            没有活动路径时,关闭队列前重试的次数,fail则直接返回错误,queue则全部加入队列,默认值为0。
user_friendly_names      如果是置位yes,则使用/etc/multipath/bindings中的设置命名,如果市值为no,则使用wwid命名(可以被multipaths中的设置覆盖),默认值为no。
max_fds                  multipathd和multipath可打开的文件描述符最大个数。
checker_timeout          路径检查超时时间,单位我秒,默认值从/sys/block/sd<x>/device/timeout获取。
fast_io_fail_tmo         SCSI IO错误超时,应该比dev_loss_tmo小,设置off则禁用超时。
dev_loss_tmo             SCSI 设备移除超时,Linux下的默认值为300.
queue_without_daemon     如果设置为no,当multipathd没有启动时,会停止所有设备的IO加入队列。
bindings_file            当设置user_friendly_names时,名称绑定文件的路径,默认值为/etc/multipath/bindings。
wwids_file               wwids跟踪文件路径,默认为/etc/multipath/wwids。
log_checker_err          路径检查出错时的日志记录方式,默认为always。
reservation_key          指定mpathpersist命令的key。
retain_attached_hw_handler    是否继续使用hardware_handler,默认为no。
detect_prio              如果设置为yes,则首先尝试使用alua来检测,默认为no。
hw_str_match             如果设置为yes,则优先使用字符串匹配名称、厂商等信息,默认为no。
force_sync               如果设置为yes,则强制使用同步模式检查路径,默认为no。
deferred_remove          如果设为yes,则延迟删除没有路径的设备,默认为no。
config_dir               配置文件目录,如果不为“”,则按照字母排序搜索目录中的*.conf文件,和使用/etc/multipath.conf一样读取他们,默认为/etc/multipath/conf.d。
delay_watch_checks       如果大于0,则只有连续delay_watch_checks检查路径是有效时才认为有效,默认为no。
delay_wait_checks        如果大于0,在路径经过delay_watch_check此检查认为有效后,延迟delay_wait_checks次检查后才正式重新启用,默认为no。
missing_uev_msg_delay   当一个新的设备被创建后,在延迟missing_uev_msg_delay秒后开始接受udev信息,默认值是30。

blacklist配置

blacklist黑名单内的设备将会被多路径忽略,有三种格式:

  1. wwid 后面跟设备的WWID;
  2. devnode 后面跟设备名称的正则表达式;
  3. device 设备描述,这是一个子节(Subsection),其中需要包含vendor、product,详细请参考devices节的描述。

blacklist_exceptions语法与blacklist相同,用于取消blacklist的忽略。

multipaths配置

multipaths用于单独配置每条路径,每个路径单独使用multipath子节,可以包含如下属性:

wwid                   (必选)路径WWID,可以通过命令/lib/udev/scsi_id -g -u /dev/sdX获取。
alias                  设备别名
path_grouping_policy   下面的与defaults节说明相同。
path_selector	
prio	
prio_args	
failback	
rr_weight	
flush_on_last_del	
no_path_retry	
rr_min_io	
rr_min_io_q	
features	
reservation_key	
deferred_remove	
delay_watch_checks	
delay_wait_checks

devices配置

devices节中的每个设备使用device子节来描述,主要字段如下:

vendor                  (必选)生产商。
product                 (必选)产品型号。
revision                版本号。
product_blacklist       产品型号黑名单。
alias_prefix            设备名称前缀,默认为mapth。
hardware_handler        硬件相关操作的型号,主要有:
                               1 emc     Hardware handler for EMC storage arrays.
                               1 rdac    Hardware handler for LSI/Engenio/NetApp E-Series RDAC storage controller.
                               1 hp_sw   Hardware handler for Compaq/HP storage arrays in active/standby mode.
                               1 alua    Hardware handler for SCSI-3 ALUA compatible arrays.
path_grouping_policy	下面的与defaults节说明相同。
uid_attribute	
path_selector	
path_checker	
prio	
prio_args	
features	
failback	
rr_weight	
no_path_retry	
rr_min_io	
rr_min_io_rq	
fast_io_fail_tmo	
dev_loss_tmo	
flush_on_last_del	
retain_attached_hw_handler	
detect_prio	
deferred_remove	
delay_watch_checks	
delay_wait_checks

配置基本步骤

  1. 确定存储的部署方式,比如存储个数,存储类型,路径个数及其类型和关系;
  2. 仔细阅读存储厂商关于多路径配置的说明,并根据其要求和建议配置devices一节的信息;
  3. 根据用户需求和使用场景配置multipaths一节的信息;
  4. 在blacklist一节中屏蔽掉不使用多路径的设备;
  5. 重启度路径服务(systemctl restart multipathd.service,或者重启主机),并清空(multipath -F),重建(multipath –v3)设备列表,最后查看列表(multipath -ll),看路径是否正常。

故障排除基本步骤

  1. 确定多路径服务是否正常运行(systemctl status multipathd.service),重启服务或主机;
  2. 重建多路径设备列表,使用multipath –F和multipath –v3;
  3. 确认存储设备是否配置正常,多条路径是否能正常访问,并使用dd命令进行读取测试(dd if=/dev/sdX of=/dev/null bs=512 count=1);
  4. 仔细检查配置中与路径状态检测和路径切换相关的配置与存储设备说明书中的是否一致;

故障实例

问题:使用两个完全相同的光纤存储设备,每个设备有两个控制器,每个控制器。其中一个作为主存,另外一个作为备存,主存正常时备存处于只读状态。备存实时与主存同步,且都分配有6个LUN,每个LUN都使用LVM进行管理,结果有的LVM卷会处于只读状态,无法正常使用。

分析:对于主机来说,看到了是12个LUN,每个LUN有4条路径,SCSI会产生48个块设备(/dev/sdX),因此多路径会产生12个块设备(/dev/mapper/mpathX),多路径通过SCSI设备的WWID识别4个sdX为同一个LUN。对于LVM,在每个PV,VG或者LV创建时,都会制定一个唯一的UUID,并将其写入块设备的元数据扇区中。当LVM扫描全部块设备时,读取这48+12个块设备的源数据扇区,会有5个块设备有相同的UUID,LVM无法区分不同的PV、VG和LV,因此会导致LVM映射错误的卷。

解决办法:使用LVM配置文件中的global_filter参数,或者多路径配置中的blacklist节过滤掉多余的块设备,只留下6个正在使用的块设备,最后使用pvscan --cache刷新LVM缓存即可(刷新前需要关闭占用这些LVM卷的应用,否则可能不会立即生效)。