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

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.

1
2
3
4
  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.

1
2
3
4
# Create a dedicated hierarchy for iscsi share
zfs create -o mountpoint=none \
           -o volmode=dev     \
           data/iscsi

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)

1
2
# Create a 10Gb volume using 4k block
zfs create -s -V 10g -b 4k data/iscsi/debian

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.

ctl.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# User authentication
auth-group users {
    chap johndoe complicated_password
}

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

# List of targets
target iqn.2001-04.com.example:debian {
    alias "Debian (Buster)"  # Human readable description
    auth-group   users       # User authorisation
    portal-group remote      # Remote access
    lun 0 {
        path      /dev/zvol/data/iscsi/debian
        blocksize 4096       # Keep it as a multiple of dataset blocksize
        device-id debian     # Pass optional information as device-id/serial
        serial    buster     #  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)

rc.conf
1
2
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.

iscsi.conf
1
2
3
4
5
6
7
remote-debian {
        TargetAddress   = iscsi.example.com:3260
        targetname      = iqn.2001-04.com.example:debian
        authmethod      = CHAP
        chapIName       = johndoe
        chapsecret      = complicated_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
1
2
3
iscsictl -A -n remote-debian      # 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
1
2
geli init   /dev/da0    # Initialize the encyption (destoying disk content)
geli attach /dev/da0    # Attach the encrypted device