Prerequisites#
Before you start, ensure you have:
- RHEL/CentOS 7/8/9 or Fedora 38+ (tested on RHEL 9.3)
- Root/sudo access to the target server
- At least one additional storage device (physical or virtual) for LVM (do NOT use your root disk!)
- Network connectivity between the target and initiator (same subnet recommended)
- Basic Linux command-line knowledge
Table of Contents#
- Introduction
- Prerequisites
- Step 1: Install Required Packages
- Step 2: Set Up LVM for iSCSI LUNs
- Step 3: Configure iSCSI Target with Targetcli
- Step 4: Configure Firewall and SELinux
- Step 5: Test iSCSI LUN from an Initiator
- Step 6: Troubleshooting Common Issues
- Step 7: Resizing iSCSI LUNs (Optional)
- Conclusion
- References
Step 1: Install Required Packages#
First, update your system and install packages for LVM and iSCSI target management:
sudo dnf update -y
sudo dnf install -y lvm2 targetclilvm2: Provides LVM utilities (e.g.,pvcreate,vgcreate,lvcreate).targetcli: A command-line tool for configuring iSCSI targets on RHEL/CentOS/Fedora.
Verify the installation:
rpm -q lvm2 targetcliExpected Output:
lvm2-2.03.11-5.el9.x86_64
targetcli-2.1.53-1.el9.noarch
Step 2: Set Up LVM for iSCSI LUNs#
LVM uses three layers to manage storage:
- Physical Volumes (PVs): Raw storage devices (e.g.,
/dev/sdb). - Volume Groups (VGs): Pools of PVs that act as a single storage resource.
- Logical Volumes (LVs): "Partitions" of VGs that become iSCSI LUNs.
2.1 Identify Storage Devices#
First, identify the storage device you’ll use for LVM. Do NOT use your root disk (e.g., /dev/sda)—use a separate physical or virtual disk.
List available disks with:
lsblk -d -o NAME,SIZE,TYPEExample Output:
NAME SIZE TYPE
sda 20G disk # Root disk (DO NOT USE!)
sdb 50G disk # New storage device for LVM
In this example, we’ll use /dev/sdb.
2.2 Create Physical Volumes (PVs)#
Initialize the disk as a Physical Volume (PV) for LVM:
sudo pvcreate /dev/sdbExpected Output:
Physical volume "/dev/sdb" successfully created.
Verify the PV:
sudo pvsOutput:
PV VG Fmt Attr PSize PFree
/dev/sdb lvm2 --- 50.00g 50.00g
2.3 Create Volume Groups (VGs)#
Combine PVs into a Volume Group (VG). A VG acts as a pool of storage for LVs.
Create a VG named vg_iscsi using /dev/sdb:
sudo vgcreate vg_iscsi /dev/sdbExpected Output:
Volume group "vg_iscsi" successfully created
Verify the VG:
sudo vgsOutput:
VG #PV #LV #SN Attr VSize VFree
vg_iscsi 1 0 0 wz--n- 50.00g 50.00g
2.4 Create Logical Volumes (LVs)#
Create a Logical Volume (LV) from the VG—this will become your iSCSI LUN.
Create an LV named lv_iscsi1 with 20GB of storage:
sudo lvcreate -L 20G -n lv_iscsi1 vg_iscsiOr use 100% of the VG’s free space (maximize LUN size):
sudo lvcreate -l +100%FREE -n lv_iscsi1 vg_iscsiExpected Output:
Logical volume "lv_iscsi1" created.
Verify the LV:
sudo lvsOutput:
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv_iscsi1 vg_iscsi -wi-a----- 20.00g
Step 3: Configure iSCSI Target with Targetcli#
targetcli is the official tool for managing iSCSI targets on RHEL/CentOS/Fedora. It uses a tree-based hierarchy to configure:
- Backstores: Storage sources (e.g., LVM LVs).
- Targets: IQN (unique identifier) for the iSCSI service.
- Portals: IP/port the target listens on.
- LUNs: Mapping of backstores to targets.
- ACLs: Access control lists (for CHAP authentication).
3.1 Launch Targetcli#
Start the targetcli shell:
sudo targetcliYou’ll see a prompt like:
targetcli shell version 2.1.53
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.
/>
3.2 Create a Block Backstore from LVM LV#
iSCSI targets use backstores to map physical storage to LUNs. For LVM, we’ll create a block backstore (since LVs are block devices).
In the targetcli shell:
- Navigate to the block backstores directory:
cd /backstores/block - Create a backstore using your LVM LV:
create name=iscsi_lun1 dev=/dev/vg_iscsi/lv_iscsi1
name=iscsi_lun1: A human-readable name for the backstore.dev=/dev/vg_iscsi/lv_iscsi1: Path to the LVM LV you created earlier.
Verify the backstore:
ls /backstores/blockOutput:
iscsi_lun1 (source: /dev/vg_iscsi/lv_iscsi1)
3.3 Create an iSCSI Target IQN#
An IQN (iSCSI Qualified Name) uniquely identifies the iSCSI target. The format is:
iqn.yyyy-mm.<reverse-domain>:<identifier>
iqn: Mandatory prefix for iSCSI names.yyyy-mm: Year/month the domain was registered.reverse-domain: Your domain name in reverse (e.g.,com.exampleforexample.com).identifier: A unique name for the target (e.g.,iscsi-target1).
Create the target IQN:
cd /targets
create iqn.2024-05.com.example:iscsi-target1Replace 2024-05.com.example:iscsi-target1 with your own IQN.
Verify the target:
ls /targetsOutput:
iqn.2024-05.com.example:iscsi-target1
3.4 Configure iSCSI Portal#
A portal defines the IP address and port the target listens on. By default, iSCSI uses port 3260.
Create a portal to listen on all interfaces (0.0.0.0):
cd /targets/iqn.2024-05.com.example:iscsi-target1/portals
create 0.0.0.0:3260Verify the portal:
ls /targets/iqn.2024-05.com.example:iscsi-target1/portalsOutput:
0.0.0.0:3260
3.5 Associate LUN with Target#
Now, map the block backstore (your LVM LV) to the target as a LUN (Logical Unit Number). LUNs are numbered sequentially (starting from 0).
In the targetcli shell:
- Navigate to the target’s LUNs directory:
cd /targets/iqn.2024-05.com.example:iscsi-target1/luns - Create a LUN from the backstore:
create /backstores/block/iscsi_lun1
Verify the LUN:
ls /targets/iqn.2024-05.com.example:iscsi-target1/lunsOutput:
0 (backstore: iscsi_lun1)
3.6 Optional: Set Up CHAP Authentication#
CHAP (Challenge-Handshake Authentication Protocol) adds security by requiring initiators to authenticate before accessing the target.
Step 1: Create an ACL for the Initiator#
First, you’ll need the initiator’s IQN (we’ll configure this in Step 5.2). For now, use a placeholder like iqn.2024-05.com.example:iscsi-initiator1.
In the targetcli shell:
cd /targets/iqn.2024-05.com.example:iscsi-target1/acls
create iqn.2024-05.com.example:iscsi-initiator1Step 2: Set CHAP Credentials#
Configure CHAP credentials for the initiator:
cd iqn.2024-05.com.example:iscsi-initiator1
set auth userid=initiator_user password=StrongPass123!userid: Username the initiator will use.password: A strong password (minimum 12 characters, mix of letters/numbers/symbols).
Step 3: Mutual CHAP (Optional)#
For mutual authentication (target authenticates to the initiator), add:
set auth mutual_userid=target_user mutual_password=AnotherStrongPass!Verify the ACL and CHAP settings:
ls /targets/iqn.2024-05.com.example:iscsi-target1/aclsOutput:
iqn.2024-05.com.example:iscsi-initiator1 (userid=initiator_user, password=StrongPass123!)
3.7 Save and Persist Configuration#
By default, targetcli does not save changes across reboots. Use the saveconfig command to write your configuration to /etc/target/saveconfig.json:
saveconfigEnable and start the target service to load the configuration on boot:
systemctl enable --now targetVerify the service status:
systemctl status targetExpected Output:
● target.service - Kernel Target Manager
Loaded: loaded (/usr/lib/systemd/system/target.service; enabled; preset: disabled)
Active: active (running) since Tue 2024-05-21 14:30:00 UTC; 1min ago
Step 4: Configure Firewall and SELinux#
Firewall Setup#
The iSCSI target uses TCP port 3260. Allow this port through the firewall (permanent):
sudo firewall-cmd --add-service=iscsi-target --permanent
sudo firewall-cmd --reloadVerify the rule:
sudo firewall-cmd --list-services --permanentOutput:
cockpit dhcpv6-client iscsi-target ssh
SELinux Configuration#
SELinux is enabled by default on RHEL/CentOS. For most setups, the default policies work with iSCSI targets. If you encounter issues (e.g., initiators can’t access LUNs), check the audit log:
sudo ausearch -m AVC -ts recentFix SELinux Denials (If Needed)#
If SELinux blocks access to the LVM LV, add the correct context:
sudo semanage fcontext -a -t iscsi_target_var_lib_t "/dev/vg_iscsi/lv_iscsi1"
sudo restorecon -v /dev/vg_iscsi/lv_iscsi1For temporary testing, set SELinux to permissive mode (not recommended for production):
sudo setenforce 0Step 5: Test iSCSI LUN from an Initiator#
Now, we’ll configure an initiator (a RHEL/CentOS/Fedora client) to connect to the target and use the LUN.
5.1 Install Initiator Packages#
On the initiator, install the iscsi-initiator-utils package:
sudo dnf install -y iscsi-initiator-utils5.2 Configure Initiator IQN#
The initiator needs a unique IQN. Edit /etc/iscsi/initiatorname.iscsi:
sudo nano /etc/iscsi/initiatorname.iscsiReplace the existing line with your IQN (e.g., iqn.2024-05.com.example:iscsi-initiator1):
InitiatorName=iqn.2024-05.com.example:iscsi-initiator1
Save the file and restart the iscsid service:
sudo systemctl restart iscsid
sudo systemctl enable iscsid5.3 Discover and Log In to Target#
Step 1: Discover the Target#
Use the target’s IP address (e.g., 192.168.1.100) to discover the iSCSI target:
sudo iscsiadm -m discovery -t st -p 192.168.1.100:3260-m discovery: Enter discovery mode.-t st: Use SendTarget discovery (standard for iSCSI).-p 192.168.1.100:3260: Target IP and port.
Expected Output:
192.168.1.100:3260,1 iqn.2024-05.com.example:iscsi-target1
Step 2: Log In to the Target#
Log in to the target using its IQN:
sudo iscsiadm -m node -T iqn.2024-05.com.example:iscsi-target1 -p 192.168.1.100:3260 -l-m node: Manage iSCSI nodes (targets).-T: Specify the target IQN.-l: Login to the target.
Step 3: Configure CHAP Credentials (If Enabled)#
If you set up CHAP in Step 3.6, edit /etc/iscsi/iscsid.conf to add credentials:
sudo nano /etc/iscsi/iscsid.confAdd:
# CHAP credentials for initiator -> target
node.session.auth.authmethod = CHAP
node.session.auth.username = initiator_user
node.session.auth.password = StrongPass123!
# Mutual CHAP (target -> initiator, optional)
node.session.auth.username_in = target_user
node.session.auth.password_in = AnotherStrongPass!Save and restart iscsid:
sudo systemctl restart iscsid5.4 Verify LUN Detection#
List active iSCSI sessions:
sudo iscsiadm -m sessionOutput:
tcp: [1] 192.168.1.100:3260,1 iqn.2024-05.com.example:iscsi-target1
Verify the LUN is detected as a block device:
lsblk -d -o NAME,SIZE,TYPEExample Output:
NAME SIZE TYPE
sda 20G disk # Root disk
sdb 20G disk # iSCSI LUN from target!
5.5 Format and Mount the LUN#
Step 1: Format the LUN#
Format the LUN with XFS (recommended for RHEL/CentOS):
sudo mkfs.xfs /dev/sdbOr use ext4:
sudo mkfs.ext4 /dev/sdbStep 2: Create a Mount Point#
Create a directory to mount the LUN:
sudo mkdir -p /mnt/iscsiStep 3: Mount the LUN#
Mount the LUN to /mnt/iscsi:
sudo mount /dev/sdb /mnt/iscsiStep 4: Test Write Access#
Create a test file to verify the LUN works:
sudo touch /mnt/iscsi/test.txt
sudo echo "Hello from iSCSI!" > /mnt/iscsi/test.txt
cat /mnt/iscsi/test.txtExpected Output:
Hello from iSCSI!
Step 5: Mount on Boot (Optional)#
To mount the LUN automatically on boot, add an entry to /etc/fstab:
sudo nano /etc/fstabAdd:
/dev/sdb /mnt/iscsi xfs defaults,_netdev 0 0
_netdev: Ensures the mount waits for the network to be active (critical for iSCSI).
Test the fstab entry:
sudo umount /mnt/iscsi
sudo mount /mnt/iscsiStep 6: Troubleshooting Common Issues#
6.1 Firewall Blocking iSCSI Traffic#
Symptom: Initiator can’t discover the target.
Fix: Re-add the iSCSI target firewall rule:
sudo firewall-cmd --add-service=iscsi-target --permanent
sudo firewall-cmd --reload6.2 SELinux Denials#
Symptom: Initiator can’t mount the LUN, error: Permission denied.
Fix: Restore the SELinux context for the LV:
sudo restorecon -v /dev/vg_iscsi/lv_iscsi16.3 Target Not Discovered#
Symptom: iscsiadm -m discovery returns no results.
Check:
- Is the
targetservice running?sudo systemctl status target - Is the target IP correct? Ping the target from the initiator:
ping 192.168.1.100 - Is the portal configured correctly?
sudo targetcli ls /targets/iqn.2024-05.com.example:iscsi-target1/portals
6.4 LUN Not Visible After Login#
Symptom: lsblk doesn’t show the LUN.
Fix: Rescan the iSCSI bus:
sudo iscsiadm -m node -R6.5 CHAP Authentication Failures#
Symptom: Initiator can’t log in, error: authentication failed.
Check:
- Did you set the correct credentials in
/etc/iscsi/iscsid.conf? - Are the credentials the same on the target? Verify with:
sudo targetcli ls /targets/iqn.2024-05.com.example:iscsi-target1/acls
Step 7: Resizing iSCSI LUNs (Optional)#
One of the biggest benefits of using LVM with iSCSI is dynamic resizing. Here’s how to extend a LUN:
On the Target Server#
- Extend the LVM LV (add 10GB):
Or use all free space in the VG:sudo lvresize -L +10G /dev/vg_iscsi/lv_iscsi1sudo lvresize -l +100%FREE /dev/vg_iscsi/lv_iscsi1 - Verify the new size:
sudo lvs /dev/vg_iscsi/lv_iscsi1
On the Initiator#
- Rescan the iSCSI bus:
sudo iscsiadm -m node -R - Resize the filesystem:
- For XFS:
sudo xfs_growfs /mnt/iscsi - For ext4:
sudo resize2fs /dev/sdb
- For XFS:
- Verify the new size:
df -h /mnt/iscsi
Conclusion#
You’ve successfully set up an iSCSI target server using LVM on RHEL/CentOS/Fedora! By combining iSCSI with LVM, you’ve created a scalable, flexible storage solution that:
- Lets you dynamically resize LUNs
- Aggregates multiple disks into a single storage pool
- Supports snapshots for backups
- Secures access with CHAP authentication
This setup is ideal for:
- Virtualization (e.g., VM storage for KVM/Xen)
- Network-attached storage (NAS)
- Backup targets
- Enterprise applications requiring block storage
References#
- RHEL iSCSI Target Documentation: Configuring iSCSI Targets
- LVM Administration Guide: Logical Volume Manager
- Targetcli Man Page: targetcli(8)
- iSCSI Initiator Documentation: Configuring iSCSI Initiators
- FirewallD Documentation: firewall-cmd(1)
- SELinux Documentation: SELinux User’s and Administrator’s Guide
Let me know if you have any questions or need help troubleshooting!