多路徑基本原理
Linux下多路徑軟件主要有三個部分組成:
-
守護進程multipathd,狀態可通過systemctl status multipathd.service命令進行查看;
-
用戶工具multipath,可用於刷新當前系統中的多路徑設備等;
-
多路徑的DeviceMapper驅動dm-mpath.ko以及路徑選擇器插件dm-queue-length.ko和dm-service-time.ko,源碼在內核中。
多路徑內部運行的基本過程:
-
內核加載多路徑驅動模塊dm-mpath.ko、dm-queue-length.ko、dm-service-time.ko,可使用modprobe dm-multipath命令進行加載,運行時可通過lsmod | grep dm命令確認是否被加載成功。
-
多路徑服務啓動multipathd進程,讀取/etc/multipath.conf配置文件,進行初始化。
-
掃描/sys目錄下的塊設備,並根據配置文件,排除黑名單中設備,建立塊設備列表。
-
根據配置文件,爲WWID相同的塊設備建立優先級組,形成設備樹。
-
以設備樹爲參數使用libdevicemapper庫調用內核接口,創建多路徑設備,此時會用到多路徑的驅動。
-
創建基於netlink的uevent套接字,監聽內核中塊設備增減的消息,並以此更新設備樹和多路徑設備狀態。
-
另外創建獨立線程根據配置文件定時檢測(比如使用DirectIO方式定時讀取塊設備第一扇區)塊設備是否正常,如果不正常則通知驅動,設置相應的路徑爲無效,驅動根據之前配置的參數切換到可用的路徑(切換方法根據配置來確定)。
-
執行multipath –F命令可以讓multipathd清空之間的設備樹,並刪除多路徑設備。
-
執行multipath –v3命令可以讓multipathd重新掃描系統中的塊設備,並建立多路徑設備。
其中路徑切換的方法跟存儲廠商的硬件相關,如果默認配置無法使用則需要參考存儲設備用戶手冊。其中的路徑檢測方法默認爲使用DirectIO方式定時讀取塊設備的第一個扇區是否正常,這是通用處理方法,不排除個別廠商有更好的處理方法,出問題時同樣需要參考存儲設備用戶手冊。路徑狀態發生變化的情況有且僅有以下三種:
-
用戶程序讀寫多路徑設備時出錯,多路徑驅動會使該路徑無效,同時通知multipathd進程;
-
multipathd進程定時檢測,發現某條路徑無法正常訪問,會通知驅動設置此條路徑無效;
-
塊設備驅動的增加、刪減或故障會通過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黑名單內的設備將會被多路徑忽略,有三種格式:
-
wwid 後面跟設備的WWID;
-
devnode 後面跟設備名稱的正則表達式;
-
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
配置基本步驟
-
確定存儲的部署方式,比如存儲個數,存儲類型,路徑個數及其類型和關係;
-
仔細閱讀存儲廠商關於多路徑配置的說明,並根據其要求和建議配置devices一節的信息;
-
根據用戶需求和使用場景配置multipaths一節的信息;
-
在blacklist一節中屏蔽掉不使用多路徑的設備;
-
重啓度路徑服務(systemctl restart multipathd.service,或者重啓主機),並清空(multipath -F),重建(multipath –v3)設備列表,最後查看列表(multipath -ll),看路徑是否正常。
故障排除基本步驟
-
確定多路徑服務是否正常運行(systemctl status multipathd.service),重啓服務或主機;
-
重建多路徑設備列表,使用multipath –F和multipath –v3;
-
確認存儲設備是否配置正常,多條路徑是否能正常訪問,並使用dd命令進行讀取測試(dd if=/dev/sdX of=/dev/null bs=512 count=1);
-
仔細檢查配置中與路徑狀態檢測和路徑切換相關的配置與存儲設備說明書中的是否一致;
故障實例
問題:使用兩個完全相同的光纖存儲設備,每個設備有兩個控制器,每個控制器。其中一個作爲主存,另外一個作爲備存,主存正常時備存處於只讀狀態。備存實時與主存同步,且都分配有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卷的應用,否則可能不會立即生效)。