Beginners Guide to Configuring iSCSI in CentOS/RHEL 7

Introduction To ISCSI

The Internet Small Computer System Interface (iSCSI) is a TCP/IP-based protocol for emulating a SCSI high-performance local storage bus over IP networks, providing data transfer and management to remote block storage devices. As a storage area network (SAN) protocol, iSCSI extends SANs across local and wide area networks (LANs, WANs, and the Internet), providing location-independent data storage retrieval with distributed servers and arrays.

Iscsi Target Overview

In original SCSI protocol terminology, a target is a single connectible storage or output device uniquely identified on a SCSI bus. In iSCSI, in which the SCSI bus is emulated across an IP network, a target can be a dedicated physical device in a network-attached storage enclosure or an iSCSI software-configured logical device on a networked storage server. A target, like HBAs and initiators, is an endpoint in SCSI bus communication, passing command descriptor blocks (CDB) to request or provide storage transactions.

To provide access to the storage or output device, a target is configured with one or more logical unit numbers (LUNs). In iSCSI, LUNs appear as the target’s sequentially numbered disk drives, although targets typically have only one LUN. An initiator performs SCSI negotiation with a target to establish a connection to the LUN. The LUN responds as an emulated SCSI disk block device, which can be used in raw form or formatted with a client-supported file system.

iSCSI provides for LUN masking by using ACLs to restrict LUN accessibility to specific initiators. Except when shared access is intended, ACLs can ensure that only a designated client node can login to a specific target. On the target server, ACLs can be set at the TPG level to secure groups of LUNs, or set individually per LUN.

Iscsi Target Coniguration

Target server configuration demonstration

targetcli is both a command-line utility and an interactive shell in which to create, delete, and configure iSCSI target components. Target stack objects are grouped into a hierarchical tree of objects, allowing easy navigation and contextual configuration. Familiar Linux commands are used in this shell: cd, ls, pwd, and set.

The targetcli shell also supports TAB completion. Administrators can use TAB to either complete partially typed commands or view a list of acceptable key-words at the current location in a command. In this example, please follow along with the steps below using targetcli to configure a target server.

1. Install targetcli if needed.

# yum -y install targetcli

2. Run targetcli with no options to enter interactive mode.

# targetcli /> ls
Initial targetcli blank configuration

3. Create backing storage (backstores). There are several types of backing storage.

  • block - A block device defined on the server. A disk drive, disk partition, a logical volume, multipath device, any device files defined on the server that are of type b.
  • fileio - Create a file, of a specified size, in the filesystem of the server. This method is similar to using image files to be the storage for virtual machine disk images.
  • pscsi - Physical SCSI. Permits passthrough to a physical SCSI device connected to the server. This backstore type is not typically used.
  • ramdisk - Create a ramdisk device, of a specified size, in memory on the server. This type of storage will not store data persistently. When the server is rebooted, the ramdisk definition will return when the target is instantiated, but all data will have been lost.

Examples include using an existing logical volume, a disk partition, and a new file at a specified size. The backstores display as deactivated.

/> cd /backstores/
/backstores> block/ create block1 /dev/iSCSI_vg/disk1_lv
Created block storage object block1 using /dev/iSCSI_vg/disk1_lv.
/backstores> block/ create block2 /dev/vdb2
Created block storage object block2 using /dev/vdb2.
/backstores> fileio/ create file1 /root/disk1_file 100M
Created fileio file1 with size 104857600
/backstores> ls
o- backstores ............................................................ [...]
  o- block ................................................ [Storage Objects: 2]
  | o- block1 ....... [/dev/iSCSI_vg/disk1_lv (100.0MiB) write-thru deactivated]
  | o- block2 ...................... [/dev/vdb2 (1.0GiB) write-thru deactivated]
  o- fileio ............................................... [Storage Objects: 1]
  | o- file1 .............. [/root/disk1_file (100.0MiB) write-back deactivated]
  o- pscsi ................................................ [Storage Objects: 0]
  o- ramdisk .............................................. [Storage Objects: 0]

4. Create an IQN for the target. This step will also create a default TPG underneath the IQN.

/backstores> cd /iscsi/
/iscsi> create iqn.2014-06.com.example:remotedisk1
Created target iqn.2014-06.com.example:remotedisk1.
Created TPG 1.
/iscsi> ls
o- iscsi .......................................................... [Targets: 1]
  o- iqn.2014-06.com.example:remotedisk1 ............................. [TPGs: 1]
    o- tpg1 ............................................. [no-gen-acls, no-auth]
      o- acls ........................................................ [ACLs: 0]
      o- luns ........................................................ [LUNs: 0]
      o- portals .................................................. [Portals: 0]

An administrator can use create without specifying the IQN to create. targetcli will generate an IQN similar to the following: **iqn.2003-01.org.linuxiscsi.server0.x8664:sn.69b30d2cfd01. **Specifying the IQN value provides the ability for an administrator to use a meaningful namespace for their IQNs.

5. In the TPG, create an ACL for the client node to be used later. Because the global auto_add_mapped_luns parameter is set to true (default), any existing LUNs in the TPG are mapped to each ACL as it is created.

/iscsi> cd iqn.2014-06.com.example:remotedisk1/tpg1/
/iscsi/iqn.20...sk1/tpg1> acls/ create iqn.2014-06.com.example:desktop0
Created NODE ACL for iqn.2014-06.com.example:desktop0
/iscsi/iqn.20...sk1/tgp1> ls
o- tpg1 ................................................. [no-gen-acls, no-auth]
  o- acls ............................................................ [ACLs: 1]
  | o- iqn.2014-06.com.example:desktop0 ....................... [Mapped LUNs: 0]
  o- luns ............................................................ [LUNs: 0]
  o- portals ...................................................... [Portals: 0]

This ACL configures the target to only accept initiator connections from a client presenting iqn.2014-06.com.example:desktop0 as it’s initiator IQN, also known as the initiator name. 6. In this TPG, create a LUN for each existing backstores. This step also activates each backstore. Because acls exist for the TPG, they will be automatically assigned to each LUN created.

/iscsi/iqn.20...sk1/tgp1> luns/ create /backstores/block/block1
Created LUN 0.
Created LUN 0->0 mapping in node ACL iqn.2014-06.com.example:desktop0
/iscsi/iqn.20...sk1/tgp1> luns/ create /backstores/block/block2
Created LUN 1.
Created LUN 1->1 mapping in node ACL iqn.2014-06.com.example:desktop0
/iscsi/iqn.20...sk1/tgp1> luns/ create /backstores/fileio/file1
Created LUN 2.
Created LUN 2->2 mapping in node ACL iqn.2014-06.com.example:desktop0
/iscsi/iqn.20...sk1/tgp1> ls
o- tpg1 ................................................. [no-gen-acls, no-auth]
  o- acls ............................................................ [ACLs: 1]
  | o- iqn.2014-06.com.example:desktop0 ....................... [Mapped LUNs: 3]
  |   o- mapped_lun0 .................................. [lun0 block/block1 (rw)]
  |   o- mapped_lun1 .................................. [lun1 block/block2 (rw)]
  |   o- mapped_lun2 .................................. [lun2 fileio/file1 (rw)]
  o- luns ............................................................ [LUNs: 3]
  | o- lun0 ............................ [block/block1 (/dev/iSCSI_vg/disk1_lv)]
  | o- lun1 ......................................... [block/block2 (/dev/vdb2)]
  | o- lun2 .................................. [fileio/file1 (/root/disk1_file)]
  o- portals ...................................................... [Portals: 0]

Having three LUNs assigned to a target means that when the initiator connects to the target, it will receive three new SCSI devices.

7. Still inside the TPG, create a portal configuration to designate the listening IP address and ports. Create a portal using the system’s public network interface. Without specifying a TCP port to use, the portal creation will default to the standard iSCSI port (3260).

/iscsi/iqn.20...sk1/tgp1> portals/ create 172.25.0.11
Using default IP port 3260
Created network portal 172.25.0.11:3260
/iscsi/iqn.20...sk1/tgp1> ls
o- tpg1 ................................................. [no-gen-acls, no-auth]
  o- acls ............................................................ [ACLs: 1]
  | o- iqn.2014-06.com.example:desktop0 ....................... [Mapped LUNs: 3]
  |   o- mapped_lun0 .................................. [lun0 block/block1 (rw)]
  |   o- mapped_lun1 .................................. [lun1 block/block2 (rw)]
  |   o- mapped_lun2 .................................. [lun2 fileio/file1 (rw)]
  o- luns ............................................................ [LUNs: 3]
  | o- lun0 ............................ [block/block1 (/dev/iSCSI_vg/disk1_lv)]
  | o- lun1 ......................................... [block/block2 (/dev/vdb2)]
  | o- lun2 .................................. [fileio/file1 (/root/disk1_file)]
  o- portals ...................................................... [Portals: 1]
    o- 172.25.0.11:3260 ................................................... [OK]

If the IP is not specified with the portal creation, an IP of 0.0.0.0 will be used. This will permit connections on all network interfaces defined on the server.

8. View the entire configuration, then exit targetcli. targetcli will automatically save upon exit. The resulting persistent configuration file is stored in JavaScript Object Notation (JSON) format.

/iscsi/iqn.20...sk1/tgp1> cd /
/> ls
o- / ..................................................................... [...]
  o- backstores .......................................................... [...]
  | o- block .............................................. [Storage Objects: 2]
  | | o- block1 ....... [/dev/iSCSI_vg/disk1_lv (100.0MiB) write-thru activated]
  | | o- block2 ...................... [/dev/vdb2 (1.0GiB) write-thru activated]
  | o- fileio ............................................. [Storage Objects: 1]
  | | o- file1 .............. [/root/disk1_file (100.0MiB) write-back activated]
  | o- pscsi .............................................. [Storage Objects: 0]
  | o- ramdisk ............................................ [Storage Objects: 0]
  o- iscsi ........................................................ [Targets: 1]
  | o- iqn.2014-06.com.example:remotedisk1 ........................... [TPGs: 1]
  |   o- tpg1 ........................................... [no-gen-acls, no-auth]
  |     o- acls ...................................................... [ACLs: 1]
  |     | o- iqn.2014-06.com.example:desktop0 ................. [Mapped LUNs: 3]
  |     |   o- mapped_lun0 ............................ [lun0 block/block1 (rw)]
  |     |   o- mapped_lun1 ............................ [lun1 block/block2 (rw)]
  |     |   o- mapped_lun2 ............................ [lun2 fileio/file1 (rw)]
  |     o- luns ...................................................... [LUNs: 3]
  |     | o- lun0 ...................... [block/block1 (/dev/iSCSI_vg/disk1_lv)]
  |     | o- lun1 ................................... [block/block2 (/dev/vdb2)]
  |     | o- lun2 ............................ [fileio/file1 (/root/disk1_file)]
  |     o- portals ................................................ [Portals: 1]
  |       o- 172.25.0.11:3260 ............................................. [OK]
  o- loopback ..................................................... [Targets: 0]
/> exit
Global pref auto_save_on_exit=true
Last 10 configs saved in /etc/target/backup.
Configuration saved to /etc/target/saveconfig.json

9. Add a port exemption to the default firewall for port 3260, the standard iSCSI port.

# firewall-cmd --add-port=3260/tcp
# firewall-cmd --add-port=3260/tcp --permanent

10. Enable and start the target.service systemd unit. The target.service will recreate the target configuration from the json file at boot. If this step is skipped, any configured targets will work until the machine is rebooted; however, after a reboot, no targets will be offered by the server.

# systemctl enable target
# systemctl start target

Authentication

In addition to ACL node verification, password-based authentication can be implemented. Authentication can be required during the iSCSI discovery phase. Authentication can be unidirectional or bidirectional

CHAP authentication does not use strong encryption for the passing of credentials. While CHAP does offer an additional factor of authentication besides having a correctly configured initiator name, configured in an ACL, it should not be considered secure. If the security of iSCSI data is a concern, controlling the network side of the protocol is a better method to assure security. Providing a dedicated, isolated network, or VLANs to pass the iSCSI traffic will be a more secure implementation of the protocol.

Command-line mode

In the demonstration, targetcli was run in interactive mode, but targetcli can also be used to execute a series of commands via the command-line. In the following example, targetcli will be used to create a backstore device, an IQN, and activate a portal. The example, as written, will not present a usable target, but is meant to demonstrate several actions executed with targetcli. This method could be used to script target configuration. At the end of the list of commands, a saveconfig command is executed. Unlike the interactive use of targetcli, command-line mode will not save the configuration as a json file until the **saveconfig **command is used.

# targetcli /backstores/block create block1 /dev/vdb
Created block storage object block1 using /dev/vdb.
# targetcli /iscsi create iqn.2014-06.com.example:remotedisk1
Created target iqn.2014-06.com.example:remotedisk1.
Created TPG 1.
# targetcli /iscsi/iqn.2014-06.com.example:remotedisk1/tpg1/
portals create 172.25.0.11
Using default IP port 3260
Created network portal 172.25.0.11:3260.
# targetcli saveconfig
Last 10 configs saved in /etc/target/backup.
Configuration saved to /etc/target/saveconfig.json

iSCSI Initiator Introduction

In a CentOS/RHEL system, an iSCSI initiator is typically implemented in software and functions similar to a hardware iSCSI HBA to access targets from a remote storage server. Using a softwarebased iSCSI initiator requires connecting to an existing Ethernet network of sufficient bandwidth to carry the expected storage traffic.

iSCSI can also be implemented using a hardware initiator that includes the required protocols in a dedicated host bus adapter. iSCSI HBAs and TCP offload engines (TOE), which include the TCP network stack on an Ethernet NIC, move the processing of iSCSI or TCP overhead and Ethernet interrupts to hardware, easing the load on system CPUs.

Configuring an iSCSI client initiator requires installing the iscsi-initiator-utils package, which includes the iscsi and iscsid services and the /etc/iscsi/iscsid.conf and /etc/iscsi/initiatorname.iscsi configuration files.

As an iSCSI node, the client requires a unique IQN. The default /etc/iscsi/initiatorname.iscsi file contains a generated IQN. Administrators typically reset the IQN to their own domain and an appropriate client system string. Changing this file requires restarting the iscsid service.

# systemctl restart iscsid

The /etc/iscsi/iscsid.conf file contains default settings for node records created during new target discovery. Settings include iSCSI timeouts, retry parameters, and authentication usernames and passwords. Changing this file requires restarting the iscsi service.

# systemctl restart iscsi

To be able to discover targets, install the iscsi-initiator-utils package, then enable and start the iscsi service. Targets must be discovered before device connection and use. The discovery process stores target node information and settings in the /var/lib/iscsi/nodes directory, using defaults from /etc/iscsi/iscsid.conf. Since the same target can exist on multiple portals, node records are stored for each portal. Perform discovery with the following command:

# iscsiadm -m discovery -t sendtargets -p target_server[:port]
172.25.X.11:3260,1 iqn.2014-06.com.example:serverX

In discovery mode, the sendtargets request returns only targets with access configured for this initiator. The port number can be omitted when the target server is configured on default port 3260. Upon discovery, a node record is written to /var/lib/iscsi/nodes and used for subsequent logins. To use the listed target, log in using the following command:

# iscsiadm -m node -T iqn.2014-06.com.example:serverX [-p target_server[:port]] -l

Specifying the portal is optional. If the target exists on multiple portals (e.g., in a multipathed, redundant server configuration), performing a login without specifying a portal will connect to every portal node that accepts this target name.

Once discovered, obtain information about targets with the iscsiadm command. Use the option -P N to set the command detail level, with 0 specifying the least verbose output.

  • iscsiadm -m discovery [-P 0|1]: Show information about discovered targets.
  • iscsiadm -m node [-P 0|1]: Show information about known targets.
  • iscsiadm -m session [-P 0|1|2|3]: Show information about active sessions

To discontinue using a target, use iscsiadm to log out temporarily. By design, node records remain after logout and are used to automatically log into targets upon system reboot or iscsi service restart. Log out of a target using the following command (notice the similarity to login):

# iscsiadm -m node -T iqn.2012-04.com.example:example [-p target_server[:port]] -u

If a portal is not specified, the target logs out of all relevant portals. To log into the target again, repeating discovery is not necessary since the node records already exist. Permanently logging out of a target requires deleting the node records so that manual or automatic login cannot reoccur without performing another discovery. Not specifying a portal removes the target node records for all relevant portals. Delete the node record permanently by using the following command (notice again the command similarity):

# iscsiadm -m node -T iqn.2012-04.com.example:example [-p target_server[:port]] -o delete