十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CentOS 7多路径存储配置与性能调优实战指南

CentOS 7多路径存储配置与性能调优实战指南 1. 项目背景与核心需求拆解1.1 为什么单路径存储会成为生产环境的隐患很多运维同行第一次接触多路径存储往往是在一次故障之后。服务器上挂载了一块来自磁盘阵列的LUN系统识别为/dev/sdb业务跑得好好的某天机房网络抖动或者HBA卡固件升级重启之后发现设备名变成了/dev/sdc挂载脚本直接报错数据库起不来。更麻烦的是有些场景下同一条链路被操作系统识别成两个甚至四个块设备应用层看到的是多块盘实际上指向的是同一份数据一旦同时写入文件系统直接损坏。这个问题的根源在于服务器到存储之间通常存在多条物理链路。以典型的双控存储为例每台服务器配两块HBA卡分别接到两台光纤交换机存储的两个控制器各出一个端口这样服务器到同一块LUN之间就有 2×24 条可达路径。操作系统默认的块设备层并不理解这些路径其实通向同一个后端卷它只会老老实实把每条路径都枚举成一个SCSI设备。于是就有了上面说的设备名漂移和重复识别问题。Multipath多路径要解决的就是这件事把这些物理上分离、逻辑上同源的路径聚合成一个虚拟块设备向上层屏蔽底层链路的复杂性同时提供故障切换和负载均衡能力。CentOS 7 自带的device-mapper-multipath就是干这个的它工作在块设备层位于 SCSI 层和文件系统层之间对上层应用完全透明。1.2 这套方案适合谁、解决什么问题这篇文章面向的是手里有真实存储环境、需要在 CentOS 7 上把多路径跑起来并且跑好的运维工程师和系统管理员。如果你只是用虚拟机做实验也能跟着走一遍流程但很多参数调优的体感只有在真实负载下才明显。具体来说Multipath 在 CentOS 7 上要达成的目标有这么几个设备聚合把多条路径合并成/dev/mapper/mpathX这样的单一设备业务只认这一个名字重启、换卡、换交换机端口都不影响。故障切换某条链路断了I/O 自动切到其他可用路径业务基本无感知。负载均衡多条健康路径同时分担 I/O提升吞吐。路径管理提供命令行工具查看每条路径的状态方便排障。需要提前说清楚的是Multipath 本身不产生冗余冗余是存储和网络层面已经做好的Multipath 只是把这份冗余用起来。如果后端只有一条物理链路配了 Multipath 也没有意义。1.3 核心组件与工作模型理解 Multipath 的工作模型关键要分清三个层次层次名称作用物理层路径path每条 HBA 到存储端口的链路对应一个/dev/sdX聚合层路径组path group优先级相同的路径集合同一时刻只有一个组处于 active设备层多路径设备mpath对上层暴露的虚拟块设备如/dev/mapper/mpatha内核里的dm-multipath模块负责实际的 I/O 转发用户态的multipathd守护进程负责监控路径状态、执行切换策略、响应配置变更。两者通过 device-mapper 的 ioctl 接口通信。multipath命令是一次性的配置和查询工具multipathd是常驻服务实际生产里真正干活的是后者。提示很多人配完 Multipath 发现不生效八成是multipathd没起来或者配置文件语法有问题导致守护进程加载了默认配置。排查时先看systemctl status multipathd。2. 环境准备与安装配置全流程2.1 安装前的环境确认清单动手之前先把下面这些信息确认清楚能省掉后面大量的返工存储侧确认 LUN 已经映射给这台服务器并且存储管理员告诉你这块 LUN 的 WWIDWorld Wide Identifier。这个 ID 是 Multipath 聚合路径的唯一依据必须准确。链路侧lspci | grep -i fibre确认 HBA 卡被识别cat /sys/class/fc_host/host*/port_name查看每块 HBA 的 WWPN。系统侧uname -r看内核版本CentOS 7 建议 3.10.0-957 以上rpm -qa | grep device-mapper确认基础包在。网络侧如果是 iSCSI确认iscsiadm能发现目标如果是 FC确认fdisk -l能看到多块同名容量的盘。一个很实用的判断方法如果lsblk或者fdisk -l里出现了多块容量完全一致、型号也一致的盘而你又只申请了一块 LUN那基本可以确定是多路径没配导致的重复识别。2.2 安装 device-mapper-multipathCentOS 7 的安装很直接但有几个细节要注意# 确认仓库可用 yum repolist # 安装核心包和工具 yum install -y device-mapper-multipath device-mapper-multipath-libs # 确认版本 rpm -qa | grep multipath如果生产环境不能连外网需要提前把 rpm 包和依赖下载好。依赖关系其实不复杂主要是device-mapper、device-mapper-libs、kmod这几类。离线安装时用yum install --downloadonly --downloaddir/tmp/mp在一台能上网的同版本机器上把包拉全再拷到目标机yum localinstall *.rpm。安装完成后不要急着启动先把配置文件准备好。CentOS 7 默认会生成一个/etc/multipath.conf但内容基本是注释实际生效的是内置默认值。我习惯的做法是保留一份原始备份然后自己写一份精简的配置。2.3 生成并理解默认配置# 备份原始配置 cp /etc/multipath.conf /etc/multipath.conf.bak # 生成一份带默认值的配置参考 mpathconf --enable --with_multipathd ympathconf这个工具会帮你把服务设成开机启动并生成基础配置。执行完之后/etc/multipath.conf里会有defaults、blacklist、multipaths等段落。这里有个坑mpathconf生成的配置里user_friendly_names默认是yes意味着设备名会是mpatha、mpathb这种而不是基于 WWID 的3600...长串。两种方式各有取舍后面会专门讲。2.4 启动服务并验证基础状态# 启动并设置开机自启 systemctl enable multipathd systemctl start multipathd # 查看服务状态 systemctl status multipathd # 查看当前多路径设备 multipath -ll如果multipath -ll输出为空说明还没有设备被聚合。这时候先别怀疑配置先确认底层是不是真的有多条路径。用multipath -v3可以看到详细的探测过程它会告诉你哪些设备被扫描到、哪些被黑名单过滤、哪些因为 WWID 不合法被跳过。这个-v3的输出信息量很大是排障的第一手资料。3. multipath.conf 核心参数深度解析3.1 defaults 段全局行为的基调defaults段决定了所有多路径设备的默认行为是配置里最需要花心思的部分。下面这份是我在多个生产环境里验证过的配置逐项说明为什么这么设defaults { user_friendly_names no polling_interval 10 path_selector service-time 0 path_grouping_policy multibus failback immediate no_path_retry 5 rr_min_io_rq 1 max_sectors_kb 1024 dev_loss_tmo 60 fast_io_fail_tmo 5 find_multipaths yes }user_friendly_names设成no是我强烈建议的。设成yes时设备名mpatha是绑定到/etc/multipath/bindings文件的这个文件一旦丢失或者换机器名字就全乱了。而用 WWID 命名设备名是3600508b400105e210000900000490000这种虽然长但它跟存储卷一一对应任何机器上看到这个名字都知道是哪块盘。脚本里引用也更安全。polling_interval是multipathd检查路径状态的间隔单位秒。默认 5 秒我一般设 10 秒。设太小会增加系统开销设太大故障发现不及时。10 秒是个平衡点对大多数业务够用。path_selector决定多条健康路径之间怎么分发 I/O。service-time 0是基于每条路径的预估服务时间动态选择比老式的round-robin 0更智能。round-robin是无脑轮询不管路径快慢在链路性能不一致时会导致慢路径拖后腿。service-time会把 I/O 优先发给当前响应最快的路径实测在混合链路环境下吞吐提升明显。path_grouping_policy设成multibus表示所有路径放在一个组里全部参与负载均衡。另一种常见值是failover同一时刻只有一条路径 active其余待命。multibus适合存储两个控制器都能同时服务的场景比如 ALUA 的 active/active 模式failover适合 active/passive 存储。选错了不会报错但性能会差一大截。failback控制路径恢复后是否切回。immediate表示路径一恢复就立刻切回适合主备链路性能差异大的场景。如果两条链路对等设成manual或一个较大的延迟值如failback 30可以避免频繁切换带来的抖动。no_path_retry是路径全断后 I/O 的行为。设成数字表示重试多少次后失败设成queue表示一直排队等待路径恢复。生产环境里我倾向设一个具体数字比如 5避免 I/O 无限挂起导致应用假死。但如果是数据库这种对 I/O 中断极度敏感的场景queue配合合理的dev_loss_tmo更稳妥。max_sectors_kb限制单次 I/O 的最大扇区数。默认值在不同内核版本上不一致显式设成 1024 可以保证行为一致。设太大在某些存储上会触发超时设太小又增加 I/O 次数。1024 是个保守稳妥的值。dev_loss_tmo和fast_io_fail_tmo是配合使用的。fast_io_fail_tmo设成 5 秒意味着链路出问题后 5 秒内快速失败把 I/O 切到其他路径dev_loss_tmo设成 60 秒是设备彻底从系统移除前的等待时间。这两个值要保证fast_io_fail_tmo dev_loss_tmo否则快速失败没意义。3.2 blacklist 段把不该管的设备排除掉黑名单非常重要配不好会把本地盘也卷进多路径导致系统盘无法启动。CentOS 7 上至少要排除本地 SATA/SAS 盘和虚拟设备blacklist { devnode ^sd[a-z]$ devnode ^hd[a-z] devnode ^vd[a-z] devnode ^cciss!c[0-9]d[0-9]* wwid 3600508b400105e210000900000490000 }devnode ^sd[a-z]$这条会把所有单字母的 sd 设备排除但多路径设备本身是/dev/dm-X不受影响。注意这个正则只匹配sda到sdz如果服务器本地盘超过 26 块需要调整正则。更稳妥的做法是用wwid精确排除但前提是你知道本地盘的 WWID。blacklist_exceptions段可以给黑名单开例外比如某些设备虽然匹配了 devnode 规则但你确实想让它走多路径blacklist_exceptions { wwid 3600d0230000000000e0d0a0000d3a1b2 }3.3 multipaths 段针对特定 LUN 的精细控制全局配置管的是默认行为但不同存储、不同业务对多路径的要求可能不一样。multipaths段允许你针对单个 WWID 做覆盖multipaths { multipath { wwid 3600d0230000000000e0d0a0000d3a1b2 alias data_lun01 path_grouping_policy multibus path_selector service-time 0 failback immediate no_path_retry 10 } multipath { wwid 3600d0230000000000e0d0a0000d3a1b3 alias log_lun01 path_grouping_policy failover failback 30 } }alias是给设备起个人性化名字比mpatha更可控比 WWID 更好记。设了 alias 之后设备会出现在/dev/mapper/data_lun01。注意 alias 不能和已有设备名冲突也不能包含斜杠。这里有个经验数据库数据盘和日志盘对 I/O 的要求不同数据盘随机读写多适合service-time选择器日志盘顺序写多round-robin反而可能更稳定。分 LUN 配置能把这些差异照顾到。3.4 devices 段存储厂商特定的参数不同存储对 SCSI 命令的响应行为不一样devices段可以针对厂商和产品型号设置参数devices { device { vendor NETAPP product LUN path_grouping_policy group_by_prio prio alua path_checker tur failback immediate no_path_retry 5 } device { vendor HITACHI product DF.* path_grouping_policy multibus path_checker readsector0 prio alua } }path_checker决定用什么方式检测路径是否健康。turTest Unit Ready是最通用的发一个不产生实际 I/O 的命令探测readsector0是读第一个扇区对某些老存储更可靠但会产生实际读操作。选错了可能导致路径误判比如某些存储对 TUR 响应慢会被误认为路径故障。prio是路径优先级算法。alua是 SCSI 标准里的非对称逻辑单元访问存储会告诉主机哪些路径是优化的、哪些是非优化的。用alua配合group_by_prio策略可以让 I/O 优先走优化路径这是现代存储的最佳实践。4. 实操验证与性能调优4.1 配置生效与设备识别验证改完配置后标准操作流程是# 重新加载配置 systemctl reload multipathd # 或者完全重启 systemctl restart multipathd # 查看聚合结果 multipath -llmultipath -ll的输出需要仔细读。一个健康的多路径设备长这样data_lun01 (3600d0230000000000e0d0a0000d3a1b2) dm-3 NETAPP,LUN size500G features1 queue_if_no_path hwhandler0 wprw -- policyservice-time 0 prio50 statusactive |- 2:0:0:1 sdb 8:16 active ready running |- 3:0:0:1 sdc 8:32 active ready running |- 2:0:1:1 sdd 8:48 active ready running - 3:0:1:1 sde 8:64 active ready running关键信息dm-3是内核设备号size500G是容量policy是选择器prio50是优先级四条路径都是active ready running。如果某条路径显示failed faulty说明那条链路有问题需要查 HBA、光纤、交换机端口。4.2 故障切换实测配置完不测故障切换等于没配。测试方法很简单但要在业务低峰期做# 找到一条路径对应的 HBA 端口 ls -l /sys/block/sdb/device/scsi_device/ # 模拟链路故障以 2:0:0:1 为例 echo 1 /sys/block/sdb/device/delete执行后立刻multipath -ll观察应该看到sdb消失其余三条路径仍然active设备dm-3依然可用。同时开一个dd或者fio在/dev/mapper/data_lun01上跑I/O 不应该中断。恢复测试用# 重新扫描 SCSI 总线 echo - - - /sys/class/scsi_host/host2/scan路径回来后根据failback设置决定是否自动切回。immediate会立刻切回manual需要手动执行multipathd reconfigure或者multipath -r。注意echo 1 /sys/block/sdb/device/delete这个操作在有些内核版本上会直接移除设备有些只是标记。测试前确认业务能承受最好在测试环境先演练一遍。4.3 性能调优的关键参数多路径的性能调优核心是让 I/O 尽可能均匀且高效地分布在健康路径上。除了前面说的path_selector还有几个参数值得调rr_min_io_rq是轮询模式下每条路径连续处理的 I/O 数。设成 1 表示每个 I/O 都换路径设成 1000 表示一条路径处理 1000 个 I/O 再换。设太小会导致路径切换开销大设太大又失去负载均衡意义。用service-time选择器时这个参数基本不起作用但用round-robin时很关键。一般设 1 到 100 之间SSD 存储可以设小一点机械盘设大一点。queue_if_no_path特性配合no_path_retry使用。当所有路径都断时I/O 是排队还是直接失败。可以在features里显式指定features 1 queue_if_no_path数字 1 表示启用。这个特性在存储短暂抖动时能保住业务但如果存储长时间不可用I/O 会一直挂起需要配合应用层的超时机制。max_sectors_kb的调整需要结合存储的条带大小。如果存储条带是 256KB把max_sectors_kb设成 256 的整数倍能让 I/O 对齐减少读改写。这个值可以通过cat /sys/block/dm-3/queue/max_sectors_kb查看当前生效值。4.4 用 fio 做基准测试调优前后要有数据对比fio是最常用的工具# 顺序读测试 fio --nameseqread --filename/dev/mapper/data_lun01 \ --direct1 --rwread --bs1M --size10G \ --numjobs4 --iodepth32 --runtime60 --group_reporting # 随机写测试 fio --namerandwrite --filename/dev/mapper/data_lun01 \ --direct1 --rwrandwrite --bs4k --size10G \ --numjobs4 --iodepth64 --runtime60 --group_reporting对比单路径和多路径的 IOPS、带宽、延迟。正常情况下四条路径的聚合带宽应该接近单路径的四倍受限于存储控制器和交换机背板。如果提升不明显检查是不是path_grouping_policy设成了failover或者存储侧只允许一条路径 active。提示fio测试会破坏设备上的数据务必在空 LUN 或者测试环境做。生产环境可以用--readonly参数只做读测试。5. 常见问题排查与避坑经验5.1 设备重复识别与黑名单失效最常见的现象是multipath -ll里同一个 WWID 出现多次或者本地盘被错误聚合。排查步骤multipath -v3 21 | grep -i blacklist看黑名单规则有没有匹配上。检查blacklist里的正则是不是写错了比如^sd[a-z]$匹配不了sdaa。确认find_multipaths的值。设成yes时只有满足特定条件的设备才会被聚合能减少误判设成no时所有非黑名单设备都会被尝试聚合。如果本地盘已经被聚合了千万不要直接删/dev/mapper下的设备可能导致系统盘不可用。正确做法是先把该 WWID 加入黑名单然后multipathd reconfigure再multipath -f刷新。5.2 路径状态异常排查表现象可能原因排查命令处理方式路径显示 failed faulty光纤断、HBA 故障、交换机端口 downcat /sys/class/fc_host/host*/port_state检查物理链路换端口路径显示 active ghost存储 ALUA 非优化路径multipathd show paths format %w %i %p %t正常现象I/O 会优先走优化路径路径频繁 up/down链路抖动、SFP 光模块老化dmesggrep -i fc|scsi所有路径消失存储控制器重启、交换机故障multipath -ll无输出检查存储和交换机状态设备容量不对LUN 映射错误、WWID 冲突multipath -ll对比存储侧重新映射 LUN5.3 服务启动顺序与依赖问题CentOS 7 用 systemd 管理服务multipathd的启动时机很关键。如果它启动太晚可能在根文件系统挂载之后才运行导致根分区无法使用多路径。检查/usr/lib/systemd/system/multipathd.service里的Before和After设置确保它在local-fs-pre.target之前启动。另一个坑是multipathd和iscsid的依赖关系。iSCSI 场景下iscsid必须先启动并发现目标multipathd才能看到设备。如果顺序反了multipathd启动时没有设备可聚合后面也不会自动补上。解决办法是在multipathd.service里加Afteriscsid.service或者手动systemctl restart multipathd。5.4 配置文件语法错误的隐蔽性multipath.conf的语法检查不算严格有些错误不会导致服务启动失败但配置不生效。比如段落名拼错default写成defaults才对。参数值没加引号path_selector service-time 0会被解析成两个 token必须写成path_selector service-time 0。大括号不匹配少一个}会导致后面所有配置被忽略。改完配置后用multipathd -kshow config可以查看实际生效的配置对比你写的文件能发现哪些没被加载。这个命令比重启服务再猜要高效得多。5.5 udev 规则与设备权限多路径设备默认属主是root:disk权限brw-rw----。如果业务以非 root 用户运行需要调整 udev 规则# /etc/udev/rules.d/99-multipath-permissions.rules KERNELdm-*, SUBSYSTEMblock, PROGRAM/sbin/multipath -c /dev/$name, RESULT*, OWNERoracle, GROUPoinstall, MODE0660改完udevadm control --reload-rules udevadm trigger生效。注意规则里的PROGRAM调用multipath -c判断是不是多路径设备避免影响其他 dm 设备。6. 生产环境落地建议6.1 配置版本化管理multipath.conf是核心配置文件必须纳入版本管理。我习惯在文件头部加注释记录变更# multipath.conf # 2024-01-15 初始配置适配 NETAPP E系列 # 2024-03-02 调整 no_path_retry 从 queue 改为 5解决存储维护时 I/O 挂起 # 2024-06-10 新增 log_lun01 的 failover 配置配合 Git 或者内部配置管理平台每次变更都有记录出问题能快速回滚。6.2 监控与告警multipathd本身不提供监控接口但可以通过multipathd show paths的输出做监控。关键指标路径状态任何一条路径非active ready就告警。路径数量少于预期数量告警。设备状态multipath -ll里设备不是rw状态告警。可以用 Zabbix 或者 Prometheus 的自定义脚本采集也可以写个简单的 shell 脚本定时检查#!/bin/bash # check_multipath.sh failed$(multipathd show paths | grep -v active ready | grep -c ^) if [ $failed -gt 0 ]; then echo WARNING: $failed paths not ready multipathd show paths | grep -v active ready exit 1 fi exit 06.3 变更窗口与回滚预案多路径配置变更涉及存储链路必须在变更窗口做。回滚预案要提前准备好备份当前multipath.conf。记录当前multipath -ll输出。如果变更后业务异常立即恢复配置文件并systemctl restart multipathd。如果设备名变了导致挂载失败用 WWID 重新挂载。最稳妥的做法是在测试环境先验证一遍完整流程包括故障切换和恢复。6.4 与集群软件的配合如果服务器上跑的是 Oracle RAC、Pacemaker 这类集群软件多路径设备的命名必须稳定。用 WWID 命名或者固定的 alias 是关键。集群软件通常有自己的存储检查机制要确保它检查的是/dev/mapper/下的设备而不是底层的/dev/sdX。另外集群软件可能会自己管理设备挂载和卸载要确认它的操作不会和多路径的failback冲突。比如集群在路径切换时执行了multipath -f可能导致设备被移除影响其他节点。6.5 内核参数配合调优多路径的性能还受一些内核参数影响# /etc/sysctl.d/99-multipath.conf # SCSI 层命令超时默认 30 秒可适当调大 kernel.sysrq 0 # 提高 SCSI 设备队列深度 # 通过 /sys/block/dm-X/queue/nr_requests 调整nr_requests是块设备层的请求队列深度默认 128。高并发场景可以调到 256 或 512但要注意内存占用。调整方法echo 256 /sys/block/dm-3/queue/nr_requests这个值重启后会恢复需要写进 udev 规则或者 systemd 服务里持久化。6.6 存储侧配合的注意事项多路径不是主机单方面的事存储侧的配置同样关键ALUA 配置确认存储的 ALUA 状态是 active/active 还是 active/passive主机侧的path_grouping_policy要匹配。LUN masking确认 LUN 只映射给需要的服务器避免多台主机同时看到同一 LUN 导致数据损坏。控制器固件保持存储控制器固件和 HBA 固件版本兼容厂商兼容性列表要查。交换机 zoningFC 交换机的 zoning 配置要确保每条路径独立避免单点故障。我在实际项目中遇到过存储侧 ALUA 配置错误导致主机侧所有路径都被标记为优化路径group_by_prio策略失效I/O 全部涌向一个控制器。后来在存储侧修正 ALUA 状态主机侧multipath -ll的prio值才正常区分。这个案例说明多路径调优必须主机和存储两边一起看单看一边容易误判。最后分享一个我常用的快速检查脚本登录服务器后跑一遍基本能判断多路径状态是否健康#!/bin/bash echo multipathd 服务状态 systemctl is-active multipathd echo 多路径设备列表 multipath -ll echo 路径状态统计 multipathd show paths | awk {print $NF} | sort | uniq -c echo 黑名单检查 multipathd show blacklist echo 最近内核 SCSI 错误 dmesg | grep -i scsi\|fc | tail -20这个脚本输出信息量足够日常巡检和故障初判都能用。多路径这东西配好之后平时不用管但一旦出问题就是存储链路级别的事故所以前期的配置严谨度和监控覆盖度直接决定了后面是省心还是救火。
返回列表