Multipath多路徑冗餘全解
一、什麼是multipath
普通的電腦主機都是一個硬碟掛接到一個總線上,這裡是一對一的關係。而到了有光纖組成的SAN環境,由於主機和儲存通過了光纖交換機連線,這樣的話,就構成了多對多的關係。也就是說,主機到儲存可以有多條路徑可以選擇。主機到儲存之間的IO由多條路徑可以選擇。
既然,每個主機到所對應的儲存可以經過幾條不同的路徑,如果是同時使用的話,I/O流量如何分配?其中一條路徑壞掉了,如何處理?還有在作業系統的角度來看,每條路徑,作業系統會認為是一個實際存在的物理盤,但實際上只是通向同一個物理盤的不同路徑而已,這樣是在使用的時候,就給使用者帶來了困惑。多路徑軟體就是為了解決上面的問題應運而生的。多路徑的主要功能就是和儲存裝置一起配合實現如下功能:
1. 故障的切換和恢復
2. IO流量的負載均衡
3. 磁碟的虛擬化
二、為什麼使用multipath
由於多路徑軟體是需要和儲存在一起配合使用的,不同的廠商基於不同的作業系統,都提供了不同的版本。並且有的廠商,軟體和硬體也不是一起賣的,如果要使用多路徑軟體的話,可能還需要向廠商購買license才行。比如EMC公司基於linux下的多路徑軟體,就需要單獨的購買license。
其中,EMC提供的就是PowerPath,HDS提供的就是HDLM,更多的儲存廠商提供的軟體,可參考這裡。
當然,使用系統自帶的免費多路徑軟體包,同時也是一個比較通用的包,可以支援大多數儲存廠商的裝置,即使是一些不是出名的廠商,通過對配置檔案進行稍作修改,也是可以支援並執行的很好的。
※ 請與IBM的RDAC、Qlogic的failover驅動區分開,它們都僅提供了Failover的功能,不支援Load Balance方式。但multipath根據選擇的策略不同,可支援多種方式,如:Failover、Multipath等。
三、multipath的組成
我這裡以紅帽x86_64為例,雖然版本比較老,但下面的配置方式基本適用後面的所有版本。
# cat /etc/redflag-release
Red Flag DC Server release 5.0 (Trinity SP2)
# uname -a
Linux localhost.localdomain 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
# rpm -qa|grep device
device-mapper-event-1.02.32-1.el5
device-mapper-1.02.32-1.el5
device-mapper-multipath-0.4.7-30.el5
device-mapper-1.02.32-1.el5
可見,一套完整的multipath由下面幾部分組成:
1. device-mapper-multipath
提供multipathd和multipath等工具和multipath.conf等配置檔案。這些工具通過device mapper的ioctr的介面建立和配置multipath裝置(呼叫device-mapper的使用者空間庫。建立的多路徑裝置會在/dev/mapper中);
2. device-mapper
device-mapper包括兩大部分:核心部分和使用者部分。
核心部分由device-mapper核心(multipath.ko)和一些target driver(dm-multipath.ko)構成。dm-mod.ko是實現multipath的基礎,dm-multipath其實是dm的一個target驅動。核心完成裝置的對映,而target根據對映關係和自身特點具體處理從mappered device 下來的i/o。同時,在核心部分,提供了一個介面,使用者通過ioctr可和核心部分通訊,以指導核心驅動的行為,比如如何建立mappered device,這些device的屬性等。
使用者空間部分包括device-mapper這個包。其中包括dmsetup工具和一些幫助建立和配置mappered device的庫。這些庫主要抽象,封裝了與ioctr通訊的介面,以便方便建立和配置mappered device。device-mapper-multipath的程式中就需要呼叫這些庫;
3. scsi_id
其包含在udev程式包中,可以在multipath.conf中配置該程式來獲取scsi裝置的序號。通過序號,便可以判斷多個路徑對應了同一裝置。這個是多路徑實現的關鍵。scsi_id是通過sg驅動,向裝置傳送EVPD page80或page83 的inquery命令來查詢scsi裝置的標識。但一些裝置並不支援EVPD 的inquery命令,所以他們無法被用來生成multipath裝置。但可以改寫scsi_id,為不能提供scsi裝置標識的裝置虛擬一個識別符號,並輸出到標準輸出。
multipath程式在建立multipath裝置時,會呼叫scsi_id,從其標準輸出中獲得該裝置的scsi id。在改寫時,需要修改scsi_id程式的返回值為0。因為在multipath程式中,會檢查該直來確定scsi id是否已經成功得到。
四、配置multipath
原理看了一堆,實際配置還是比較簡單的。配置檔案只有一個:/etc/multipath.conf 。配置前,請用fdisk -l 確認已可正確識別盤櫃的所有LUN,HDS支援多鏈路負載均衡,因此每條鏈路都是正常的;而如果是類似EMC CX300這樣僅支援負載均衡的裝置,則冗餘的鏈路會出現I/O Error的錯誤。
multipath.conf的配置引數、預設值,可參考:
1、編輯黑名單
預設情況下,multipath會把所有裝置都加入到黑名單(devnode "*"),也就是禁止使用。所以,我們首先需要取消該設定,把配置檔案修改為類似下面的內容:
devnode_blacklist {
#devnode "*"
devnode "hda"
wwid 3600508e000000000dc7200032e08af0b
}
這裡禁止使用hda,也就是光碟機。另外,還限制使用本地的sda裝置,這個wwid,可通過下面的命令獲得:
# scsi_id -g -u -s /block/sda
3600508e000000000dc7200032e08af0b
2、編輯預設規則
不同的device-mapper-multipath或作業系統發行版,其預設的規則都有點不同,以RedHat x86_64為例,其path_grouping_policy預設為failover,也就是主備的方式。這明顯不符合我們的要求。(HDS支援多路徑負載均衡,EMC CX300等只支援Failover)。
所以,我們需要修改預設的規則:
defaults {
udev_dir /dev
path_grouping_policy multibus
failback immediate
no_path_retry fail
user_friendly_name yes
}
關鍵是path_grouping_policy一項,其他選項可參考說明文件。
3、啟動服務及生成對映
# modprobe dm-multipath
# service multipathd start
# multipath -v0
4、檢視複合後的裝置
# multipath -ll
會看到類似下面的資訊:
mpath0 (360060e80058e980000008e9800000007)
[size=20 GB][features="0"][hwhandler="0"]
\_ round-robin 0 [prio=1][active]
\_ 3:0:0:7 sdaa 65:160 [active][ready]
\_ round-robin 0 [prio=1][enabled]
\_ 4:0:0:7 sdas 66:192 [active][ready]
\_ round-robin 0 [prio=1][enabled]
\_ 5:0:0:7 sdbk 67:224 [active][ready]
\_ round-robin 0 [prio=1][enabled]
\_ 2:0:0:7 sdi 8:128 [active][ready]
這說明,已由四條鏈路sdaa/sdas/sdbk/sdi複合成一條鏈路,裝置名為mpath0。
狀態正常的話,把multipathd設定為自啟動:
# chkconfig multipathd on
5、使用mpath裝置
用multipath生成對映後,會在/dev目錄下產生多個指向同一條鏈路的裝置:
/dev/mapper/mpathn
/dev/mpath/mpathn
/dev/dm-n
但它們的來源是完全不同的:
/dev/mapper/mpathn 是multipath虛擬出來的多路徑裝置,我們應該使用這個裝置;
/dev/mpath/mpathn 是udev裝置管理器建立的,實際上就是指向下面的dm-n裝置,僅為了方便,不能用來掛載;
/dev/dm-n 是軟體內部自身使用的,不能被軟體以外使用,不可掛載。
簡單來說,就是我們應該使用/dev/mapper/下的裝置符。對該裝置即可用fdisk進行分割槽,或建立為pv。
6、分割槽或建立lvm
以前,我考慮到從系統iostat看到的都是dm-n的裝置,所以一直都是直接對dm-n操作。但這會產生一個問題,就是沒法分割槽。而對/dev/mapper/mpathn裝置操作就沒有這問題。只要要注意,用fdisk分割槽並儲存後,必須重新整理multipath的對映表,以便其建立分割槽對應的裝置符,例如:
# fdisk -l /dev/mapper/mpath0
Disk /dev/mapper/mpath0: 214.7 GB, 214748364800 bytes
255 heads, 63 sectors/track, 26108 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/mapper/mpath0p1 1 26108 209712478+ 83 Linux
# multipath -F
# multipath -v0
# ll /dev/mapper/mpath0p1
brw-rw---- 1 root disk 253, 2 5月 7 07:40 /dev/mapper/mpath0p1
同樣的,mpathn或其分割槽都可用來做pv使用:
# pvcreate /dev/mapper/mpath0p1
# vgcreate test /dev/mapper/mpath0p1
# lvcreate -L 1g -n lv1 test
# lvdisplay
# mkfs.ext3 /dev/test/lv1
※ 注意:
根據網上的資料,有部分multipath版本存在與lvm相容的問題。具體表現是,使用device-mapper裝置建立lvm完成,重啟後,雖然lvm仍存在,但/dev/mapper下的裝置丟失。為了防止可能的意外,建議還是修改一下lvm的配置檔案/etc/lvm/lvm.conf,加入:
types=["device-mapper", 1]
7、其他
最簡單的測試方法,是用dd往磁碟讀寫資料,然後用iostat觀察各通道的流量和狀態,以判斷Failover或負載均衡方式是否正常:
# dd if=/dev/zero of=/dev/mapper/mpath0
# iostat -k 2
另外,如果是在由多臺伺服器構建叢集環境中,為了讓每臺伺服器識別的mpathn裝置順序一直,需進行wwid的繫結工作,請參考後面“自定義裝置名稱”中的內容。
五、答疑
1、為什麼黑名單中不直接使用devnode "sda" 呢?
因為按Linux對裝置的編號,當裝置從sda到sdz時,後一個裝置應該是sdaa。而multipath對黑名單的設定是以匹配的方式進行的,也就是說,如果你設定為devnode "sda",那麼除了sda為,sdaa、sdab等的裝置(通道)都會被加入到黑名單中,而禁止使用。當然,你也可以參考配置檔案中的樣式,以正規表示式的形式進行描述:devnode "^sda$"。
但考慮到每次重啟後,udev分配的碟符可能都不同(沒有做udev繫結的情況),所以,我覺得以wwid的方式處理更可靠。
2、為儲存定製特定的策略
在前面的配置中,我們已經在/etc/mulitpah.conf中配置了多路徑的預設path_grouping_policy為multibus。但有時候,同一臺機器上如果連線了一個以上的儲存時,可能預設規則並不完全適用。這時,我們可以給特定的儲存定製多路徑符合的策略。
a、mulipath命令
該命令提供了一個-p的引數,可以修改預設策略,引數有:
-p policy force all maps to specified policy :
failover 1 path per priority group
multibus all paths in 1 priority group
group_by_serial 1 priority group per serial
group_by_prio 1 priority group per priority lvl
group_by_node_name 1 priority group per target node
例如,執行:
# multipath -F
# multipath -p failover -v0
有如下結果:
mpath18 (360060e8010463ef004f2b79f00000006)
[size=320 GB][features="0"][hwhandler="0"]
\_ round-robin 0 [prio=2][active]
\_ 5:0:0:6 sdaf 65:240 [active][ready]
\_ 4:0:0:6 sdv 65:80 [active][ready]
\_ round-robin 0 [enabled]
\_ 2:0:0:6 sdb 8:16 [active][ready]
\_ 3:0:0:6 sdl 8:176 [active][ready]
這說明,當你對mpath18裝置讀寫時,sdaf、sdv 會處於active狀態,都有資料流,但sdb、sdl 組成的鏈路是enabled,作為ready情況。這為Failover(主備)情況,僅當sdaf、sdv組成的鏈路出現問題時,才會切換到sdb、sdl 的鏈路上。
b、修改配置檔案
可以在配置檔案中為指定的儲存定義策略。首先,可以用multipath -v3 -ll 看看儲存的資訊,例如,我這裡的機器就同時連線了兩個不同的儲存:
===== path info sdaa (mask 0x5) =====
bus = 1
dev_t = 65:160
size = 10487040
vendor = HITACHI
product = OPEN-V
rev = 6006
h:b:t:l = 2:0:1:24
tgt_node_name = 0x50060e80058e9800
path checker = readsector0 (internal default)
state = 2
uid = 360060e80058e980000008e9800000058 (cache)
===== path info sdaf (mask 0x5) =====
bus = 1
dev_t = 65:240
size = 671088640
vendor = HITACHI
product = DF600F
rev = 0000
h:b:t:l = 3:0:0:6
tgt_node_name = 0x50060e8010463ef1
path checker = readsector0 (internal default)
state = 2
uid = 360060e8010463ef004f2b79f00000006 (cache)
預設情況下,multipath已經支援大部分常見的儲存型號(可見multipath.conf.defaults),但不同的multipath版本可能都有些不同。這時,建議參考儲存的官方文件:
devices {
device {
vendor "HITACHI" //廠商名稱
product "OPEN-V" //產品型號
path_grouping_policy group_by_prio //預設的路徑組策略
getuid_callout "/sbin/scsi_id -p 0x80 -g -u -s /block/%n" //獲得唯一裝置號使用的預設程式
path_checker readsector0 //決定路徑狀態的方法
path_selector "round-robin 0" //選擇那條路徑進行下一個IO操作的方法
prio_callout "/sbin/mpath_prio_alua /dev/%n" //獲取有限級數值使用的預設程式
failback immediate //故障恢復的模式
hardware_handler "0" //確認用來在路徑切換和IO錯誤時,執行特定的操作的模組。
no_path_retry queue //在disable queue之前系統嘗試使用失效路徑的次數的數值
rr_min_io 100 //在當前的使用者組中,在切換到另外一條路徑之前的IO請求的數目
}
}
※ 千萬不要寫錯path_checker(可能值有:readsector0, tur, emc_clariion, hp_sw, directio)。 不清楚的,可從儲存的官方資料獲得。
3、自定義裝置名稱
預設情況下,multipath會根據multipath.conf.defaults中的定義,生成mpathn的裝置名。當然,我們也可以自行定義。不過,更主要的原因是:當我們有多臺伺服器以相同的方式連線到儲存時,每臺伺服器識別出來的mpathn順序可能不同。為了組成叢集,我們需要固定每臺機器識別的裝置名順序是一致的(繫結wwid)。
修改配置檔案,加入:
multipaths {
multipath {
wwid 360060e80058e980000008e9800000007
alias mpath0
}
}
重新重新整理multipath對映表後,mpath0就與該wwid裝置一一對應起來。除了別名alias外,還可以為該裝置定義其他屬性,請參考multipath.conf上的樣式。把該配置賦值到其他同一叢集的機器上,則每臺機器識別的mpathn裝置順序將是一致的。
※ 注意:1、繫結後,需重新生成路徑的對映表;2、當加入該wwid繫結後,沒有繫結的裝置將不能使用,用-ll 也無法看到這些裝置,但/var/lib/multipath/bindings 中可見。
4、如何排錯
# multipath -v3 -ll
# dmsetup ls
# multipathd -k
> > show config
> >reconfigure
> >show paths
> > CTRL-D
/var/lib/multipath/bindings
/dev/mapper/
# cat /sys/block/sda/device/vendor
# cat /sys/block/sda/device/model
※ 注意:
/var/lib/multipath/bindings顯示的內容包括黑名單中的wwid,其mpathn順序與multipath -ll 的結果可能不同。實際以multipath -ll 的結果為可用裝置。