# iSCSI Storage Server
###### tags: `iscsi`, `san`
iSCSI is a Storage Area Network (SAN) protocol for sharing block devices, partitions or block files on network.
iSCSI target is a service on iSCSI server which provides access to its shared storage devices and iSCSI Initiator is an client which connects the target to access the shared storage.
This lab has basic iSCSI storage server with two iSCSI target servers and one for iSCSI initiator server.
Each target server has additional two block devices for sharing stroage.
Environment:
- OS: Ubuntu 20.04
- iscsi target server 1: 1 vCPU, 2G RAM, vdb (2GB), vcc (2GB), 192.168.122.61
- iscsi target server 2: 1 vCPU, 2G RAM, vdb (2GB), vcc (2GB), 192.168.122.62
- iscsi initiator server: 1 vCPU, 2G RAM, 192.168.122.63
#### Setup steps
Upgrade to the latest packages
```
root@lab-iscsi-initiator:~# apt update; apt upgrade -y
root@lab-iscsi-target-1:~# apt update; apt upgrade -y
root@lab-iscsi-target-2:~# apt update; apt upgrade -y
```
Install iSCSI Target
```
root@lab-iscsi-target-1:~# apt install tgt -y
root@lab-iscsi-target-2:~# apt install tgt -y
```
Configure iSCSI Target. Create **/etc/tgt/conf.d/iscsi.conf** on both target servers.
```
# target 1
<target iqn.2022-10.homelab.com:lun1>
backing-store /dev/vdb
backing-store /dev/vdc
initiator-address 192.168.122.0/24
incominguser iscsi-user password
outgoinguser iscsi-target secretpass
write-cache off
</target>
```
```
# target 2
<target iqn.2022-10.homelab.com:lun2>
backing-store /dev/vdb
backing-store /dev/vdc
initiator-address 192.168.122/24
incominguser iscsi-user password
outgoinguser iscsi-target secretpass
write-cache off
</target>
```
*__NOTE__*: 1st line define name of target.
Ideal format: *iqn.yyyy-mm.naming-authority:unique name* (RFC 3721 and RFC 3722)
yyyy-mm - year and month when naming authority was established
naming-authority - a domain name of naming authority
unique name - a name you want to use
*__NOTE__*: 2nd and 3rd lines sets storage devices. (could use "direct-store" if use entire drive/disk)
*__NOTE__*: 4th line set limit client source. (either client IP or an subnet)
*__NOTE__*: 5th line set user and password for accessing this iSCSI target.
*__NOTE__*: 6th line defines user password for the target to provide manual CHAP authentication to the initiator.
*__NOTE__*: 7th line sets cache on or off. set off to reduce data loss.
Restart iSCSI service on both target servers.
```
root@lab-iscsi-target-1:~# systemctl restart tgt
● tgt.service - (i)SCSI target daemon
Loaded: loaded (/lib/systemd/system/tgt.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-10-08 21:43:38 AEDT; 5s ago
Docs: man:tgtd(8)
Process: 92182 ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v offline (code=exited, status=0/SUCCESS)
Process: 92183 ExecStartPost=/usr/sbin/tgt-admin -e -c /etc/tgt/targets.conf (code=exited, status=0/SUCCESS)
Process: 92245 ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v ready (code=exited, status=0/SUCCESS)
Main PID: 92179 (tgtd)
Status: "Starting event loop..."
Tasks: 33
Memory: 2.3M
CGroup: /system.slice/tgt.service
└─92179 /usr/sbin/tgtd -f
Oct 08 21:43:38 lab-iscsi-target-1 systemd[1]: Starting (i)SCSI target daemon...
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: iser_ib_init(3431) Failed to initialize RDMA; load kernel modules?
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: work_timer_start(146) use timer_fd based scheduler
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: bs_init(387) use signalfd notification
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: device_mgmt(246) sz:14 params:path=/dev/vdb
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: bs_thread_open(409) 16
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: device_mgmt(246) sz:14 params:path=/dev/vdc
Oct 08 21:43:38 lab-iscsi-target-1 tgtd[92179]: tgtd: bs_thread_open(409) 16
Oct 08 21:43:38 lab-iscsi-target-1 systemd[1]: Started (i)SCSI target daemon.
```
```
root@lab-iscsi-target-2:~# systemctl restart tgt
● tgt.service - (i)SCSI target daemon
Loaded: loaded (/lib/systemd/system/tgt.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-10-08 21:47:36 AEDT; 4s ago
Docs: man:tgtd(8)
Process: 91472 ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v offline (code=exited, status=0/SUCCESS)
Process: 91473 ExecStartPost=/usr/sbin/tgt-admin -e -c /etc/tgt/targets.conf (code=exited, status=0/SUCCESS)
Process: 91535 ExecStartPost=/usr/sbin/tgtadm --op update --mode sys --name State -v ready (code=exited, status=0/SUCCESS)
Main PID: 91468 (tgtd)
Status: "Starting event loop..."
Tasks: 33
Memory: 2.3M
CGroup: /system.slice/tgt.service
└─91468 /usr/sbin/tgtd -f
Oct 08 21:47:36 lab-iscsi-target-2 systemd[1]: Starting (i)SCSI target daemon...
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: iser_ib_init(3431) Failed to initialize RDMA; load kernel modules?
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: work_timer_start(146) use timer_fd based scheduler
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: bs_init(387) use signalfd notification
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: device_mgmt(246) sz:14 params:path=/dev/vdb
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: bs_thread_open(409) 16
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: device_mgmt(246) sz:14 params:path=/dev/vdc
Oct 08 21:47:36 lab-iscsi-target-2 tgtd[91468]: tgtd: bs_thread_open(409) 16
Oct 08 21:47:36 lab-iscsi-target-2 systemd[1]: Started (i)SCSI target daemon.
```
Show Target, on both target servers.
```
root@lab-iscsi-target-1:~# tgtadm --mode target --op show
Target 1: iqn.2022-10.homelab.com:lun1
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
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 2147 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:
LUN: 2
Type: disk
SCSI ID: IET 00010002
SCSI SN: beaf12
Size: 2147 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/vdc
Backing store flags:
Account information:
iscsi-user
iscsi-target (outgoing)
ACL information:
192.168.122.0/24
```
```
root@lab-iscsi-target-2:~# tgtadm --mode target --op show
Target 1: iqn.2022-10.homelab.com:lun2
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
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 2147 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:
LUN: 2
Type: disk
SCSI ID: IET 00010002
SCSI SN: beaf12
Size: 2147 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/vdc
Backing store flags:
Account information:
iscsi-user
iscsi-target (outgoing)
ACL information:
192.168.122.0/24
```
Install iSCSI Initiator
```
root@lab-iscsi-initiator:~# apt install open-iscsi -y
```
Discover iSCSI target server
```
root@lab-iscsi-initiator:~# iscsiadm -m discovery -t st -p 192.168.122.61
192.168.122.61:3260,1 iqn.2022-10.homelab.com:lun1
root@lab-iscsi-initiator:~# iscsiadm -m discovery -t st -p 192.168.122.62
192.168.122.62:3260,1 iqn.2022-10.homelab.com:lun2
```
Update InitiatorName in file **/etc/iscsi/initiatorname.iscsi**
```
InitiatorName=iqn.2022-10.homelab.com:initiator
```
*__NOTE__*: Update initiator name step should be done before you start using target LUN.
Define CHAP information (the files should be created after your discover iSCSI target servers)
```
root@lab-iscsi-initiator:~# ls -l /etc/iscsi/nodes/
total 8
drw------- 3 root root 4096 Oct 8 21:49 iqn.2022-10.homelab.com:lun1
drw------- 3 root root 4096 Oct 8 21:49 iqn.2022-10.homelab.com:lun2
```
```
root@lab-iscsi-initiator:~# cd /etc/iscsi/nodes/
root@lab-iscsi-initiator:/etc/iscsi/nodes# tree ./
./
├── iqn.2022-10.homelab.com:lun1
│ └── 192.168.122.61,3260,1
│ └── default
└── iqn.2022-10.homelab.com:lun2
└── 192.168.122.62,3260,1
└── default
```
Edit the *default* files with following lines (files to both targets)
```
node.session.auth.authmethod = CHAP
node.session.auth.username = iscsi-user
node.session.auth.password = password
node.session.auth.username_in = iscsi-target
node.session.auth.password_in = secretpass
node.startup = automatic
```
Full content.
```
root@lab-iscsi-initiator:/etc/iscsi/nodes# cat iqn.2022-10.homelab.com\:lun1/192.168.122.61\,3260\,1/default
# BEGIN RECORD 2.0-874
node.name = iqn.2022-10.homelab.com:lun1
node.tpgt = 1
# set to automatic
node.startup = automatic
node.leading_login = No
iface.iscsi_ifacename = default
iface.transport_name = tcp
iface.vlan_id = 0
iface.vlan_priority = 0
iface.iface_num = 0
iface.mtu = 0
iface.port = 0
iface.tos = 0
iface.ttl = 0
iface.tcp_wsf = 0
iface.tcp_timer_scale = 0
iface.def_task_mgmt_timeout = 0
iface.erl = 0
iface.max_receive_data_len = 0
iface.first_burst_len = 0
iface.max_outstanding_r2t = 0
iface.max_burst_len = 0
node.discovery_address = 192.168.122.61
node.discovery_port = 3260
node.discovery_type = send_targets
node.session.initial_cmdsn = 0
node.session.initial_login_retry_max = 8
node.session.xmit_thread_priority = -20
node.session.cmds_max = 128
node.session.queue_depth = 32
node.session.nr_sessions = 1
# set to CHAP
node.session.auth.authmethod = CHAP
node.session.timeo.replacement_timeout = 120
node.session.err_timeo.abort_timeout = 15
node.session.err_timeo.lu_reset_timeout = 30
node.session.err_timeo.tgt_reset_timeout = 30
node.session.err_timeo.host_reset_timeout = 60
node.session.iscsi.FastAbort = Yes
node.session.iscsi.InitialR2T = No
node.session.iscsi.ImmediateData = Yes
node.session.iscsi.FirstBurstLength = 262144
node.session.iscsi.MaxBurstLength = 16776192
node.session.iscsi.DefaultTime2Retain = 0
node.session.iscsi.DefaultTime2Wait = 2
node.session.iscsi.MaxConnections = 1
node.session.iscsi.MaxOutstandingR2T = 1
node.session.iscsi.ERL = 0
node.session.scan = auto
# add username password
node.session.auth.username = iscsi-user
node.session.auth.password = password
node.session.auth.username_in = iscsi-target
node.session.auth.password_in = secretpass
node.conn[0].address = 192.168.122.61
node.conn[0].port = 3260
node.conn[0].startup = manual
node.conn[0].tcp.window_size = 524288
node.conn[0].tcp.type_of_service = 0
node.conn[0].timeo.logout_timeout = 15
node.conn[0].timeo.login_timeout = 15
node.conn[0].timeo.auth_timeout = 45
node.conn[0].timeo.noop_out_interval = 5
node.conn[0].timeo.noop_out_timeout = 5
node.conn[0].iscsi.MaxXmitDataSegmentLength = 0
node.conn[0].iscsi.MaxRecvDataSegmentLength = 262144
node.conn[0].iscsi.HeaderDigest = None
node.conn[0].iscsi.DataDigest = None
node.conn[0].iscsi.IFMarker = No
node.conn[0].iscsi.OFMarker = No
# END RECORD
```
```
root@lab-iscsi-initiator:/etc/iscsi/nodes# cat iqn.2022-10.homelab.com\:lun2/192.168.122.62\,3260\,1/default
# BEGIN RECORD 2.0-874
node.name = iqn.2022-10.homelab.com:lun2
node.tpgt = 1
# set to automatic
node.startup = automatic
node.leading_login = No
iface.iscsi_ifacename = default
iface.transport_name = tcp
iface.vlan_id = 0
iface.vlan_priority = 0
iface.iface_num = 0
iface.mtu = 0
iface.port = 0
iface.tos = 0
iface.ttl = 0
iface.tcp_wsf = 0
iface.tcp_timer_scale = 0
iface.def_task_mgmt_timeout = 0
iface.erl = 0
iface.max_receive_data_len = 0
iface.first_burst_len = 0
iface.max_outstanding_r2t = 0
iface.max_burst_len = 0
node.discovery_address = 192.168.122.62
node.discovery_port = 3260
node.discovery_type = send_targets
node.session.initial_cmdsn = 0
node.session.initial_login_retry_max = 8
node.session.xmit_thread_priority = -20
node.session.cmds_max = 128
node.session.queue_depth = 32
node.session.nr_sessions = 1
# set to CHAP
node.session.auth.authmethod = CHAP
node.session.timeo.replacement_timeout = 120
node.session.err_timeo.abort_timeout = 15
node.session.err_timeo.lu_reset_timeout = 30
node.session.err_timeo.tgt_reset_timeout = 30
node.session.err_timeo.host_reset_timeout = 60
node.session.iscsi.FastAbort = Yes
node.session.iscsi.InitialR2T = No
node.session.iscsi.ImmediateData = Yes
node.session.iscsi.FirstBurstLength = 262144
node.session.iscsi.MaxBurstLength = 16776192
node.session.iscsi.DefaultTime2Retain = 0
node.session.iscsi.DefaultTime2Wait = 2
node.session.iscsi.MaxConnections = 1
node.session.iscsi.MaxOutstandingR2T = 1
node.session.iscsi.ERL = 0
node.session.scan = auto
# add username password
node.session.auth.username = iscsi-user
node.session.auth.password = password
node.session.auth.username_in = iscsi-target
node.session.auth.password_in = secretpass
node.conn[0].address = 192.168.122.62
node.conn[0].port = 3260
node.conn[0].startup = manual
node.conn[0].tcp.window_size = 524288
node.conn[0].tcp.type_of_service = 0
node.conn[0].timeo.logout_timeout = 15
node.conn[0].timeo.login_timeout = 15
node.conn[0].timeo.auth_timeout = 45
node.conn[0].timeo.noop_out_interval = 5
node.conn[0].timeo.noop_out_timeout = 5
node.conn[0].iscsi.MaxXmitDataSegmentLength = 0
node.conn[0].iscsi.MaxRecvDataSegmentLength = 262144
node.conn[0].iscsi.HeaderDigest = None
node.conn[0].iscsi.DataDigest = None
node.conn[0].iscsi.IFMarker = No
node.conn[0].iscsi.OFMarker = No
# END RECORD
```
Restart open-iscsi and iscsid
```
root@lab-iscsi-initiator:~# systemctl restart open-iscsi iscsid
root@lab-iscsi-initiator:~# systemctl status open-iscsi
root@lab-iscsi-initiator:~# systemctl status open-iscsi
● open-iscsi.service - Login to default iSCSI targets
Loaded: loaded (/lib/systemd/system/open-iscsi.service; enabled; vendor preset: enabled)
Active: active (exited) since Sat 2022-10-08 22:39:26 AEDT; 8s ago
Docs: man:iscsiadm(8)
man:iscsid(8)
Process: 1419 ExecStart=/sbin/iscsiadm -m node --loginall=automatic (code=exited, status=0/SUCCESS)
Process: 1430 ExecStart=/lib/open-iscsi/activate-storage.sh (code=exited, status=0/SUCCESS)
Main PID: 1430 (code=exited, status=0/SUCCESS)
Oct 08 22:39:26 lab-iscsi-initiator systemd[1]: Starting Login to default iSCSI targets...
Oct 08 22:39:26 lab-iscsi-initiator iscsiadm[1419]: Logging in to [iface: default, target: iqn.2022-10.homelab.com:lun1, portal: 192.168.122.61,3260] (multiple)
Oct 08 22:39:26 lab-iscsi-initiator iscsiadm[1419]: Logging in to [iface: default, target: iqn.2022-10.homelab.com:lun2, portal: 192.168.122.62,3260] (multiple)
Oct 08 22:39:26 lab-iscsi-initiator iscsiadm[1419]: Login to [iface: default, target: iqn.2022-10.homelab.com:lun1, portal: 192.168.122.61,3260] successful.
Oct 08 22:39:26 lab-iscsi-initiator iscsiadm[1419]: Login to [iface: default, target: iqn.2022-10.homelab.com:lun2, portal: 192.168.122.62,3260] successful.
Oct 08 22:39:26 lab-iscsi-initiator systemd[1]: Finished Login to default iSCSI targets.
```
Verify iSCSI connection
```
root@lab-iscsi-initiator:~# iscsiadm -m session -o show
tcp: [3] 192.168.122.61:3260,1 iqn.2022-10.homelab.com:lun1 (non-flash)
tcp: [4] 192.168.122.62:3260,1 iqn.2022-10.homelab.com:lun2 (non-flash)
```
Verify block storage device from iSCSI
```
root@lab-iscsi-initiator:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 55.5M 1 loop /snap/core18/2344
loop1 7:1 0 55.6M 1 loop /snap/core18/2566
loop2 7:2 0 61.9M 1 loop /snap/core20/1376
loop3 7:3 0 67.8M 1 loop /snap/lxd/22753
loop4 7:4 0 63.2M 1 loop /snap/core20/1623
loop5 7:5 0 67.9M 1 loop /snap/lxd/22526
loop6 7:6 0 43.6M 1 loop /snap/snapd/15177
loop7 7:7 0 48M 1 loop /snap/snapd/17029
sda 8:0 0 2G 0 disk
└─mpathb 253:0 0 2G 0 mpath
sdb 8:16 0 2G 0 disk
└─mpatha 253:1 0 2G 0 mpath
sde 8:64 0 2G 0 disk
└─mpathb 253:0 0 2G 0 mpath
sdf 8:80 0 2G 0 disk
└─mpatha 253:1 0 2G 0 mpath
vda 252:0 0 16G 0 disk
├─vda1 252:1 0 1M 0 part
└─vda2 252:2 0 16G 0 part /
```
*__NOTE__*: multipath is auto created when start iscsi service. (maybe this is enabled by default???)
#### Tests
```
root@lab-iscsi-initiator:~# mkfs.ext4 /dev/sda
mke2fs 1.45.5 (07-Jan-2020)
Creating filesystem with 524288 4k blocks and 131072 inodes
Filesystem UUID: d04bf38c-0f47-43b7-bc30-129d3a67a749
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
```
```
root@lab-iscsi-initiator:~# mkdir /mnt/data1
root@lab-iscsi-initiator:~# mount /dev/sda /mnt/data1
root@lab-iscsi-initiator:~# df -h | grep data1
/dev/sda 2.0G 24K 1.8G 1% /mnt/data1
```
Repeat for other devices and check.
```
root@lab-iscsi-initiator:~# df -h | grep data
/dev/sda 2.0G 24K 1.8G 1% /mnt/data1
/dev/sdb 2.0G 24K 1.8G 1% /mnt/data2
/dev/sde 2.0G 24K 1.8G 1% /mnt/data3
/dev/sdf 2.0G 24K 1.8G 1% /mnt/data4
```
!!! This is really slow..., but it works.
```
root@lab-iscsi-initiator:~# dd if=/dev/zero of=/mnt/data1/file1 bs=4096 count=100 oflag=direct
100+0 records in
100+0 records out
409600 bytes (410 kB, 400 KiB) copied, 5.14605 s, 79.6 kB/s
```
*__NOTE__*: if mkfs.ext4 shows "/dev/xxx is apparently in use by the system; will not make a filesystem here!", there could be mpath created and remove them as following.
```
root@lab-iscsi-initiator:~# dmsetup status
mpathb: 0 4194304 multipath 2 0 0 0 2 1 A 0 1 2 8:0 A 0 0 1 E 0 1 2 8:16 A 0 0 1
mpatha: 0 4194304 multipath 2 0 0 0 2 1 A 0 1 2 8:80 A 0 0 1 E 0 1 2 8:64 A 0 0 1
root@lab-iscsi-initiator:~# dmsetup remove_all
root@lab-iscsi-initiator:~# dmsetup status
No devices found
```
Or
```
root@lab-iscsi-initiator:~# multipath -ll
root@lab-iscsi-initiator:~# multipath -f mpatha
root@lab-iscsi-initiator:~# multipath -f mpathb
```
#### Todo:
- research multipath
```
root@lab-iscsi-initiator:~# multipath -ll
mpathb (360000000000000000e00000000010001) dm-1 IET,VIRTUAL-DISK
size=2.0G features='0' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=1 status=active
| `- 2:0:0:1 sdb 8:16 active ready running
`-+- policy='service-time 0' prio=1 status=enabled
`- 3:0:0:1 sda 8:0 active ready running
mpatha (360000000000000000e00000000010002) dm-0 IET,VIRTUAL-DISK
size=2.0G features='0' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=1 status=active
| `- 3:0:0:2 sdc 8:32 active ready running
`-+- policy='service-time 0' prio=1 status=enabled
`- 2:0:0:2 sdd 8:48 active ready running
```
#### Reference:
- https://www.howtoforge.com/tutorial/how-to-setup-iscsi-storage-server-on-ubuntu-2004-lts/
- https://www.informaticar.net/ubuntu-20-04-how-to-setup-iscsi-initiator/
- https://linuxhint.com/iscsi_storage_server_ubuntu/
- https://techviewleo.com/configure-iscsi-target-on-ubuntu/
- https://linux.vbird.org/linux_server/centos6/0460iscsi.php#disk
- https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.storage.doc/GUID-686D92B6-A2B2-4944-8718-F1B74F6A2C53.html
- https://blog.csdn.net/weixin_39787057/article/details/116621630
- https://blog.csdn.net/bobpen/article/details/52415267
- https://www.thegeekdiary.com/how-to-configure-dm-multipath-from-an-iscsi-initiator-to-an-iscsi-target-in-centos-rhel/
- https://ubuntu.com/server/docs/service-iscsi
- https://www.it145.com/9/14447.html
- https://ubuntu.com/server/docs/service-iscsi
- https://www.ithome.com.tw/tech/51926