iSCSI Initiator und Target mit Alpine/Debian

ZIEL: Alpinelinux soll als Target (= Server) ein Image-File als Storage-Volume im Netzwerk bereitstellen; das Debian-Hostsystem stellt nachfolgend den Client sprich Initiator dar. Dieser Initiator bekommt nach erfolgreichem Login am entfernten Target das dortige Volume als lokales Blockgerät zur Verfügung gestellt.

Siehe dazu insbesondere das Kurztutorial unter:

Aber auch diese Seiten:

Einrichtung des Targets

Wo? Auf dem Alpinelinux-System (= Server), Release: 3.8

Vorbereitungen

Wir verwenden hier ein ganz normal installiertes Alpinelinux-System ohne grafische Oberfläche. Eine Container-Virtualisierung (LXC, Docker) ist für die Target-Software „targetcli“ nicht ausreichend, weil Kernelmodule für das Erzeugen einer Gerätedatei geladen werden müssten, was im Container nicht gelingt.

Zuerst erfolgt die Netzwerkkonfiguration und Installation der benötigten Software:

ip addr add 10.2.2.3/24 dev eth0
ip route add default via 10.2.2.1
echo nameserver 80.80.80.80 > /etc/resolv.conf
apk update
apk add targetcli

Dann starten wir die Dienste und aktivieren sie für automatischen Start beim Bootvorgang:

alp3:~# /etc/init.d/dbus start
* Starting D-BUS system messagebus ...                  [ ok ]
alp3:~#
alp3:~# ps aux | grep dbus
2310 messageb  0:00 /usr/bin/dbus-daemon --system
2318 root      0:00 grep dbus
alp3:~#
alp3:~# /etc/init.d/targetcli start
* Starting targetcli ...
mount: mounting none on /sys/kernel/config failed: Resource busy
Restore file /etc/target/saveconfig.json not found       [ ok ]
alp3:~#
alp3:~# rc-update add dbus
* service dbus added to runlevel default
alp3:~#
alp3:~# rc-update add targetcli
* service targetcli added to runlevel default
alp3:~#

Konfiguration

Starten des Client-Tools und Erzeugen eines Sparse-Imagefiles, das freigegeben werden soll (Hinweis: Die Autovervollständigung mittels Tabulator-Taste funktioniert in diesem Tool hervorragend):

alp3:~# targetcli
targetcli shell version 2.1.fb47
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.
/> ls
o- / ...................................................... [...]
o- backstores ............................................. [...]
| o- block ..................................[Storage Objects: 0]
| o- fileio .................................[Storage Objects: 0]
| o- pscsi ..................................[Storage Objects: 0]
| o- ramdisk ................................[Storage Objects: 0]
o- iscsi ........................................... [Targets: 0]
o- loopback ........................................ [Targets: 0]
o- vhost ........................................... [Targets: 0]
o- xen_pvscsi ...................................... [Targets: 0]
/>
/>
/> /backstores/fileio create file1 /lun1 128M write_back=false
Created fileio file1 with size 134217728
/>
/> ls /backstores/fileio/
o- fileio ................................. [Storage Objects: 1]
o- file1 ............. [/lun1 (128.0MiB) write-thru deactivated]
    o- alua ................................... [ALUA Groups: 1]
    o- default_tg_pt_gp ......... [ALUA state: Active/optimized]
/>
/>

Von anderem Terminal aus (bash) überprüfen wir die erfolgreiche Erzeugung des Image-Files:

alp3:~$ ls -lisah /lun*
9586      0 -rw-r--r--    1 root     root      128.0M Apr 16 18:47 /lun1
alp3:~$

Erzeugen eines iSCSI Qualified Name (IQN):

/> iscsi/ create iqn.2018-04.org.x:disk1
Created target iqn.2018-04.org.x:disk1.
Created TPG 1.
Global pref auto_add_default_portal=true
Created default portal listening on all IPs (0.0.0.0), port 3260.
/>
/> cd iscsi/iqn.2018-04.org.x:disk1/tpg1/
/iscsi/iqn.20....x:disk1/tpg1> luns/ create /backstores/fileio/file1
Created LUN 0.
/iscsi/iqn.20....x:disk1/tpg1>

Festlegen einer ACL, diese Angabe muss beim Initiator zur Autorisierung hinterlegt werden:

/iscsi/iqn.20....x:disk1/tpg1> cd acls
/iscsi/iqn.20...sk1/tpg1/acls> ls
o- acls ............................................. [ACLs: 0]
/iscsi/iqn.20...sk1/tpg1/acls>
/iscsi/iqn.20...sk1/tpg1/acls> create iqn.2018-04.org.debian9:testinit
Created Node ACL for iqn.2018-04.org.debian9:testinit
Created mapped LUN 0.
/iscsi/iqn.20...sk1/tpg1/acls>
/iscsi/iqn.20...sk1/tpg1/acls> ls
o- acls ............................................. [ACLs: 1]
o- iqn.2018-04.org.debian9:testinit .......... [Mapped LUNs: 1]
    o- mapped_lun0 ................... [lun0 fileio/file1 (rw)]
/iscsi/iqn.20...sk1/tpg1/acls>
/iscsi/iqn.20...sk1/tpg1/acls>
/iscsi/iqn.20...sk1/tpg1/acls> exit
Global pref auto_save_on_exit=true
Could not create backup file /etc/target/backup/saveconfig-20190416-19:03:03.json: No such file or directory.
Configuration saved to /etc/target/saveconfig.json
alp3:~#
alp3:~#
alp3:~# grep -A5 lun1 /etc/target/saveconfig.json
    "dev": "/lun1",
    "name": "file1",
    "plugin": "fileio",
    "size": 134217728,
    "write_back": false,
    "wwn": "19bf99b8-203b-4b5f-b0ff-c6c579bd0092"
alp3:~#

Zusammenfassung der 3 wichtigen Konfigurationsschritte im interaktiven Tool ‚targetcli‘:

  1. Erzeugen eines Sparse-Imagefiles als Storage

/backstores/fileio create file1 /lun1 128M write_back=false
  1. Erzeugen eines iSCSI Qualified Name (IQN)

iscsi/ create iqn.2018-04.org.x:disk1
cd iscsi/iqn.2018-04.org.x:disk1/tpg1/
luns/ create /backstores/fileio/file1
  1. Erzeugen einer ACL, mit der sich dann der Initiator autorisieren kann

cd acls
create iqn.2018-04.org.debian9:testinit
exit

Einrichtung des Initiators

Wo? Auf dem Debian-Hostsystem (= Client). Release: 9.8

Vorbereitungen

Vor allem brauchen wir erst einmal wieder die Software:

root@debhost:~# apt-get install open-iscsi
Paketlisten werden gelesen... Fertig
Abhängigkeitsbaum wird aufgebaut.
Statusinformationen werden eingelesen.... Fertig
The following additional packages will be installed:
libisns0
Die folgenden NEUEN Pakete werden installiert:
libisns0 open-iscsi
0 aktualisiert, 2 neu installiert, 0 zu entfernen und 6 nicht aktualisiert.
Es müssen 403 kB an Archiven heruntergeladen werden.
Nach dieser Operation werden 2.432 kB Plattenplatz zusätzlich benutzt.
Möchten Sie fortfahren? [J/n]
Holen:1 http://ftp-stud.hs-esslingen.de/debian stretch/main amd64 libisns0 amd64 0.97-2 [113 kB]
Holen:2 http://ftp-stud.hs-esslingen.de/debian stretch/main amd64 open-iscsi amd64 2.0.874-3~deb9u1 [290 kB]
Es wurden 403 kB in 0 s geholt (1.065 kB/s).
Vorkonfiguration der Pakete ...
Vormals nicht ausgewähltes Paket libisns0:amd64 wird gewählt.
  (Lese Datenbank ... 103588 Dateien und Verzeichnisse sind derzeit installiert.)
Vorbereitung zum Entpacken von .../libisns0_0.97-2_amd64.deb ...
Entpacken von libisns0:amd64 (0.97-2) ...
Vormals nicht ausgewähltes Paket open-iscsi wird gewählt.
Vorbereitung zum Entpacken von .../open-iscsi_2.0.874-3~deb9u1_amd64.deb ...
Entpacken von open-iscsi (2.0.874-3~deb9u1) ...
libisns0:amd64 (0.97-2) wird eingerichtet ...
Trigger für initramfs-tools (0.130) werden verarbeitet ...
update-initramfs: Generating /boot/initrd.img-4.9.0-7-amd64
cp: der Aufruf von stat für '/etc/iscsi/initiatorname.iscsi' ist nicht möglich: Datei oder Verzeichnis nicht gefunden
open-iscsi (2.0.874-3~deb9u1) wird eingerichtet ...
Created symlink /etc/systemd/system/sysinit.target.wants/iscsid.service → /lib/systemd/system/iscsid.service.
Created symlink /etc/systemd/system/iscsi.service → /lib/systemd/system/open-iscsi.service.
Created symlink /etc/systemd/system/sysinit.target.wants/open-iscsi.service → /lib/systemd/system/open-iscsi.service.
Trigger für libc-bin (2.24-11+deb9u4) werden verarbeitet ...
Trigger für systemd (232-25+deb9u11) werden verarbeitet ...
Trigger für man-db (2.7.6.1-2) werden verarbeitet ...
Trigger für initramfs-tools (0.130) werden verarbeitet ...
update-initramfs: Generating /boot/initrd.img-4.9.0-7-amd64
root@debhost:~#

Konfiguration

Danach lassen wir eine Erkennungsroutine laufen:

root@debhost:~# iscsiadm -m discovery -t sendtargets -p 10.2.2.3
10.2.2.3:3260,1 iqn.2018-04.org.x:disk1
root@debhost:~#
root@debhost:~# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 101,9G  0 disk
├─sda1   8:1    0  23,3G  0 part /
├─sda2   8:2    0   1,9G  0 part [SWAP]
├─sda3   8:3    0     1K  0 part
├─sda5   8:5    0     5G  0 part
└─sda6   8:6    0  71,7G  0 part /var/lib/docker
sr0     11:0    1    82M  0 rom  /media/cdrom0
root@debhost:~#

Und schon versuchen wir uns am ersten Login, der ja dann schon die gewünschte Gerätedatei erzeugen würde:

root@debhost:~# iscsiadm -m node --target iqn.2018-04.org.x:disk1 -p 10.2.2.3 --login
Logging in to [iface: default, target: iqn.2018-04.org.x:disk1, portal: 10.2.2.3,3260] (multiple)
iscsiadm: Could not login to [iface: default, target: iqn.2018-04.org.x:disk1, portal: 10.2.2.3:,3260].
iscsiadm: initiator reported error (24 - iSCSI login failed due to authorization failure)
iscsiadm: Could not log into all portals
root@debhost:~#
root@debhost:~# #  >>> Na klar: Der Client kann noch keine ACL vorweisen.

Damit es aber tatsächlich funzt, muss die oben erzeugte ACL hier noch eingefügt werden, danach muss vor allem der Daemon ‚iscsid‘ neu gestartet werden:

root@debhost:~# vi /etc/iscsi/initiatorname.iscsi
root@debhost:~#
root@debhost:~# cat /etc/iscsi/initiatorname.iscsi
## DO NOT EDIT OR REMOVE THIS FILE!
## If you remove this file, the iSCSI daemon will not start.
## If you change the InitiatorName, existing access control lists
## may reject this initiator.  The InitiatorName must be unique
## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames.
#AXPE: Original-Zeile auskommentiert und den neuen Wert hinterlegt (wie oben auf dem Target angegeben):
###InitiatorName=iqn.1993-08.org.debian:01:d38db5492390
InitiatorName=iqn.2018-04.org.debian9:testinit
root@debhost:~#
root@debhost:~# systemctl restart iscsid iscsi
root@debhost:~#
root@debhost:~# iscsiadm -m node --target  iqn.2018-04.org.x:disk1 -p 10.2.2.3 --login
Logging in to [iface: default, target: iqn.2018-04.org.x:disk1, portal: 10.2.2.3,3260] (multiple)
Login to [iface: default, target: iqn.2018-04.org.x:disk1, portal: 10.2.2.3,3260] successful.
root@debhost:~#
root@debhost:~# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 101,9G  0 disk
├─sda1   8:1    0  23,3G  0 part /
├─sda2   8:2    0   1,9G  0 part [SWAP]
├─sda3   8:3    0     1K  0 part
├─sda5   8:5    0     5G  0 part
└─sda6   8:6    0  71,7G  0 part /var/lib/docker
sdb      8:16   0   128M  0 disk
sr0     11:0    1    82M  0 rom  /media/cdrom0
root@debhost:~#

Schließlich kann wie üblich das neue Gerät benutzt werden:

root@debhost:~# mkfs /dev/sdb
mke2fs 1.43.4 (31-Jan-2017)
Ein Dateisystems mit 131072 (1k) Blöcken und 32768 Inodes wird erzeugt.
UUID des Dateisystems: 3821bf9a-8f0e-434d-8b94-967ea417b116
Superblock-Sicherungskopien gespeichert in den Blöcken:
    8193, 24577, 40961, 57345, 73729

beim Anfordern von Speicher für die Gruppentabellen: erledigt
Inode-Tabellen werden geschrieben: erledigt
Die Superblöcke und die Informationen über die Dateisystemnutzung werden
geschrieben: erledigt

root@debhost:~#
root@debhost:~# mount /dev/sdb /mnt
root@debhost:~#
root@debhost:~# df -h /mnt/
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
/dev/sdb        124M    1,6M  117M    2% /mnt
root@debhost:~#
root@debhost:~#
root@debhost:~# cp -a /etc/ /mnt/
root@debhost:~# df -h /mnt/
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
/dev/sdb        124M    4,3M  114M    4% /mnt
root@debhost:~#
root@debhost:~# sync
root@debhost:~#

Kontrolle auf dem Target

Wenn das Image-File nach der Kopieraktion tatsächlich angeschwollen ist, hat alles geklappt:

alp3:~$ ls -lisah /lun*
9586   7348 -rw-r--r--    1 root     root      128.0M Apr 16 19:27 /lun1
alp3:~$

Im Vergleich zur Ausgangssituation (siehe oben):

9586      0 -rw-r--r--    1 root     root      128.0M Apr 16 18:47 /lun1