Linux iSCSI Target with targetcli (LIO): Setup Guide - 夜莺博客

Linux iSCSI Target with targetcli (LIO): Setup Guide

The Linux kernel's LIO target subsystem turns any Linux server into a SAN storage array, exporting local disks, LVM volumes or plain files to iSCSI initiators on the network. The administration shell for LIO is targetcli, a tree-based CLI with tab completion that walks you through backstores, targets, portals, LUNs and ACLs. Whether you are building a small lab SAN, a backup target for VMware ESXi, or a shared disk for a cluster, the workflow is the same. This guide follows Red Hat's documented procedure step by step and ends with the initiator-side commands that verify the whole path.

How iSCSI and LIO Fit Together

iSCSI carries SCSI commands over TCP. The server side is called the target; the client is the initiator. A target is identified by an IQN — an iSCSI Qualified Name such as iqn.2006-04.com.example:444 — and inside each target there are one or more TPGs (target portal groups). A TPG holds the network portals the target listens on, the LUNs it exports, and the ACLs that decide which initiators may log in.

LIO is the kernel's in-tree target implementation, and it is not iSCSI-specific: the same codebase backs Fibre Channel, FCoE and vhost-scsi targets. That matters because it means an exported LUN is a first-class kernel block device with normal performance characteristics, not a user-space proxy. targetcli is only a front end: every command you type is validated by a Python library and written into the kernel configfs interface under /sys/kernel/config/target. Understanding that layering explains most targetcli error messages, which are usually configfs complaining about a constraint rather than the CLI being broken.

Install and Start the Target Service

# dnf install targetcli
# systemctl enable --now target

On Debian and Ubuntu the package is targetcli-fb and the unit is rtslib-fb-targetctl on older releases; if the unit name does not exist, the configfs filesystem simply needs to be mounted and targetcli works without a daemon at all. Check that the module loaded and the port is bound before going further:

# targetcli ls
# ss -tlnp | grep 3260

Step 1: Create a Backstore

A backstore defines how the exported LUN's data is stored. The two most common types are fileio (a regular file as a disk image) and block (a real block device such as /dev/sdb, an LVM volume or a RAID device):

# targetcli
/> backstores/fileio
/backstores/fileio> create file1 /tmp/disk1.img 200M write_back=false

/> backstores/block
/backstores/block> create name=block_backend dev=/dev/sdb

Use write_back=false for fileio unless you accept the higher data-loss risk of the file system cache. For production block storage, the block backstore over an LVM or hardware RAID device is the safer choice.

Three backstore types are worth knowing about. fileio stores the LUN as one file and lets you snapshot, copy and back it up with ordinary file tools — ideal for labs and test clusters. block exports a real block device with no extra layer, giving the lowest latency and the most predictable behaviour under power loss. ramdisk keeps the LUN in memory and is purely for benchmarking the transport without touching a disk. You can see all three plus their current configuration with ls /backstores.

Two attributes on a fileio backstore decide how it behaves in production. write_back=false forces every write through to stable storage before the SCSI command completes, which is what makes an exported file behave like a real disk for databases and clustered filesystems. Leaving write-back enabled buys throughput at the cost of losing acknowledged writes on a host crash. emulate_fua_write and emulate_tpu, visible via ls on the backstore, control whether the target advertises FUA and TPU support to the initiator; leave them at defaults unless an application specifically needs them.

Step 2: Create the iSCSI Target and LUN

/> iscsi/
/iscsi> create iqn.2006-04.com.example:444
/iscsi> cd iqn.2006-04.com.example:444/tpg1
/iscsi/iqn.20...:444/tpg1> luns/ create /backstores/block/block_backend
/iscsi/iqn.20...:444/tpg1> luns/ create /backstores/fileio/file1

The create command auto-generates an IQN if you omit it, and every target automatically gets a target portal group (tpg1) listening on 0.0.0.0:3260.

LUN numbering starts at zero and increments automatically, so the block backstore above becomes LUN 0 and the fileio backstore becomes LUN 1. That ordering matters, because many initiators and hypervisors boot from LUN 0. If you need a specific mapping, create the LUNs in the order you want them assigned, or use the explicit form luns/ create /backstores/block/block_backend lun=5.

Step 3: Create Portals (if Needed)

By default LIO listens on all addresses on the standard iSCSI port. To bind a specific IP or add high-availability portals:

/iscsi/iqn.20...:444/tpg1> portals/ create 192.168.1.10

Creating a portal on an explicit address does not remove the default wildcard portal created with the target. For a hardened production target, delete the 0.0.0.0:3260 portal so the target cannot accidentally be discovered on a management or storage network you did not intend to expose:

/iscsi/iqn.20...:444/tpg1> portals/ delete 0.0.0.0 ip_port=3260
/iscsi/iqn.20...:444/tpg1> portals/ create 192.168.1.10
/iscsi/iqn.20...:444/tpg1> portals/ create 192.168.1.11

Two portals on two subnets is the standard setup for multipath: the initiator sees the same LUN through two independent paths, and the device-mapper multipath layer keeps one active while the other stands by or round-robins.

Step 4: Allow Initiators with ACLs

Find the initiator's IQN (it lives in /etc/iscsi/initiatorname.iscsi on the client) and create an ACL so that initiator may log in. targetcli maps the LUNs to the ACL automatically:

/iscsi/iqn.20...:444/tpg1> acls/ create iqn.2005-03.org.open-iscsi:SERIAL

To export a read-only LUN to a specific initiator, disable auto-mapping first, then create the mapped LUN with write_protect=1:

/> set global auto_add_mapped_luns=false
/iscsi/iqn.20...:444/tpg1/acls/iqn.2005-03.org.open-iscsi:SERIAL> create mapped_lun=1 tpg_lun_or_backstore=/backstores/block/block2 write_protect=1

With auto-mapping disabled you must create a mapped LUN for every initiator and every LUN it is allowed to see — forget one and the initiator logs in successfully but sees no disks, which is one of the most common "the target is broken" reports. Disabling auto-mapping is nevertheless the right default for anything multi-tenant, because it prevents a newly added LUN from silently appearing on every ACL in the target.

CHAP Authentication

An ACL restricts who may log in by IQN, but an IQN is trivially spoofable. For any target reachable from an untrusted segment, add CHAP, either one-way or mutual:

/> iscsi/iqn.2006-04.com.example:444/tpg1
/iscsi/iqn.20...:444/tpg1> set attribute authentication=1
/iscsi/iqn.20...:444/tpg1> set attribute generate_node_acls=1
/iscsi/iqn.20...:444/tpg1> set attribute demo_mode_write_protect=0
/iscsi/iqn.20...:444/tpg1> set auth userid=initiatoruser
/iscsi/iqn.20...:444/tpg1> set auth password=initiatorpassword
/iscsi/iqn.20...:444/tpg1> set auth mutual_userid=targetuser
/iscsi/iqn.20...:444/tpg1> set auth mutual_password=targetpassword

Note that enabling authentication with generate_node_acls=1 makes the TPG accept any initiator that presents valid credentials, which is normally what you want when CHAP is the actual control. If you prefer to require both a valid IQN ACL and CHAP, leave generate_node_acls at 0 and set the same credentials per ACL instead. The inverse mistake — setting demo_mode_write_protect=1 and leaving it there — makes every LUN read-only, which is a fine safety switch during bring-up and a confusing outage afterwards.

Save the Configuration and Verify

/> saveconfig
/> ls
# ss -tlnp | grep 3260

saveconfig writes /etc/target/saveconfig.json so the target survives reboots. From the initiator host, discover and log in:

# iscsiadm -m discovery -t sendtargets -p 192.168.1.10
# iscsiadm -m node -L all
# lsblk

A healthy discovery prints one line per target portal, and a successful login leaves a new /dev/sdX in lsblk. Not every LUN is a disk you can mount: the target may also export a changers or tape LUN, which appears in /dev as an sg device or under /dev/tape/by-id rather than as a block device.

Understanding what discovery just told the initiator is worth a minute. The initiator writes each discovered portal and target into /var/lib/iscsi/nodes/, so iscsiadm -m node -L all is really "log in to everything I already recorded". To stop a guest from reconnecting to a target you are decommissioning, log out with iscsiadm -m node -T iqn.2006-04.com.example:444 -u and then iscsiadm -m node -T iqn.2006-04.com.example:444 -o delete so the stale record does not survive into the next reboot.

Using the LUN on the Initiator

Once the disk is visible, treat it exactly like a local disk — but remember that a shared LUN must be handed to a cluster filesystem or a volume manager with proper locking, never mounted by two hosts with a plain mount:

# parted /dev/sdb mklabel gpt
# parted -s /dev/sdb mkpart primary ext4 0% 100%
# mkfs.ext4 /dev/sdb1
# mkdir -p /mnt/iscsi
# mount /dev/sdb1 /mnt/iscsi
# blkid /dev/sdb1

For the single-host case add the resulting UUID to /etc/fstab with the _netdev option so the mount waits for networking to be up and never blocks boot on a target that is rebooting. For the multi-host case, stop here and put a cluster filesystem such as GFS2 or OCFS2 on top, or an LVM volume group that only one node activates at a time; ext4 mounted from two hosts simultaneously will corrupt its own journal.

Performance Notes

  • Use the block backstore for production. It removes a file-system layer between the initiator's writes and the platter or SSD, which is worth both latency and CPU.
  • Never put a backstore file on a filesystem that is itself exported. Recursive dependencies produce hangs that are hard to attribute.
  • Jumbo frames help iSCSI more than most protocols because SCSI payloads are large and the per-packet overhead is significant; raise MTU on both the target portal network and the initiator side together.
  • Use a separate VLAN or subnet for storage so a backup job or a broadcast storm cannot add latency to SCSI I/O.
  • Enable multipath for redundancy, not for speed. A single iSCSI session is usually close to line rate already; two paths mainly protect against a NIC, switch or cable failure.

Troubleshooting Checklist

  • Discovery returns nothing — check ss -tlnp | grep 3260 on the target, then the firewall (firewall-cmd --add-service=iscsi-target --permanent), then whether the portal is bound to an address the initiator can reach.
  • Login succeeds but lsblk shows no new disk — almost always a missing mapped LUN because auto-mapping is off, or an ACL for the wrong IQN.
  • The disk disappears after the initiator reboots — the node record was never saved, or iscsid is not enabled with systemctl enable --now iscsid.
  • Writes are extremely slow — a fileio backstore with write-back disabled on a slow or nearly full filesystem, or an MTU mismatch causing fragmentation.
  • The target will not start after a change — /etc/target/saveconfig.json is malformed. Restore the previous copy and re-apply changes incrementally with targetcli so each step is validated.

Cleanup

To tear down a lab target, remove objects from the leaves upward, because configfs refuses to delete something that still has children:

/> iscsi/iqn.2006-04.com.example:444/tpg1/ delete
/> backstores/fileio/ delete file1
/> backstores/block/ delete block_backend
/> saveconfig

Related articles: Linux multipath configuration for iSCSI SANs, Fibre Channel vs iSCSI vs NVMe-oF, and NVMe over TCP target and initiator setup if you want the same export model without the SCSI-over-TCP overhead. Pair the target with LVM thin provisioning when you want snapshots of the exported LUN, and with smartctl and smartd so that a failing disk behind the backstore pages you before an initiator does.

原文链接:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_storage_devices/configuring-an-iscsi-target_managing-storage-devices