On top of the TCP Protocol, the iSCSI (Internet Small Computer System Interface) is a transport layer protocol. It guarantees block-level data transfer via the TCP/IP network between the iSCSI initiator and the storage target. Additionally, it provides high-level encryption of the data packets being sent as well as decryption upon data packet arrival at the target side.

Table of Contents
iSCSI Target
A networked storage server’s networked storage server or a dedicated physical device in the network can act as an iSCSI target. In SCSI bus communication, the end point serves as the target. LUNs on the target define the storage that an initiator can access.
System Configuration
We need two system to configure iSCSI Target and Initiator, provisioned two RockyLinux 8 virtual machines with following specifications.
iSCSI Server | iSCSI Initiator | |
OS: | RockyLinux 8 | RockyLinux 8 |
Hostname: | server1.techarticles.in | client1.techarticles.in |
IP Address: | 192.168.82.100 | 192.168.82.99 |
Note: Rocky Linux is an open-source enterprise operating system designed to be 100% bug-for-bug compatible with Red Hat Enterprise Linux®. It is under intensive development by the community.
Creating an iSCSI Target
Let’s bigen to Install targetcli
tool on the iSCSI Target server.
# yum install targetcli
[root@TechArticles ~]# yum install targetcli -y Last metadata expiration check: 0:09:40 ago on Mon 17 Apr 2023 12:49:56 AM EDT. Dependencies resolved. =========================================================================================== Package Architecture Version Repository Size =========================================================================================== Installing: targetcli noarch 2.1.53-2.el8 appstream 79 k Installing dependencies: python3-configshell noarch 1:1.1.28-1.el8 baseos 71 k python3-kmod x86_64 0.9-20.el8 baseos 89 k python3-pyparsing noarch 2.1.10-7.el8 baseos 140 k python3-rtslib noarch 2.1.75-4.el8 baseos 102 k python3-urwid x86_64 1.3.1-4.el8 baseos 782 k target-restore noarch 2.1.75-4.el8 baseos 23 k Transaction Summary =========================================================================================== Install 7 Packages [....Altered....] Installed: python3-configshell-1:1.1.28-1.el8.noarch python3-kmod-0.9-20.el8.x86_64 python3-pyparsing-2.1.10-7.el8.noarch python3-rtslib-2.1.75-4.el8.noarch python3-urwid-1.3.1-4.el8.x86_64 target-restore-2.1.75-4.el8.noarch targetcli-2.1.53-2.el8.noarch Complete!
Then access a targetcli shell.
[root@TechArticles ~]# targetcli targetcli shell version 2.1.53 Copyright 2011-2013 by Datera, Inc and others. For help on commands, type 'help'. /> ls
You can Check the current iSCSI Target configurations status by running command.
/> ls o- / ..................................................................... [...] o- backstores .......................................................... [...] | o- block .............................................. [Storage Objects: 0] | o- fileio ............................................. [Storage Objects: 0] | o- pscsi .............................................. [Storage Objects: 0] | o- ramdisk ............................................ [Storage Objects: 0] o- iscsi ........................................................ [Targets: 0] o- loopback ..................................................... [Targets: 0] />
Now create a Storage Block using following commands.
/> cd backstores/block /backstores/block> ls o- block .................................................. [Storage Objects: 0] /backstores/block>create block1 /dev/sdb1 Created block storage object block1 using /dev/sdb1. /backstores/block> /backstores/block> ls o- block .................................................... [Storage Objects: 1] o- block1 ......................... [/dev/sdb1 (11.0GiB) write-thru deactivated] o- alua ..................................................... [ALUA Groups: 1] o- default_tg_pt_gp ......................... [ALUA state: Active/optimized] /backstores/block>
Now Create a Target portal Group
/backstores/block> cd /iscsi /iscsi> create iqn.2023-04.com.example.server1:tadisk1 Created target iqn.2023-04.com.example.server1:tadisk1. Created TPG 1. Global pref auto_add_default_portal=true Created default portal listening on all IPs (0.0.0.0), port 3260. /iscsi> /iscsi> ls o- iscsi .................................................. [Targets: 1] o- iqn.2023-04.com.example.server1:tadisk1 ................. [TPGs: 1] o- tpg1 ..................................... [no-gen-acls, no-auth] o- acls ................................................ [ACLs: 0] o- luns ................................................ [LUNs: 0] o- portals .......................................... [Portals: 1] o- 0.0.0.0:3260 ........................................... [OK] /iscsi>
Get the client iqn (iSCSI Qualified Name) from the client machine and use it to build an ACL that restricts client1.example.com’s access to our iSCSI target.
To obtain the client iqn (iSCSI Qualified Name) from the client machine, Login on client machine and run below command
[root@client1 ~]# iscsi-iname iqn.1994-05.com.redhat:78e811875986 OR # cat /etc/iscsi/initiatorname.iscsi InitiatorName=iqn.1994-05.com.redhat:78e811875986
Now On the iSCSI Target Server build an ACL that restricts client1.example.com’s access to our iSCSI target.
/iscsi> cd /iscsi/iqn.2023-04.com.example.server1:tadisk1/tpg1/acls /iscsi/iqn.20...sk1/tpg1/acls> create iqn.1994-05.com.redhat:78e811875986 Created Node ACL for iqn.1994-05.com.redhat:78e811875986 /iscsi/iqn.20...sk1/tpg1/acls>
Now Create a LUN (Logical Unit Number) for the client.
/iscsi/iqn.20...sk1/tpg1/acls> cd /iscsi/iqn.2023-04.com.example.server1:tadisk1/tpg1/luns/ /iscsi/iqn.20...sk1/tpg1/luns> ls o- luns .............................................................. [LUNs: 0] /iscsi/iqn.20...sk1/tpg1/luns> create /backstores/block/block1 Created LUN 0. Created LUN 0->0 mapping in node ACL iqn.1994-05.com.redhat:78e811875986 /iscsi/iqn.20...sk1/tpg1/luns> ls o- luns ............................................................... [LUNs: 1] o- lun0 ......................... [block/block1 (/dev/sdb1) (default_tg_pt_gp)] /iscsi/iqn.20...sk1/tpg1/luns>
Finally Create a Portal now. IP will be iSCSI target server
/iscsi/iqn.20.../tpg1/portals> create 192.168.82.100
Using default IP port 3260
Could not create NetworkPortal in configFS /iscsi/iqn.20.../tpg1/portals> /iscsi/iqn.20.../tpg1/portals> ls o- portals .................................................. [Portals: 1]o- 0.0.0.0:3260
................................................... [OK] /iscsi/iqn.20.../tpg1/portals>
If you got error Could not create NetworkPortal in configFS
. By default it’s created portal to allow any network, It can be fixed by removing the0.0.0.0:3260
.
Let’s remove 0.0.0.0:3260
and retry to create portal to allow request for 192.168.82.100
Target IP.
/iscsi/iqn.20.../tpg1/portals> delete 0.0.0.0 3260 Deleted network portal 0.0.0.0:3260 /iscsi/iqn.20.../tpg1/portals> create 192.168.82.100 Using default IP port 3260 Created network portal 192.168.82.100:3260. /iscsi/iqn.20.../tpg1/portals> exit Global pref auto_save_on_exit=true Last 10 configs saved in /etc/target/backup/. Configuration saved to /etc/target/saveconfig.json [root@TechArticles ~]#
Open port 3260 in the firewall if running
# firewall-cmd --permanent --add-port=3260/tcp # firewall-cmd --reload
Once the above steps are completed successful, Start and enable the target service.
[root@TechArticles ~]# systemctl enable --now target Created symlink /etc/systemd/system/multi-user.target.wants/target.service → /usr/lib/systemd/system/target.service. [root@TechArticles ~]# systemctl status target ● target.service - Restore LIO kernel target configuration Loaded: loaded (/usr/lib/systemd/system/target.service; enabled; vendor preset: disabled) Active: active (exited) since Mon 2023-04-17 02:10:20 EDT; 11s ago Process: 32982 ExecStart=/usr/bin/targetctl restore (code=exited, status=0/SUCCESS) Main PID: 32982 (code=exited, status=0/SUCCESS)
We have confgured the iSCSI Target.
Let’s Configure an iSCSI Initiator
To configure the iSCSI Initiator Install the iscsi-initiator-utils package.
[root@client1 ~]# yum install -y iscsi-initiator-utils Dependencies resolved. ========================================================================================================= Package Architecture Version Repository Size ========================================================================================================= Installing: iscsi-initiator-utils x86_64 6.2.1.4-3.git2a8f9d8.el9 baseos 378 k Installing dependencies: iscsi-initiator-utils-iscsiuio x86_64 6.2.1.4-3.git2a8f9d8.el9 baseos 94 k isns-utils-libs x86_64 0.101-4.el9 baseos 99 k Transaction Summary ========================================================================================================= Install 3 Packages [... Altered ...] Installed: iscsi-initiator-utils-6.2.1.4-3.git2a8f9d8.el9.x86_64 iscsi-initiator-utils-iscsiuio-6.2.1.4-3.git2a8f9d8.el9.x86_64 isns-utils-libs-0.101-4.el9.x86_64 Complete!
Let’s confirm the iSCSI iqn id we have used during iSCSI Target configuration to create an ACL.
[root@client1 ~]# iscsi-iname iqn.1994-05.com.redhat:78e811875986 OR # cat /etc/iscsi/initiatorname.iscsi InitiatorName=iqn.1994-05.com.redhat:78e811875986
Let’s Start and enable iSCSI service.
[root@client1 ~]# systemctl enable --now iscsi [root@client1 ~]#
run lsblk
command again to check the current disk output of client machine
[root@client1 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 40.7G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 37.7G 0 part ├─rl-root 253:0 0 33.7G 0 lvm / └─rl-swap 253:1 0 4G 0 lvm [SWAP] sr0 11:0 1 1024M 0 rom
Now, Discover the available iSCSI Targets at 192.168.82.100.
[root@client1 ~]# iscsiadm -m discovery -t sendtargets -p 192.168.82.100 192.168.82.100:3260,1 iqn.2023-04.com.example.server1:tadisk1
Once iSCSI discovery has completed successfully, restart the iSCSI service to take effect of the changes.
[root@client1 ~]# systemctl restart iscsi [root@client1 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 40.7G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 37.7G 0 part ├─rl-root 253:0 0 33.7G 0 lvm / └─rl-swap 253:1 0 4G 0 lvm [SWAP] sdb 8:16 0 11G 0 disk sr0 11:0 1 1024M 0 rom
/dev/sdb
has been successfully identified as the iSCSI target disk. Let’s create the filesystem and a partition.
You can use fdisk
command to create partitions on the iSCSI disk or you can use whole disk as per your requirement. For demonstration purpose I am going to create LVM
[root@client1 ~]# pvcreate /dev/sdb Physical volume "/dev/sdb" successfully created. [root@client1 ~]# vgcreate vg_iscsi /dev/sdb Volume group "vg_iscsi" successfully created [root@client1 ~]# lvcreate -l 100%free -n lv_iscsiDisk1 vg_iscsi Logical volume "lv_iscsiDisk1" created. [root@client1 ~]# mkfs.xfs /dev/vg_iscsi/lv_iscsiDisk1 meta-data=/dev/vg_iscsi/lv_iscsiDisk1 isize=512 agcount=4, agsize=716288 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=1, rmapbt=0 = reflink=1 bigtime=0 inobtcount=0 data = bsize=4096 blocks=2865152, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0, ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
Mounting the partition at /mnt/iscsiDisk1 persistently
[root@client1 ~]# mkdir -p /mnt/iscsiDisk1 [root@client1 ~]# echo "/dev/vg_iscsi/lv_iscsiDisk1 /mnt/iscsiDisk1 xfs _netdev 0 0" >> /etc/fstab [root@client1 ~]# mount -a [root@client1 ~]# mount | grep /mnt/iscsiDisk1 /dev/mapper/vg_iscsi-lv_iscsiDisk1 on /mnt/iscsiDisk1 type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota,_netdev)
An iSCSI Target has been successfully created, and it has been persistently mounted at the iSCSI Initiator.
Was this article of use to you? Post your insightful thoughts or recommendations in the comments section if you don’t find this article to be helpful or if you see any outdated information, a problem, or a typo to help this article better.