本文詳細介紹iSCSI相關的內容,以及在Linux上如何實現iSCSI。 第1章 iSCSI簡介 1.1 scsi和iscsi 傳統的SCSI技術是存儲設備最基本的標準協議,但通常需要設備互相靠近並用SCSI匯流排連接,因此受到物理環境的限制。 iSCSI(Internet Small Compute ...
本文詳細介紹iSCSI相關的內容,以及在Linux上如何實現iSCSI。
第1章 iSCSI簡介
1.1 scsi和iscsi
傳統的SCSI技術是存儲設備最基本的標準協議,但通常需要設備互相靠近並用SCSI匯流排連接,因此受到物理環境的限制。
iSCSI(Internet Small Computer System Interface),顧名思義,iSCSI是網路上的SCSI,也就是通過網路連接的SCSI。它是由IBM公司研究開發用於實現在IP網路上運行SCSI協議的存儲技術,能夠讓SCSI介面與乙太網技術相結合,使用iSCSI協議基於乙太網傳送SCSI命令與數據,剋服了SCSI需要直接連接存儲設備的局限性,使得可以跨越不同的伺服器共用存儲設備,並可以做到不停機狀態下擴展存儲容量。
iSCSI實現的是IP SAN,數據傳輸基於乙太網。
1.2 iSCSI數據封裝
initiator向target發起scsi命令後,在數據報文從裡向外逐層封裝SCSI協議報文、iSCSI協議報文、tcp頭、ip頭。
封裝是需要消耗CPU資源的,如果完全以軟體方式來實現iscsi,那麼所有的封裝過程都由操作系統來完成。在很繁忙的伺服器上,這樣的資源消耗可能不太能接受,但好在它是完全免費的,對於不是非常繁忙的伺服器採用它可以節省一大筆資金。
除了軟體方式實現,還有硬體方式的initiator(TOE卡和HBA卡),通過硬體方式實現iSCSI。由於它們有控制晶元,可以幫助或者完全替代操作系統對協議報文的封裝。
- TOE卡,操作系統首先封裝SCSI和iSCSI協議報文,而TCP/IP頭則交由TOE內的晶元來封裝,這樣就能減少一部分系統資源消耗。
- HBA卡,操作系統只需封裝SCSI,剩餘的iSCSI協議報文還有TCP/IP頭由HBA晶元負責封裝。
顯然,HBA卡實現iSCSI是最好的方案,但是它要花錢,還不便宜。
第2章 配置使用iSCSI
2.1 部署iscsi前的說明和需求描述
1.說明
- (1).iscsi在target端是工作在套接字上的,監聽埠預設是3260,且使用的是tcp連接。因為要保證數據安全性,使用udp可能會導致丟包。
- (2).iscsi對客戶端有身份認證的需要,有兩種認證方式:基於IP認證,基於CHAP認證(雙方都進行驗證,即雙向認證)。
2.需求描述
找一臺伺服器A作為iscsi的target,將其中的一塊磁碟或分區/dev/sdb當作要共用的存儲設備共用出去。再找兩台伺服器B和C當作iscsi initiator連接到target的共用存儲上。
大致拓撲圖如下:
請確保伺服器A上已經關閉了防火牆或者允許了3260埠。
下圖描述了使用iSCSI的大致過程,後文內容雖然因為介紹各種用法而顯得比較雜,但根據這張圖的流程,閱讀時很容易搞清楚相關內容。
2.2 安裝target
在伺服器A上:
yum -y install scsi-target-utils
查看該工具包生成了哪些文件。
rpm -ql scsi-target-utils
/etc/rc.d/init.d/tgtd #
/etc/sysconfig/tgtd
/etc/tgt/targets.conf #
/usr/sbin/tgt-admin #
/usr/sbin/tgt-setup-lun
/usr/sbin/tgtadm #
/usr/sbin/tgtd
/usr/sbin/tgtimg
/usr/share/doc/scsi-target-utils-1.0.24
/usr/share/doc/scsi-target-utils-1.0.24/README
/usr/share/doc/scsi-target-utils-1.0.24/README.iscsi
/usr/share/doc/scsi-target-utils-1.0.24/README.iser
/usr/share/doc/scsi-target-utils-1.0.24/README.lu_configuration
/usr/share/doc/scsi-target-utils-1.0.24/README.mmc
/usr/share/man/man5/targets.conf.5.gz
/usr/share/man/man8/tgt-admin.8.gz
/usr/share/man/man8/tgt-setup-lun.8.gz
/usr/share/man/man8/tgtadm.8.gz
其中/usr/sbin/tgtadm
和/usr/sbin/tgt-admin
的都是管理和配置target的工具,它們作用是一樣的,只不過tgtadm是命令行下的工具,而tgt-admin是根據配置文件/etc/tgt/targets.conf
調用tgtadm來實現。另外/etc/init.d/tgtd
是服務啟動腳本。
這個時候已經可以啟動target服務了。
service tgtd start
netstat -tnlp | grep 3260
tcp 0 0 0.0.0.0:3260 0.0.0.0:* LISTEN 2074/tgtd
tcp 0 0 :::3260 :::* LISTEN 2074/tgtd
加入開機自啟動。
chkconfig tgtd on
2.2.1 tgtadm命令用法說明
tgtadm是一個高度模式化的命令,他們的模式很相近。有三個模式:target、logicalunit、account。指定模式時使用--mode選項。再使用--op來指定對應模式下的選項。另外,使用-lld指定driver,有兩種driver:iscsi和iser,基本都會使用iscsi。
tgtadm --help
--lld <driver> --mode target --op new --tid <id> --targetname <name>
add a new target with <id> and <name>. <id>
must not be zero.
--lld <driver> --mode target --op delete [--force] --tid <id>
delete the specific target with <id>.
With force option, the specific target is
deleted even if there is an activity.
--lld <driver> --mode target --op show
show all the targets.
--lld <driver> --mode target --op show --tid <id>
show the specific target's parameters.
--lld <driver> --mode target --op update --tid <id> --name <param> --value <value>
change the target parameters of the specific
target with <id>.
--lld <driver> --mode target --op bind --tid <id> --initiator-address <address>
--lld <driver> --mode target --op bind --tid <id> --initiator-name <name>
enable the target to accept the specific initiators.
--lld <driver> --mode target --op unbind --tid <id> --initiator-address <address>
--lld <driver> --mode target --op unbind --tid <id> --initiator-name <name>
disable the specific permitted initiators.
--lld <driver> --mode logicalunit --op new --tid <id> --lun <lun> \
--backing-store <path> --bstype <type> --bsoflags <options>
add a new logical unit with <lun> to the specific
target with <id>. The logical unit is offered
to the initiators. <path> must be block device files
(including LVM and RAID devices) or regular files.
bstype option is optional.
bsoflags supported options are sync and direct
(sync:direct for both).
--lld <driver> --mode logicalunit --op delete --tid <id> --lun <lun>
delete the specific logical unit with <lun>
that the target with <id> has.
--lld <driver> --mode account --op new --user <name> --password <pass>
add a new account with <name> and <pass>.
--lld <driver> --mode account --op delete --user <name>
delete the specific account having <name>.
--lld <driver> --mode account --op bind --tid <id> --user <name> [--outgoing]
add the specific account having <name> to
the specific target with <id>.
<user> could be <IncomingUser> or <OutgoingUser>.
If you use --outgoing option, the account will be
added as an outgoing account.
--lld <driver> --mode account --op unbind --tid <id> --user <name>
delete the specific account having <name> from
specific target.
--control-port <port> use control port <port>
看上去很複雜。不過可以將上面的語法拋去driver部分,target、logicalunit和account這3種模式下的操作方式簡化後如下:
這樣就簡單的多了。
上表中的選項都是長格式的,但他們都有對應的短格式選項。
target和logicalunit兩個模式隨後就會有示例,而account是和CHAP認證有關的,將在後文和配置文件放在一塊解釋。
2.2.2 target的命名方式
iqn.YYYY-mm.<reversed domain name>[:identifier]
iqn
是iscsi qualified name的縮寫,就像fqdn一樣。
YYYY-mm
描述的是此target是何年何月創建的,如2016-06。
<reversed domain name>
是功能變數名稱的反寫,起到了唯一性的作用,如longshuai.com寫為com.longshuai。
identifier
是可選的,是為了知道此target相關信息而設的描述性選項,如指明此target用到了哪些硬碟。
示例:
iqn.2016-06.com.longshuai:test.disk1
2.2.3 創建一個target
需要說明的是,下麵的實驗全是使用命令行工具tgtadm來實現的。但是修改配置文件然後使用tgt-admin也是一樣可以的,且target數量多的時候,更建議使用配置為文件載入的方式。最重要的一點是,使用命令行方式創建的target及lu等是臨時生效的,在target服務重啟後就失效了,再手動建立它們是一件相當麻煩的事情。
如下,分別使用了長格式選項和短格式選項分別創建和顯示target。註意:創建target時,tid不能是0,因為0是被系統保留的。
tgtadm --lld iscsi --mode target --op new --tid 1 --targetname iqn.2017-03.com.longshuai:test.disk1
tgtadm -L iscsi -m target -o show
以上是第一個target的信息。從信息中可以看到:
- 創建完第一個target後自動就創建了一個LUN為0的logicalunit(以後簡稱lu),這是固定給每個target都使用的LUN。
- 此lu的類型是controller。
- "backing store type"為null,即此lu沒有向下擴展邏輯設備,因為它是lun控制器。也就是說這個LUN是保留作為lu控制器用的。
- "I_T nexus information"記錄的是initiator與此target的聯結關係,nexus的意思就是聯結、關聯,在後文介紹initiator的時候會展示此處信息。
現在向此target添加一個lu,使用的是新插入的磁碟/dev/sdc(全新,未進行分區)。當然,使用新建立的分區或者已經格式化後的分區做實驗也可以。
tgtadm -L iscsi -m logicalunit -o new -t 1 -l 1 -b /dev/sdc
然後再來查看target的信息。
tgtadm -L iscsi -m target -o show
從LUN 1信息中可以看出,lu type已經是disk而非controller,且顯示了此lu的容量大小是42950M。另外還顯示了使用的邏輯設備是/dev/sdc,且是可讀可寫的(rdwr)。
但到目前為止,該target都沒有定義共用給誰,這從target信息的最後兩行Account/ACL information中可以看出。
現在將此target綁定一個共用IP,即說明此IP可以連接該target。這是iSCSI的一種認證方式:IP認證。除此之外,還有基於account的CHAP認證,詳細內容見後文。IP認證的作用是允許Initiator發現該target,並允許做進一步的基account的CHAP認證。
tgtadm -L iscsi -m target -o bind -t 1 -I 192.168.100.0/24
tgtadm -L iscsi -m target -o show
再添加一個10G分區/dev/sdb1為邏輯存儲單元,lun=2。
tgtadm -L iscsi -m logicalunit -o new -t 1 -l 2 -b /dev/sdb1
tgtadm -L iscsi -m target -o show
由於該lu是在target id=1下的,所以192.168.100.0這個網段的機器也能訪問此設備。也就是說,共用出去的是target級別而不是lu級別的。
然後在iscsi的"客戶端"initiator安裝iscsi-initiator-utils看看是否能看見這兩個設備。如果想急著看結果,請跳到安裝initiator的章節中。
2.2.4 tgt-admin和配置文件targets.conf
tgt-admin是讀取配置文件的選項然後調用tgtadm來執行的工具。它的選項很多可以簡化tgtadm命令的書寫,畢竟tgtadm的選項太長太多餘了,除此之外也有一些其他的作用用於更細緻的配(tgtadm配置的太粗糙了)。用法如下:
tgt的配置文件為/etc/tgt/targets.conf
,該配置文件的格式很容易讀懂,能實現的target和lun的配置方式多種多樣。它的配製方法在後文會和iscsi initiator的配置文件/etc/iscsi/iscsid.conf放在一起介紹。
下麵就使用tgt-admin為當前的target生成對應的配置文件來稍作分析。
首先列出當前target的信息。
bash> tgt-admin -s
Target 1: iqn.2017-03.com.longshuai:test.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 10742 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: rdwr
Backing store path: /dev/sdb1
Backing store flags:
LUN: 2
Type: disk
SCSI ID: IET 00010002
SCSI SN: beaf12
Size: 42950 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: rdwr
Backing store path: /dev/sdc
Backing store flags:
Account information:
ACL information:
192.168.100.0/24
使用--dump
選項輸出為配置文件的格式,並將其重定向到/tmp/tgt.conf中。
bash> tgt-admin --dump | tee /tmp/tgt.conf
default-driver iscsi
<target iqn.2017-03.com.longshuai:test.disk1>
backing-store /dev/sdb1
backing-store /dev/sdc
initiator-address 192.168.100.0/24
</target>
由此可以看出,全局使用的driver是iscsi,名稱為iqn.2017-03.com.longshuai:test.disk1
的target有兩個backing-store,即邏輯設備,分別是/dev/sdb1和/dev/sdc。但是要註意,這樣導出的配置文件指定的LUN號碼可能會在tgt-admin讀取並執行的時候更換位置,但這並不會有任何影響。
現在將已有的target全部刪除,再去查看信息就已經沒有了。
tgt-admin --delete ALL
tgt-admin -s
再從剛纔生成的配置文件中讀取並啟動。然後查看信息,發現已經有了target。
tgt-admin -e -c /tmp/tgt.conf
tgt-admin -s
關於tgt-admin其他選項也都很簡單,都是從字面意思就能看出來用法的。所以就不多說明瞭。
另外需要說明的是在tgt的配置文件/etc/tgt/targets.conf
中有一行:
#include /etc/tgt/temp/*.conf
將此行註釋後,以後可以導出配置文件到/etc/tgt/temp目錄下並以.conf作為尾碼,重啟tgtd服務即可重新載入,而不需要在手動載入了。不過有個問題,使用dump出來的配置文件會有default-driver指令行,而這一行在主配置文件中也有,且他們是不能出現多次的,否則將會報錯,所以需要將主配置文件中的default-driver指令註釋掉。
2.3 安裝initiator
安裝Initiator的機器成為iscsi的發起者,initiator本身的意思就是"發起者",在這裡即iscsi的"客戶端"程式的意思。
此處先在B伺服器(192.168.100.5)上安裝iscsi-initiator-utils。另一臺C伺服器後面再做測試。
yum -y install iscsi-initiator-utils
2.3.1 相關文件和目錄說明
下麵是此安裝包生成的一些重要文件和目錄(只列出了必要的部分)。
rpm –ql iscsi-initiator-utils
其中:
/etc/iscsi/iscsid.conf
:是iscsi發起者的配置文件。
/etc/rc.d/init.d/{iscsi,iscsid}
:服務啟動腳本,只需要啟動iscsi即可,因為它會自動調用iscsid腳本。
/sbin/iscsi-iname
:為initiator命名的工具。就像target有自己獨特的iqn名稱,initiator也有獨特的名稱標識自己。
/sbin/iscsiadm
:initiator的管理工具,在initiator上的絕大部分的命令都是通過它來執行的。
/var/lib/iscsi/ifaces
:指定使用哪個網卡介面和target通信。
/var/lib/iscssi/nodes
:該目錄中保存了發現的target,分別是以target_name命名的目錄,在target_name目錄下又保存了以"target_ip,port"(如192.168.100.151,3260)的配置文件,這個配置文件是本initiator向對應的target 發起連接時的參數,這些參數繼承於/etc/iscsi/iscsid.conf
。
/var/lib/iscsi/send_targets
:該目錄中也存儲了一個或多個以"target_IP,port"命名的目錄,記錄的是discovery的歷史記錄,對於discovery成功的則在對應的目錄會有文件,否則是空目錄。
其中IP,port
的記錄方式稱為protal,是入口、入門的意思。
需要註意的是,建議不要把iscsi和iscsid設置為開機自啟動,因為開機時如果它找不到target的時候會一直卡在那裡等待。可以將其放在rc.local文件中來啟動。
chkconfig iscsi off
chkconfig iscsid off
echo "service iscsi start" >>/etc/rc.d/rc.local
2.3.2 iscsi-iname命令
和target一樣,initiator也需要一個獨特的名稱來標識自己讓target識別。initiator在連接target的時候,會讀取/etc/iscsi/initiatorname.iscsi中的內容作為自己的iname。
初始狀態的iname如下:
bash> cat /etc/iscsi/initiatorname.iscsi
InitiatorName=iqn.1994-05.com.redhat:ceb390801983
其中尾碼"ceb390801983"是一個隨機串。
也可以為iname生成一個別名,只需在此文件中另起一行寫入以下內容:
InitiatorAlias=INAME_ALIAS
如:
InitiatorAlias=client.longshuai.com
若要自指定iname,可以手動修改該文件。也可以使用iscsi-iname工具來生成iname並保存到該文件。
bash> iscsi-iname
iqn.1994-05.com.redhat:5a804fa64f8e
bash> iscsi-iname
iqn.1994-05.com.redhat:ca4eb16bbddd
可以看出iscsi-iname生成的iname首碼都是一樣的,修改的只是尾碼部分的隨機串。如果要指定首碼,則使用-p選項。
bash> iscsi-iname -p iqn.2017-03.com.longshuai
iqn.2017-03.com.longshuai:adb6a5ec885c
所以,通過iscsi-iname向/etc/iscsi/initiatorname.iscsi中寫入一個iname。
echo Initiatorname=`iscsi-iname -p iqn.2017-03.com.longshuai` >/etc/iscsi/initiatorname.iscsi
然後重啟下iscsi服務。
service iscsi restart
2.3.3 iscsiadm命令
iscsiadm也是一個模式化的命令,使用-m指定mode。mode有:discovery、node、session、iface。一般就用前兩個mode。
discovery
:發現某伺服器是否有target輸出,以及輸出了哪些target。發現target後會生成target資料庫discoverydb。
node
:管理跟某target的關聯關係。在discovery發現了target後,是否要跟target建立關係,是否要刪除已有的關係或者解除已有的關係等。刪除關聯關係不僅會解除關聯,還會刪除發現target後生成的discoverydb。
session
:會話管理。
iface
:介面管理。
2.3.4 發現target(discovery)
即使用discovery模式。
iscsiadm -m discovery [ -d debug_level ] [ -t type -p ip:port -I ifaceN [ -p ip:port ]
-d:輸出調試信息,級別從0-8。出現錯誤的時候用來判斷錯誤來源是很有用處的,可以使用級別2。
-I:指定發現target時通信介面。
-t type:有三種type(sendtargets,SLP,iSNS),一般只會用到sendtargets,可以簡寫為st。
-p IP:PORT:指定要發現target的IP和埠,不指定埠時使用預設的3260。
現在可以進行discovery了。這裡發起兩次,第一次是正確的,第二次是錯誤的(該IP上沒有target或主機未啟動)。
bash> iscsiadm -m discovery -t st -p 192.168.100.151:3260
192.168.100.151:3260,1 iqn.2017-03.com.longshuai:test.disk1
bash> iscsiadm -m discovery -t st -p 192.168.100.152:3260
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: cannot make connection to 192.168.100.152: No route to host
iscsiadm: connection login retries (reopen_max) 5 exceeded
iscsiadm: Could not perform SendTargets discovery: encountered connection failure
如果出現以上錯誤,檢查下是不是防火牆阻擋了,是不是IP地址寫錯了。
在發現了target後,在/var/lib/iscsi
中的nodes和send_targets目錄中就有了文件。
tree /var/lib/iscsi/
可以看到,對於discovery失敗的在send_targets目錄中也會記錄,只不過是空目錄。在nodes目錄和正確discovery到的send_targets子目錄中都有幾個配置文件,都是些參數信息。而且可以看到,send_targets中的目錄是nodes目錄的軟鏈接。
如果想重新發現已存在的target時,可以清空nodes目錄中對應的項,然後再discovery。
使用service iscsi status
可以查看到相關信息項。
2.3.5 關聯和解除關聯target(node)
關聯target的作用是initiator和target建立session,建立session後,initiator上就可以查看、訪問、操作target上的scsi設備。
有兩種關聯方法,一是關聯所有,一是指定單個target進行關聯。
iscsiadm -m node [-d debug_level] [-L all,manual,automatic] [-U all,manual,automatic]
iscsiadm -m node [-d debug_level] [[-T targetname -p ip:port -I ifaceN] [-l | -u ]] [-o operation]
-d:指定debug級別,有0-8個級別。
-L和-U:分別是登錄和登出target,可以指定ALL表示所有發現的target,或者manual指定。
-l和-u:分別是登錄和登出某一個target。
-T:用於-l或-u時指定要登錄和登出的targetname。
-o:對discoverydb做某些操作,可用的操作有new/delete/update/show,一般只會用到delete和show。
例如,使用單個的關聯方式關聯target。其中target_name可以通過命令iscsiadm -m node
查看。
bash> iscsiadm -m node
192.168.100.151:3260,1 iqn.2017-03.com.longshuai:test.disk1
bash> iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
Logging in to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] (multiple)
Login to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] successful.
實際上,在執行discovery的時候很可能就已經自動執行了關聯,所以再次關聯很可能什麼消息也看不到。如果是這樣的話,需要先退出session,再進行關聯。當然也可能是直接顯示successful,這樣就說明原來discovery的時候是沒有主動關聯的。
iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -u
此時fdisk -l看看是否已經多出了兩塊硬碟出來。
bash> fdisk -l
Disk /dev/sda: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0005ff67
Device Boot Start End Blocks Id System
/dev/sda1 * 1 32 256000 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2 32 2356 18666496 83 Linux
/dev/sda3 2356 2611 2048000 82 Linux swap / Solaris
Disk /dev/sdb: 10.7 GB, 10742183424 bytes
64 heads, 32 sectors/track, 10244 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
Disk /dev/sdc: 42.9 GB, 42949672960 bytes
64 heads, 32 sectors/track, 40960 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
現在就可以對這兩塊邏輯盤進行分區格式化(創建文件系統),並投入使用。
此時先看下target端的target信息。
tgt-admin -s | less
其中I_T nexus表示initiator到target的關聯信息,nexus的值是該initiator關聯到target的次數。多個initiator會顯示多個I_T nexus信息。這裡可以看到只有一個I_T nexus,說明只有一個initiator進行了關聯。
2.3.6 iSCSI的數據不安全性(不同步性)
現在在initiator上將/dev/sdb進行格式化,並向其中寫入一個文件。
parted /dev/sdb mklabel gpt
parted /dev/sdb mkpart /dev/sdb1 ext4 1 10G
mkfs.ext4 /dev/sdb1
parted /dev/sdb print
mount /dev/sdb1 /mnt/
echo "haha" > /mnt/test.txt
然後配置伺服器C(192.168.100.6),讓其作為另一臺initiator。
bash> yum -y install iscsi-initiator-utils
bash> iscsiadm -m discovery -t st -p 192.168.100.151:3260
bash> iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
bash> fdisk -l
bash> mount /dev/sdb1 /mnt
bash> ls /mnt
lost+found test.txt
不出所料,C伺服器也能掛載/dev/sdb1,且在B伺服器寫入的test.txt文件也已經同步過來了。
再看看此時target的target信息。
bash> tgt-admin -s
Target 1: iqn.2017-03.com.longshuai:test.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
I_T nexus: 1
Initiator: iqn.2017-03.com.longshuai:b01d684ad13f
Connection: 0
IP Address: 192.168.100.5
I_T nexus: 2
Initiator: iqn.1994-05.com.redhat:42b7f829d2ec
Connection: 0
IP Address: 192.168.100.6
現在在C伺服器上,向/dev/sdb1掛載的目錄/mnt下寫入一個文件,看看是否會同步到B伺服器上。
echo "hehe" >/mnt/test1.txt
在192.168.100.5上執行:
ls /mnt/
lost+found test.txt
echo "heihei" >/mnt/test3.txt
顯然,test1.txt並沒有同步到B伺服器上。同理,此時B中再寫入文件也不會同步到C上。
那麼在C上卸載/mnt,然後再次掛載會有什麼情況呢?
umount /mnt
mount /dev/sdb1 /mnt
ls /mnt
lost+found test3.txt test.txt
沒看錯,test1.txt確實沒了。這就是使用iscsi出現的問題,多個主機同時使用邏輯存儲,數據會衝突並且不能及時同步而導致數據丟失。
所以,iscsi一定要配合集群文件系統或者分散式文件系統來使用以防止上述問題。
2.3.7 initiator開機一直處於等待狀態
該問題在前文描述過。
出現這個問題是因為initiator端設置了iscsi或iscsid開機自啟動,正好又無法和target聯繫,如通信出現故障、target處於關機狀態、target中的tgtd服務未啟動、target上的target_id和target_name等配置改變了。
總而言之,開機自啟動的時候無法正常關聯/var/lib/iscsi目錄下記錄的target就會出現此問題。
解決辦法也是建議的辦法是把iscsi和iscsid的開機自啟動關閉掉,然後把啟動他們的命令放到rc.local中。
如果已經遇到了無法正常開機的情況,那麼可以多等待些時間,或者修改target端讓target端能夠和initiator匹配上。如target端本來是關機狀態,將其開機即可。
第3章 target和initiator的配置文件
3.1 initiator的配置文件
一般而言,對於initiator的配置文件/etc/iscsi/iscsid.conf,裡面預設設置了重啟服務就自動對已發現過的target進行關聯,所以重啟iscsi服務的時候會自動進行關聯。
如果不使用CHAP,則基本可以無視這個配置文件。使用CHAP認證的時候配置下麵CHAP相關的段落就夠了,其他的配置段落可以不用理會。關於CHAP認證,稍後就介紹。
# *************
# CHAP Settings
# *************
####以下是initiator authentication相關
# To enable CHAP authentication set node.session.auth.authmethod to CHAP. The default is None.
#node.session.auth.authmethod = CHAP
# To set a CHAP username and password for initiator authentication by the target(s):
#node.session.auth.username = username
#node.session.auth.password = password
####以下是target authentication相關
# To set a CHAP username and password for target(s) authentication by the initiator:
#node.session.auth.username_in = username_in
#node.session.auth.password_in = password_in
####以下是discovery認證相關,iscsi-initiator-utils似乎不支持這個認證,所以以下項不能開啟和設置
# To enable CHAP authentication for a discovery session to the target
# set discovery.sendtargets.auth.authmethod to CHAP. The default is None.
#discovery.sendtargets.auth.authmethod = CHAP
# To set a discovery session CHAP username and password for the initiator authentication by the target(s):
#discovery.sendtargets.auth.username = username
#discovery.sendtargets.auth.password = password
# To set a discovery session CHAP username and password for target(s) authentication by the initiator:
#discovery.sendtargets.auth.username_in = username_in
#discovery.sendtargets.auth.password_in = password_in
所以,如果只要實現單向認證,則開啟以下三項即可。
node.session.auth.authmethod = CHAP
node.session.auth.username = username
node.session.auth.password = password
如果要實現雙向認證,則需要開啟以下5項。
node.session.auth.authmethod = CHAP
node.session.auth.username = username
node.session.auth.password = password
node.session.auth.username_in = username_in
node.session.auth.password_in = password_in
且需要註意的是,如果是單向認證,則後兩項必須不能開,開了就會進行雙向認證。
雖然iscsi-initiator-utils支持discovery認證,但是由於scsi-target-utils不支持discovery認證,所以在認證關聯target之前必須先進行discovery,也就是說在target端的訪問控制列表ACL項中必須要定義允許initiator進行discovery。
3.2 target配置文件的配置方法
target端使用tgtadm命令配置的結果都是工作在內核中的,重啟tgt服務或重啟系統時,記憶體中的內容都會丟失。所以要永久讓配置生效需要寫入到配置文件中去。
target的配置文件預設是/etc/tgt/targets.conf,但是可以在/etc/tgt/temp/目錄(預設不存在)下建立多個以".conf"為尾碼的配置文件,然後啟用主配置文件中的include指令即可。
以下給出兩個配置的例子,這個配置文件很通俗易懂。
#include /etc/tgt/temp/*.conf
default-driver iscsi
<target iqn.2017-03.com.longshuai:test.disk1>
backing-store /dev/sdb1
backing-store /dev/sdc
incominguser <incoming_username> <PASSWORD>
outgoinguser <outgoing_username> <PASSWORD>
initiator-address 192.168.100.0/24
</target>
這樣的配置,backing-store的順序決定了lun號碼的順序,上面的配置中/dev/sdb1會是Lun1,/dev/sdc會是lun2。
若想要為每個邏輯設備指定想要指定的lun號碼,需要將每個backing-store封裝在target中並獨立指定lun號碼。
#include /etc/tgt/temp/*.conf
default-driver iscsi
<target iqn.2017-03.com.longshuai:test.disk1>
<backing-store /dev/sdb1>
lun 5
</backing-store>
<backing-store /dev/sdc>
lun 6
</backing-store>
incominguser <incoming_username> <PASSWORD>
outgoinguser <outgoing_username> <PASSWORD>
initiator-address 192.168.100.0/24
</target>
3.3 重啟tgtd服務不載入配置文件的問題
如果在正常狀態下有initiator關聯了target設備,此時重啟tgtd服務很可能會導致配置文件中的配置不生效,這是為了保護initiator仍然可以隨時關聯target而不丟失數據和狀態設立的機制。但不得不說,這個特性真的很讓人煩惱,配置不生效,難道非得再使用tgtadm來重新生成到內核嗎?
問題如下描述。
當前的target狀態如下:
bash> tgt-admin -s
Target 1: iqn.2017-03.com.longshuai:test1.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
……省略部分結果……
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
……省略部分結果……
LUN: 2
Type: disk
SCSI ID: IET 00010002
SCSI SN: beaf12
Size: 42950 MB, Block size: 512
……省略部分結果……
Account information:
ACL information:
192.168.100.0/24
配置文件中啟用的項如下。這和上面的狀態是一樣的。
<target iqn.2017-03.com.longshuai:test1.disk1>
backing-store /dev/sdb1
backing-store /dev/sdc
initiator-address 192.168.100.0/24
</target>
此時在initiator上關聯此target,然後登出。這裡無論登不登出對target的影響都是一樣的。
iscsiadm -m discovery -t st -p 192.168.100.151:3260
iscsiadm -m node -T iqn.2017-03.com.longshuai:test1.disk1 -p 192.168.100.151:3260 -l
iscsiadm -m node -T iqn.2017-03.com.longshuai:test1.disk1 -p 192.168.100.151:3260 -u
再重啟target上的tgtd服務,然後查看狀態。
service tgtd restart
Stopping SCSI target daemon: [ OK ]
Starting SCSI target daemon: [ OK ]
tgt-admin -s
Target 1: iqn.2017-03.com.longshuai:test1.disk1
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
Backing store type: null
Backing store path: None
Backing store flags:
Account information:
ACL information:
192.168.100.0/24
結果lun1和lun2沒了。無論再怎麼重啟結果都是一樣,哪怕是手動使用tgt-admin -e -c
指定配置文件執行結果也一樣。
好在/etc/init.d/tgtd提供了不少的選項。
/etc/init.d/tgtd --help
Usage: /etc/init.d/tgtd {start|stop|status|restart|condrestart|try-restart|reload|force-stop|force-restart|force-reload}
它們的意思無須多述。
經過測試,上述問題只有使用force-reload選項能解決,其他所有選項都無效,包括force-restart和reload。
service tgtd force-reload
或者重啟系統也能解決,但是誰沒事會重啟系統呢?
第4章 account模式和CHAP認證
4.1 CHAP認證
基於IP的認證比較粗糙,不過多數時候已經夠用了。但對於安全性要求高的環境來說,使用CHAP認證更好一些。
CHAP(Challenge-Handshake Authentication Protocol),稱為挑戰式握手認證協議,它是雙向認證,當然也支持單向認證。
對於iscsi而言,在CHAP認證的機制上有兩種方式:initiator authentication
和target authentication
。
- initiator authentication認證
在initiator嘗試連接到一個target的時候,initator需要提供一個用戶名和密碼給target被target進行認證。也就是說initiator需要被target認證,它向target端提供的賬號和密碼是target端指定的。
這個賬號和密碼對於target來說是流入的賬號和密碼,用incoming表示。所以後面稱呼這個賬號和密碼為incoming賬號和incoming密碼。再次說明,incoming賬號是initiator端提供給target端,被target端認證的賬號。
- target authentication認證
在initiator嘗試連接到一個target的時候,target有時也需要被initiator認證,以確保該target是合法而非偽裝的target,這就要求target提供一個用戶名和密碼給initiator被initiator進行認證。
target向initiator提供的賬號和密碼對於target而言是流出的,所以稱之為outgoing。所以outgoing使用的賬號和密碼在後文稱為outgoing賬號和outgoing密碼。而對於initiator而言是incoming的,所以在initiator配置文件中稱為in。也就是說outgoing賬號是target端提供給initiator端,被initiator認證的賬號,但儘管如此,這個賬號和密碼還是在target端創建和綁定的。
綜上,不管是什麼認證,賬號和密碼都是target端創建和綁定。
以上兩種認證方式是有層次順序的。一般來說,有認證需求的時候都是伺服器驗證客戶端是否有許可權,iscsi也一樣。
initiator authentication
可以單獨存在,它可以在沒有target authentication
的情況下應用,這時候的CHAP認證就是單向認證(target認證initiator的合法性)。
但target authentication
只有在initiator authentication
的基礎上才能進行。也就是說target認證和initiator認證必須同時存在才可以。即initiator和target需要相互認證實現雙向CHAP認證。
4.2 tgtadm命令的account模式用法
以下是tgtadm --help
關於account的結果,但是用法給的並不全面。
--lld <driver> --mode account --op new --user <name> --password <pass>
--lld <driver> --mode account --op delete --user <name>
--lld <driver> --mode account --op bind --tid <id> --user <name> [--outgoing]
--lld <driver> --mode account --op unbind --tid <id> --user <name>
以下是個人發現的較為全面的用法,為了偷懶,所以使用短選項格式來表示。其中
# 新建一個用戶
-L <driver> -m account -o new --u <name> --p <pass>
# 刪除一個用戶
-L <driver> -m account -o delete --u <name>
# 查看用戶列表
-L <driver> -m account -o show
# 綁定用戶到target上,outgoing的意義在後文會說明
-L <driver> -m account -o bind -t <tid> -u <name> [--outgoing]
# 從target上解綁用戶
-L <driver> -m account -o unbind -t <tid> -u <name> [--outgoing]
4.3 實現CHAP單向認證
首先確保target的ACL是允許initiator進行discovery的。
bash> tgt-admin -s | sed -n '/Account/,$p' Account information: ACL information: 192.168.100.0/24
在target端創建
initiator authentication
所需的賬號和密碼並綁定到target_ID上。這個賬號是用來對initiator進行單向認證的,所以對於target而言是incoming賬號。tgtadm -L iscsi -m account -o new --user incoming_malong --password incoming_123456 tgtadm -L iscsi -m account -o bind -t 1 --user incoming_malong
查看下綁定情況。
由於tgtg的工作在內核當中的,所以配置好後無需重啟服務,這些賬號相關的就可以生效。tgt-admin -s | sed -n '/Account/,$p' Account information: incoming_malong ACL information: 192.168.100.0/24
在initiator端修改配置文件/etc/iscsi/iscsid.conf,設置以下幾項,這裡故意沒啟用密碼認證部分,是為了看到認證失敗的結果。。(這裡使用的是伺服器B,即192.168.100.5這台機器,伺服器C即192.168.100.6在後面綁定多個賬號的時候拿來做測試用)
vim /etc/iscsi/iscsid.conf node.session.auth.authmethod = CHAP node.session.auth.username = incoming_malong #node.session.auth.password = incoming_123456
在initiator發現,然後關聯。
bash> iscsiadm -m discovery -t st -p 192.168.100.151:3260 192.168.100.151:3260,1 iqn.2017-03.com.longshuai:test.disk1 bash> iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l Logging in to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] (multiple) iscsiadm: Could not login to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260]. iscsiadm: initiator reported error (24 - iSCSI login failed due to authorization failure) iscsiadm: Could not log into all portals
因為認證所需的密碼沒設置,所以認證失敗了。設置為正確的賬號和密碼再進行發現、關聯認證。
bash> vim /etc/iscsi/iscsid.conf
node.session.auth.authmethod = CHAP
node.session.auth.username = incoming_malong
node.session.auth.password = incoming_123456
bash> iscsiadm -m discovery -t st -p 192.168.100.151:3260
192.168.100.151:3260,1 iqn.2017-03.com.longshuai:test.disk1
bash> iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
Logging in to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] (multiple)
Login to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] successful.
4.4 實現CHAP雙向認證
要雙向認證,那麼target端需要創建一個outgoing賬號和密碼,並綁定到target上。註意下麵的--outgoing
選項,表示是從target流出的賬號,即表示該target要被initiator認證。
tgtadm -L iscsi -m account -o new --user outgoing_malong --password outgoing_123456
tgtadm -L iscsi -m account -o bind -t 1 --user outgoing_malong --outgoing
查看下target上的賬號信息。在信息中,outgoing的賬號後面使用括弧對此進行了標識。
tgt-admin -s | sed -n '/Account/,$p'
Account information:
incoming_malong
outgoing_malong (outgoing)
ACL information:
192.168.100.0/24
然後在initiator端配置CHAP雙向認證。同樣,此處先配置一個錯誤的情況以作比較。
vim /etc/iscsi/iscsid.conf
node.session.auth.authmethod = CHAP
node.session.auth.username = incoming_malong
node.session.auth.password = incoming_123456
node.session.auth.username_in = outgoing_malong
#node.session.auth.password_in = outgoing_123456
重新進行發現和關聯。不過首先要登出已經登錄的target。
iscsiadm -m node -Tiqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -u
iscsiadm -m discovery -t st -p 192.168.100.151:3260
192.168.100.151:3260,1 iqn.2017-03.com.longshuai:test.disk1
iscsiadm -m node -Tiqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
Logging in to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260] (multiple)
iscsiadm: Could not login to [iface: default, target: iqn.2017-03.com.longshuai:test.disk1, portal: 192.168.100.151,3260].
iscsiadm: initiator reported error (19 - encountered non-retryable iSCSI login failure)
iscsiadm: Could not log into all portals
它提示遇到不可重試的iscsi登錄錯誤,因為target無法被initiator認證,initiator認為這個target是非法的target。
配置為正確的密碼然後再進行發現、關聯。
vim /etc/iscsi/iscsid.conf
node.session.auth.authmethod = CHAP
node.session.auth.username = incoming_malong
node.session.auth.password = incoming_123456
node.session.auth.username_in = outgoing_malong
node.session.auth.password_in = outgoing_123456
iscsiadm -m discovery -t st -p 192.168.100.151:3260
iscsiadm -m node -Tiqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
4.5 綁定多個outgoing賬號
tgtadm -L iscsi -m account -o new --user outgoing_user1 --password outgoing_passwd1
tgtadm -L iscsi -m account -o bind -t 1 --user outgoing_user1 --outgoing
tgtadm: this target already has an outgoing account
綁定的時候提示已經有一個outgoing賬號,說明一個target的outgoing賬號只能有一個。也就是說,某一個target被認證的時候是1對多的關係。
但是incoming賬號並非如此。
4.6 綁定多個incoming賬號
tgtadm -L iscsi -m account -o new --user incoming_user1 --password incoming_passwd1
tgtadm -L iscsi -m account -o new --user incoming_user2 --password incoming_passwd2
tgtadm -L iscsi -m account -o bind -t 1 --user incoming_user1
tgtadm -L iscsi -m account -o bind -t 1 --user incoming_user2
tgt-admin -s | sed -n '/Account/,$p'
Account information:
incoming_malong
incoming_user1
incoming_user2
outgoing_malong (outgoing)
ACL information:
192.168.100.0/24
用伺服器C即192.168.100.6來登錄一個看看。
vim /etc/iscsi/iscsid.conf
node.session.auth.authmethod = CHAP
node.session.auth.username = incoming_user1
node.session.auth.password = incoming_passwd1
node.session.auth.username_in = outgoing_malong
node.session.auth.password_in = outgoing_12345
發現並關聯。
iscsiadm -m node -U all
iscsiadm -m discovery -t st -p 192.168.100.151:3260
iscsiadm -m node -T iqn.2017-03.com.longshuai:test.disk1 -p 192.168.100.151:3260 -l
所以,incoming賬號可以有多個。
4.7 解綁和刪除用戶
先查看下有目前有哪些用戶。
tgtadm -L iscsi -m account -o show
Account list:
outgoing_user1
incoming_user2
incoming_user1
outgoing_malong
incoming_malong
再查看下哪些用戶是已經綁定到target上的。
tgt-admin -s | sed -n '/Account/,$p'
Account information:
incoming_malong
incoming_user1
incoming_user2
outgoing_malong (outgoing)
ACL information:
192.168.100.0/24
對incoming_user1和incoming_user2進行解綁。
tgtadm -L iscsi -m account -o unbind -t 1 -u incoming_user1
tgtadm -L iscsi -m account -o unbind -t 1 -u incoming_user2
對outgoing賬戶解綁。
tgtadm -L iscsi -m account -o unbind -t 1 -u outgoing_malong --outgoing
刪除多餘的賬戶。
tgtadm -L iscsi -m account -o delete -u incoming_user1
tgtadm -L iscsi -m account -o delete -u incoming_user2
tgtadm -L iscsi -m account -o delete -u outgoing_malong
tgtadm -L iscsi -m account -o delete -u outgoing_user1
第5章 快速配置iscsi兩端
這裡是對前文的一個總結,用於解釋要使用iscsi時對target端和initiator大致需要做哪些事情。
#############################
# target端所需要做的事情
#############################
tgtadm -L iscsi -m target -o new -t 1 -T iqn.2017-03.com.longshuai:test1.disk1
tgtadm -L iscsi -m logicalunit -o new -t 1 -l 1 -b /dev/sdb1
tgtadm -L iscsi -m logicalunit -o new -t 1 -l 2 -b /dev/sdc
tgtadm -L iscsi -m target -o bind -t 1 -I 192.168.100.0/24
#如果要CHAP認證,則繼續添加相關賬戶和密碼並綁定到target上
tgtadm -L iscsi -m account -o new -u USERNAME -p PASSWORD
tgtadm -L iscsi -m account -o bind -t 1 -u USERNAME [--outgoing]
#最後將配置放入到配置文件中
sed -i -r 's/#include(.*)/include\1/' /etc/tgt/targets.conf
mkdir /etc/tgt/temp
tgt-admin --dump | sed '/default/d' >/etc/tgt/temp/tgt1.conf
#不用重啟服務。
#如特殊情況,出現重啟tgtd伺服器但是配置文件不生效的情況,適應force-reload選項
#service tgtd force-reload
#############################
# initiator端所需要做的事情
#############################
#第一件事是決定是否要自定義initiator的名稱,如果需要自定義,則修改/etc/iscsi/initiatorname.iscsi文件
#首先discovery目標主機上有哪些可用的target
iscsiadm -m discovery -t st -p 192.168.100.151:3260
# 然後登陸target
iscsiadm -m node -T iqn.2017-03.com.longshuai:test1.disk1 -p 192.168.100.151:3260 -l
#如果需要CHAP認證,則啟用/etc/iscsi/iscsid.conf中的相關CHAP認證指令
#前三項實現單向認證,target端認證initiator是否合法
#同時啟用這5項實現雙向認證,target端和initiator都會認證對方是否合法
node.session.auth.authmethod = CHAP
node.session.auth.username = incoming_malong
node.session.auth.password = incoming_123456
node.session.auth.username_in = outgoing_malong
node.session.auth.password_in = outgoing_123456
第6章 windows上配置initiator
在"運行"中輸入iscsicpl.exe
,打開iscsi發起程式。
但要註意,Windows中格式化的NTFS文件系統在Linux中預設是不支持的,所以iscsi的共用存儲不能跨Windows和Linux系統使用,除非安裝支持插件。