iSCSI or Fibre Channel — Which One Is Right for Your Infrastructure?
I once worked at a company running a NetApp storage system, and the first question that always came up when connecting a Linux server to SAN was: iSCSI or Fibre Channel (FC)? It’s not a matter of “which one is better” — it’s “which one fits your existing infrastructure.”
FC latency can drop below 1ms with extremely stable throughput — but it requires dedicated HBA cards (~$300–500 each), dedicated FC switches, and upfront costs that can easily run into the tens of thousands of dollars. iSCSI runs over your existing Ethernet/IP network with no special hardware needed. With 10GbE, throughput is sufficient for most mid-sized enterprise workloads. For SMB environments or dev/test setups, the practical choice is fairly obvious.
iscsiadm vs Cockpit vs iSNS: What Should You Use?
On CentOS/RHEL, there are a few ways to manage the iSCSI initiator — I’ve tried all three, and here’s my honest take:
- iscsiadm (CLI): The official tool, full-featured, and scriptable — this is what you want in production. The syntax is a bit verbose, but once you get used to it, it’s not a problem.
- Cockpit + iSCSI module: A browser-based GUI, convenient for admins who aren’t comfortable with the CLI — but offers less control and is harder to debug when things go wrong.
- iSNS (Internet Storage Name Service): Like DNS for iSCSI, automatically discovers targets in large storage environments — requires a dedicated iSNS server, which is overkill if you only have a few dozen LUNs.
sendtargets vs Static Node vs iSNS
This part rarely gets covered, but it’s important to understand when setting things up:
- sendtargets: Queries the iSCSI portal directly and the server returns a list of available targets — simple and practical when you know the portal address. This is what I use 90% of the time.
- Static node: Configures the target IQN directly without discovery — useful when you know the exact target and want tighter control.
- iSNS: Auto-discovers targets in large enterprise environments — requires a dedicated iSNS server, suited for environments with hundreds of targets.
In practice, 90% of the time you only need sendtargets + iscsiadm — no dependency on auxiliary servers, easy to script, and much simpler to debug.
Hands-On Deployment: From Installation to Mounting
Step 1: Install the iSCSI Initiator
CentOS Stream 9 uses the iscsi-initiator-utils package:
sudo dnf install -y iscsi-initiator-utils
sudo systemctl enable --now iscsid
Check your initiator’s IQN (iSCSI Qualified Name) — this is your server’s unique identifier in the storage system:
cat /etc/iscsi/initiatorname.iscsi
# Output: InitiatorName=iqn.1994-05.com.redhat:xxxxxxxx
The IQN is unique per machine. If you clone a VM without changing the IQN, it will conflict with any active sessions — a mistake I ran into during a server migration.
Step 2: Configure CHAP Authentication
This step often gets skipped with the reasoning that “it’s an internal storage network, why bother with auth?” But iSCSI has no encryption by default — traffic flows in plaintext. CHAP at least provides authentication, so you’re not leaving the target open to your entire network segment:
sudo vi /etc/iscsi/iscsid.conf
Find and update the following lines:
# Enable CHAP
node.session.auth.authmethod = CHAP
# Authentication credentials (ask your storage admin)
node.session.auth.username = your_username
node.session.auth.password = your_password
# If mutual CHAP is needed (target authenticates back to initiator)
node.session.auth.username_in = target_username
node.session.auth.password_in = target_password
Step 3: Discovery — Finding iSCSI Targets
Use sendtargets to discover targets (replace 192.168.1.100 with your iSCSI portal IP):
sudo iscsiadm -m discovery -t sendtargets -p 192.168.1.100:3260
The output will list the available targets:
192.168.1.100:3260,1 iqn.2024-01.com.company:storage.lun01
192.168.1.100:3260,1 iqn.2024-01.com.company:storage.lun02
Step 4: Log In to the Target
Log in to all discovered targets:
sudo iscsiadm -m node --loginall=automatic
Or log in to a specific target:
sudo iscsiadm -m node \
--targetname "iqn.2024-01.com.company:storage.lun01" \
--portal "192.168.1.100:3260" \
--login
Check active sessions:
sudo iscsiadm -m session -P 1
Step 5: Confirm the Disk Appears
After a successful login, the kernel recognizes the LUN as a regular SCSI device — no reboot required:
lsblk
# or
sudo fdisk -l | grep "Disk /dev/sd"
If you see additional /dev/sdb, /dev/sdc… entries appearing — those are your iSCSI LUNs.
Step 6: Format and Mount
# Format with XFS (recommended for storage workloads)
sudo mkfs.xfs /dev/sdb
# Create mount point
sudo mkdir -p /mnt/iscsi-data
# Test mount
sudo mount /dev/sdb /mnt/iscsi-data
# Verify
df -hT /mnt/iscsi-data
Step 7: Auto-Mount at Boot — Don’t Skip This Step
iSCSI mounts differ from local disks in one critical way: the network must be ready before mounting. Without the _netdev option in /etc/fstab, your server can get stuck at the boot screen waiting for a mount timeout — I’ve seen servers add 90 extra seconds to every boot just because of this oversight:
sudo blkid /dev/sdb # Get UUID
sudo vi /etc/fstab
# Add this line (replace with actual UUID):
UUID=xxxx-xxxx-xxxx /mnt/iscsi-data xfs defaults,_netdev,nofail 0 0
The nofail option prevents the server from getting stuck at boot if the storage target is unavailable. Enable the related services:
sudo systemctl enable iscsi iscsid
sudo systemctl enable remote-fs.target
Real-World Tips — Lessons from an Emergency Migration
When CentOS 8 reached EOL, I had to migrate 5 servers to Rocky Linux in one week — and iSCSI was the most stressful part because storage downtime directly impacted production databases. Here’s what I learned from that experience:
- Document IQNs before migrating: The IQN on the old machine differs from the new one. If the storage admin has configured ACLs by IQN, you need to notify them to update — otherwise you can log in successfully but see no LUNs, and waste hours debugging.
- Use multipath whenever possible: The
device-mapper-multipathpackage allows multiple paths to the same LUN — with automatic failover if one network link goes down. For production databases, this is less of a “nice to have” and more of a necessity. - Verify MTU consistency: Jumbo Frames (MTU 9000) can significantly improve iSCSI throughput, but MTU must be consistent across the entire path from NIC → switch → storage array. An MTU mismatch causes packet fragmentation, reducing throughput by 30–40% with nothing unusual appearing in the logs — the kind of problem that can take hours to track down.
- Dedicate a separate network for storage traffic: Don’t share a NIC with management traffic. At minimum, use a dedicated VLAN — to avoid situations where a backup job saturates the network and starves the database’s storage.
Troubleshooting Common Issues
Login Failed — Authentication Error
# Update CHAP settings directly on the node
sudo iscsiadm -m node \
--targetname "iqn.2024-01.com.company:storage.lun01" \
--portal "192.168.1.100:3260" \
-o update \
-n node.session.auth.authmethod -v CHAP
sudo iscsiadm -m node \
--targetname "iqn.2024-01.com.company:storage.lun01" \
--portal "192.168.1.100:3260" \
-o update \
-n node.session.auth.username -v your_user \
-n node.session.auth.password -v your_pass
Target Doesn’t Reconnect After Reboot
# Set node startup mode to automatic
sudo iscsiadm -m node -o update -n node.startup -v automatic
# Verify services are running
sudo systemctl status iscsid iscsi
Safe Logout During Maintenance
# Unmount first — IMPORTANT, do not skip this step
sudo umount /mnt/iscsi-data
sudo sync
# Then logout
sudo iscsiadm -m node --logoutall=all
iSCSI on CentOS Stream 9 is production-ready and stable enough for database storage — I’m running it in a live environment with dozens of LUNs without any issues. Setups usually fail not because the tooling is complex, but because three things tend to get overlooked: CHAP authentication, multipath for high availability, and _netdev in fstab. Get those three right, and the rest goes fairly smoothly.

