1. 程式人生 > >Multipath多路徑冗餘全解

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 的結果為可用裝置。