介紹
將遠(yuǎn)端的存儲通過iscsi協(xié)議為容器提供塊存儲,是一種通用的容器存儲解決方案,下面將通過kubernetes中的in-tree方式來演示該例子,并分析其中的細(xì)節(jié)。
iSCSI協(xié)議是C/S架構(gòu),client是iSCSI initiator,server端為iSCSI target。iSCSI協(xié)議的主要功能是利用TCP/IP網(wǎng)絡(luò),在主機(jī)系統(tǒng)(可稱為initiator)和目標(biāo)存儲設(shè)備(稱為target)之間進(jìn)行大量的數(shù)據(jù)封裝和可靠傳輸過程。主要分成兩個組成部分,分別為iSCSI服務(wù)器端和iSCSI客戶端
iSCSI服務(wù)器端 (iSCSI Target)
iSCSI服務(wù)器端為iSCSI target,這是I/O操作的執(zhí)行者。主要是為了導(dǎo)出一個或多個塊設(shè)備供啟動者(initiator)使用,可以通過硬件和軟件的方式來實現(xiàn)。在Linux中可以使用scsi-target-utils軟件包來模擬實現(xiàn)。在使用iSCSI時,會在 iSCSI 儲存設(shè)備上去建立 LUN(Logical Unit Number)來提供給具備 iSCSI Initiator 功能的主機(jī)來存取 數(shù)據(jù)的。LUN 好比是個“邏輯單位磁碟”,物理上通常是由數(shù)個實體磁碟( RAID 或 LVM 技術(shù)的技術(shù)實現(xiàn))所組成。LUN ID由iSCSI目標(biāo)設(shè)備(Target)分配。iSCSI 啟動端(Initiator)設(shè)備當(dāng)前支持在每個目標(biāo)設(shè)備(Target)中導(dǎo)出最多256個LUN。即最大支持16個target。
iSCSI target設(shè)備名稱采用如下格式來命名:iqn..[:],需要事先進(jìn)行配置,保證唯一性。
iSCSI客戶端 (iSCSI Initiator)
iSCSI客戶端為iSCSI initiator,這是I/O操作的發(fā)起者。是I/O操作的發(fā)起者,需要通過發(fā)現(xiàn)過程請求遠(yuǎn)端快設(shè)備。在Linux系統(tǒng)中可以通過軟件來模擬,需要安裝iSCSI設(shè)備驅(qū)動。如iscsi-initiator-utils。
實驗
可以通過iSCSI將遠(yuǎn)程的磁盤分區(qū)映射到本地之后就可以像使用本地磁盤一樣,將該遠(yuǎn)程盤進(jìn)行格式化以及掛載操作,給容器使用。
我們通過scsi-target-utils來實現(xiàn)iSCSI target,將主機(jī)上的/dev/sdb磁盤分區(qū)作為Lun,如下圖所示
[root@iscsi-server yum.repos.d]# tgtadm -L iscsi -o show -m target
Target 1: iqn.2021-11.com.huayun.san:123456
System information:
Driver: iscsi
State: ready
I_T nexus information:
LUN information:
LUN: 0
Type: controller
SCSI ID: IET00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET00010001
SCSI SN: beaf11
Size: 10737 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: rdwr
Backing store path: /dev/vdb
Backing store flags:
Account information:
ACL information:
之后在kubernetes的node節(jié)點(diǎn)上需要事先安裝iscsi-initiator-utils,并且設(shè)置對應(yīng)的initiatorname,如果開啟了acl認(rèn)證,需要將node節(jié)點(diǎn)的initiatorname添加到acl里面。
之后創(chuàng)建一個pod,其中指定一個存在的iscsi lun對接信息如下
apiVersion: v1
kind: Pod
metadata:
name: iscsipd
spec:
containers:
- name: iscsipd-rw
image: kubernetes/pause
volumeMounts:
- mountPath: "/mnt/iscsipd"
name: iscsipd-rw
volumes:
- name: iscsipd-rw
iscsi:
targetPortal: 10.0.2.15:3260
portals: ['10.0.2.16:3260', '10.0.2.17:3260']
iqn: iqn.2001-04.com.example:storage.kube.sys1.xyz
lun: 0
fsType: ext4
readOnly: true
之后可以看到遠(yuǎn)程的卷被成功的掛載到node上,被容器所使用
Volume.iscsi說明
pod的spec中可以在volumes.iscsi中指定對接信息包括如下
iscsi.iqn
required,string
Target iSCSI Qualified Name.
iscsi.lun
required,int32
iSCSI Target Lun number.
iscsi.targetPortal
required,string
iSCSI Target Portal. The Portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).
iscsi.chapAuthDiscovery
bolean
whether support iSCSI Discovery CHAP authentication
iscsi.chapAuthSession
boolean
whether support iSCSI Session CHAP authentication
iscsi.fsType
string
Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified.
iscsi.initiatorName
string
Custom iSCSI Initiator Name. If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface:will be created for the connection.
iscsi.iscsiInterface
string
iSCSI Interface Name that uses an iSCSI transport. Defaults to 'default' (tcp).
iscsi.portals
[]string
iSCSI Target Portal List. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).
iscsi.readOnly
boolean
ReadOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false.
iscsi.secretRef
LocalObjectReference
CHAP Secret for iSCSI target and initiator authentication
源碼分析
掛載階段
pod調(diào)度到某個node上,之后由kubelet中的volumemanager完成對于volume attach&mount操作,核心代碼位于kubernetes/pkg/volume/iscsi目錄下,在volume掛載的過程中,會首先調(diào)用WaitForAttach()完成掛載流程,SetUpDevice()掛載到某個容器所對應(yīng)的目錄。iscsiAttacher.WaitForAttach()流程如圖所示:
Step1: 通過iscsiadm -m iface -l b. InitIface -o show獲取對應(yīng)的iscsiTransport,如果不額外指定的話b. InitIface為default,iscsiTransport為tcp.
Step2: 如果pod的定義中指定iscsi.initiatorName,則需要cloneIface(), 指定iscsi.initiatorName需要與node的不一致,這樣當(dāng)開啟ACL initiatorName控制的時候,pod可以運(yùn)行在不同的節(jié)點(diǎn)上。
Step3: 基于iqn號獲取lock,主要解決的場景為相同target下不同volume同時掛載或者login與logout操作并發(fā)進(jìn)行,這個鎖引入的目的主要是為了后面volume在Detach的時候,需要根據(jù)isSessionBusy來判斷是否需要logout,斷開node與target的所有鏈接。
Step4: GetISCSIPortalHostMapForTarget主要根據(jù)target iqn獲取到login到該target上的scsi hosts number,返回的結(jié)構(gòu)為
{
"192.168.30.7:3260": 2,
"192.168.30.8:3260": 3,
}
通過這個map的引入后面用于判斷是否需要login,還是直接通過scanOneLun()來發(fā)現(xiàn)接入的Lun,避免沒有必要的login操作。scanOneLun之后會發(fā)現(xiàn)掛載到node上的device。
Step5: 根據(jù)volomeMode的類型是直接的PersistentVolumeBlock還是PersistentVolumeFileSystem模式,二者的區(qū)別在于是否需要對device進(jìn)行格式化,創(chuàng)建文件系統(tǒng),之后創(chuàng)建globalPDPath目錄,目錄位置采用如下格式
/var/lib/kubelet/plugins/kubernetes.io/iscsi/ /{ifaceName}/{portal-some_iqn-lun-lun_id},之后持久化的iscsi disk元數(shù)據(jù)到globalPDPath目錄下iscsi.json,元數(shù)據(jù)主要用于DetachVolume的時候會涉及到,內(nèi)容如下所示:
{
"VolName":"iscsipd-rw",
"Portals":[
"178.104.162.58:3260",
],
"Iqn":"iqn.2021-11.com.huayun.san:123456",
"Lun":"1",
"InitIface":"default",
"Iface":"default",
"InitiatorName":"",
"MetricsProvider":null
}
在WaitForAttach 階段完成了device遠(yuǎn)端掛載、格式化以及掛載到globalPDPath目錄下,SetUpDevice流程較為簡單主要是將globalPDPath mount –bind到容器對應(yīng)的目錄,之后對目錄進(jìn)行SetVolumeOwnership()操作。
卸載階段
pod銷毀的時候,會由kubelet完成volume的umount&detach操作,核心代碼位于kubernetes/pkg/volume/iscsi目錄下,主要完成umount node上的掛載信息,之后根據(jù)globalPDPath目錄下iscsi.json元數(shù)據(jù)信息來完成TearDownDevice斷開device,之后清理掉globalPDPath。
Step1: 根據(jù)mntPath掛載點(diǎn)信息獲得device盤符,之后Unmount()掉掛載點(diǎn)信息
Step2:loadISCSI中根據(jù)mntPath獲得該iscsi掛載信息的元數(shù)據(jù)信息,其中包括iqn iface volName initiatorName等信息
Step3: deleteDevices()中通過對device進(jìn)行echo 1> delete操作,刪除掉盤符
Step4: 基于iqn獲取targetLocks.LockKey,之后判斷該target在node上是否存在其他的盤掛載,如果沒有存在,則進(jìn)行iscsi logout操作,斷開node與target之后的連接
總結(jié)
In-tree下的iscsi方式為容器提供iscsi的存儲類似于靜態(tài)供應(yīng),需要事先系統(tǒng)管理員創(chuàng)建好后端的iscsi存儲,之后容器提供指定對應(yīng)的配置來使用。對于已經(jīng)存在支持iscsi協(xié)議掛載的后端存儲,并且不具備動態(tài)功能csi插件的場景下具有一定的使用場景。
(免責(zé)聲明:本網(wǎng)站內(nèi)容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請進(jìn)一步核實,并對任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對有關(guān)資料所引致的錯誤、不確或遺漏,概不負(fù)任何法律責(zé)任。
任何單位或個人認(rèn)為本網(wǎng)站中的網(wǎng)頁或鏈接內(nèi)容可能涉嫌侵犯其知識產(chǎn)權(quán)或存在不實內(nèi)容時,應(yīng)及時向本網(wǎng)站提出書面權(quán)利通知或不實情況說明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實情況證明。本網(wǎng)站在收到上述法律文件后,將會依法盡快聯(lián)系相關(guān)文章源頭核實,溝通刪除相關(guān)內(nèi)容或斷開相關(guān)鏈接。 )