WhyBuilding and connecting an iSCSI disk, using ZFS volume for the storage backend.

See also

Vocabulary

iSCSI Qualified Name (IQN)

IQN is the ISCSI name, it refers both to the target and to the initiator, it is composed of 4 elements: the type (here iqn), date of creation of the naming authority, naming authority (the domain name whose terms are reversed), the name assigned by the authority.

  Type  Date  Naming Auth  Name defined by authority
  +--++-----+ +---------+ +--------------------------------+
  |  ||     | |         | |                                |
  iqn.2001-04.com.example:storage
Target

This is the server, it provides access to the LUN (Logical Unit Number) resources representing storage space.

Initiator

It can be regarded as the client, it’s the part that will connect to the target to obtain a LUN on which to perform the read/write operations.

Portal

It’s the set of IP address and port number on which the target is listening.

Autodiscovery

This is the process where the initiator requests to the portal the list of available targets.

Target

We create a ZFS dataset dedicated as storage backend for iscsi volumes, so that properties can be inherited by its children dataset, in particular we set the volmode to dev to avoid importing the created device into the server host.

# Create a dedicated hierarchy for iscsi share
zfs create -o mountpoint=none \
           -o volmode=dev     \
           Dataset hierarchy

When creating the device used as storage for iSCSI, it it possible to select a few options, such as sparse volume (-s) and blocksize (-b)

# Create a 10Gb volume using 4k block
zfs create -s -V Volume size -b Block size Dataset

We will use the native FreeBSD implementation ctld, but other are available using ports/packages such as such as iscsi-target and istgt. In the following example the targets are shared with whoever is able to authenticate.

# User authentication
auth-group User group {
    chap Username Password
}

# Portal
portal-group Portal group {
    discovery-auth-group no-authentication
    listen 0.0.0.0
    listen [::]
}

# List of targets
target iqn.2001-04.com.example:debian {
    alias Human readable describtion  # Human readable description
    auth-group   User group       # User authorisation
    portal-group Portal group      # Remote access
    lun LUN number {
        path      Path to device
        blocksize Blocksize (usually: 512 or 4096)       # Keep it as a multiple of dataset blocksize
        device-id Assigned device id     # Pass optional information as device-id/serial
        serial    Assigned serial     #  to ease identification from remote side
    }
}

Initiator

The initiator is controlled by the iscsid daemon, it is necessary to have it started to manage iscsi sessions (adding or removal of iscsi volume)

iscsid_enable="YES"       # Start the iscsi daemon
iscsictl_enable="YES"     # Connect session defined in iscsi.conf

It is not necessary to have an iscsi.conf file to create or add iscsi session, it can be done on the fly using the iscsictl command. But the iscsi.conf is a convenient way to store the configuration.

Identifier {
        TargetAddress   = iscsi.example.com:3260
        targetname      = iqn.2001-04.com.example:debian
        authmethod      = CHAP
        chapIName       = Username
        chapsecret      = Password
}

Usually iscsi session are started automatically during boot-up (see: iscsictl_enable), but it is also possible to manage them manually with the iscsictl command, some examples below:

Managing iscsi session
iscsictl -A -n Identifier      # Add the specified session
iscsictl -Aa                      # Add all session defined in ctl.conf
iscsictl -Ra                      # Remove all session

The content of the disk can be protected, by encrypting it. For that, the geli module can be used on FreeBSD:

Encrypting disk
geli init   Device path    # Initialize the encyption (destoying disk content)
geli attach Device path    # Attach the encrypted device