Ubuntu/Serveur iSCSI

GNU/Linux Magazine n° 109 | octobre 2008 | Fabien Dupont
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Cet article est consacré à la transformation d'un serveur Ubuntu en serveur iSCSI. Le protocole iSCSI est un « protocole de la couche application permettant le transport de commandes SCSI sur un réseau ». Ce qu'il faut comprendre, c'est qu'il est possible d'exporter un périphérique au travers d'un réseau en le présentant comme un périphérique SCSI. Outre le fait que le protocole SCSI est un standard de l'industrie déployé massivement en production, le fait de passer par un réseau IP classique permet de réduire les coûts de mise en œuvre par rapport au déploiement de solutions de stockage basées sur la technologie Fibre Channel. Par ailleurs, la sauvegarde des données peut se faire au niveau du serveur iSCSI, ce qui limite le coût de la solution de sauvegarde.

Néanmoins, les solutions libres ne sont pas nombreuses et il est donc difficile de convaincre un directeur informatique de basculer vers une solution de ce type basée sur du logiciel libre. Pour ma part, j'ai essayé d'utiliser la distribution OpenFiler, basée sur rPath Linux (méta-distribution à base de RedHat) et iSCSI Enterprise Target pour la partie iSCSI ; mais le produit n'est pas encore suffisamment abouti pour envisager une utilisation professionnelle.

Après un rapide passage sur la configuration matérielle et logicielle de base de la maquette, nous verrons comment exporter un disque depuis le serveur, puis comment l'importer sur le client et enfin nous configurerons le client pour utiliser ce nouveau disque.

Le schéma ci-dessous montre l'architecture que nous allons mettre en place.

Fig. 1 : Architecture générale

1. Installation des machines

Pour ne pas m'encombrer inutilement, je me suis basé sur des machines virtuelles KVM pour monter la maquette servant de support à cet article. Les deux machines virtuelles, une pour le serveur et une pour le client) ont une configuration de base identique, à savoir :

Matériel
Mémoire vive 128 Mo
Disque dur n°1 (/dev/sda) Disque dur IDE de 2 Go
Carte réseau n°1 (eth0) Carte Ethernet 100Mb/s
Carte réseau n°2 (eth1) Carte Ethernet 100Mb/s
Logiciel
Système d'exploitation Ubuntu Server 8.04 LTS
Services

OpenSSH Server avec les options suivantes :

- attachement du service sur l'interface eth0

- désactivation de la connexion en root

- désactivation du forward X11

- désactivation du sous-service SFTP

Les éléments de configuration spécifiques sont l'adressage IP et le nom d'hôte de chacune des machines, ainsi que l'ajout d'un disque dur IDE de 10 Go au serveur iSCSI qui servira de LUN pour l'export vers le client.

2. Export du disque côté serveur

Comme nous l'avons indiqué précédemment, nous disposons de 2 disques durs sur le serveur : 1 disque de 2 Go sur lequel nous avons installé le système d'exploitation et 1 disque de 10 Go que nous voulons exporter vers le client. Nous pouvons le voir avec la commande suivante :

ufiler@ufiler:~$ sudo fdisk -l

Disk /dev/sda: 2147 MB, 2147483648 bytes

255 heads, 63 sectors/track, 261 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Disk identifier: 0x00059089

   Device Boot      Start         End   Blocks   Id System

/dev/sda1               1          31   248976   82 Linux swap / Solaris

/dev/sda2   *          32         261 1847475   83 Linux

Disk /dev/sdb: 10.3 GB, 10309599232 bytes

255 heads, 63 sectors/track, 1253 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Disk identifier: 0x00000000

Disk /dev/sdb doesn't contain a valid partition table

Pour l'export de nos périphériques, nous utiliserons le démon ietd fourni par le package iscsitarget ; il s'agit du logiciel libre iSCSI Enterprise Target. Ce démon a en charge la présentation des périphériques aux clients, ainsi que la gestion des sessions de connexion. Il se base sur le module noyau iscsi_trgt. L'installation du package iscsitarget est simple :

ufiler@ufiler:~$ sudo apt-get install iscsitarget

Une fois l'installation terminée, le démon ietd est lancé automatiquement et se met en écoute sur le port 3260. Nous pouvons le vérifier comme suit :

ufiler@ufiler:~$ ps -edf | grep ietd | grep -v grep

root      4269     1 0 16:40 ?       00:00:00 /usr/sbin/ietd

ufiler@ufiler:~$ sudo netstat -antp | grep LISTEN | grep 3260

tcp    0    0 0.0.0.0:3260    0.0.0.0:*   LISTEN    4269/ietd

Par défaut, une target d'exemple est créée : iqn.2001-04.com.example:storage.disk2.sys1.xyz. Le format de nommage d'une target tel que défini dans la RFC est : iqn.yyyy-mm.<reversed domain name>:<identifier>. Nous pouvons voir les volumes exportés par le serveur via le fichier /proc/net/iet/volume :

ufiler@ufiler:~$ cat /proc/net/iet/volume

tid:1 name:iqn.2001-04.com.example:storage.disk2.sys1.xyz

Bien évidemment, il ne s'agit que d'un exemple et nous allons le modifier pour qu'il corresponde à nos besoins. Nous créons une target nommée iqn.2008-05.info.evenit.virtual:storage, à laquelle nous rattachons le périphérique /dev/sdb en tant que Lun 0. Cela nous donne donc le fichier /etc/ietd.conf suivant :

Target iqn.2008-05.info.evenit.virtual:storage

 Lun 0 Path=/dev/sdb,Type=fileio

Il suffit maintenant de redémarrer le service iscsitarget pour que les modifications soient prises en compte :

ufiler@ufiler:~$ sudo /etc/init.d/iscsitarget restart

Nous pouvons vérifier que la target et le LUN associé ont bien été créés :

ufiler@ufiler:~$ cat /proc/net/iet/volume

tid:1 name:iqn.2008-05.info.evenit.virtual:storage

 lun:0 state:0 iotype:fileio iomode:wt path:/dev/sdb

3. Import du disque côté client

Avant de commencer les manipulations pour l'import du périphérique iSCSI, prenons une photo de la liste des disques durs visibles sur le client. La commande ci-dessous montre qu'il n'y a qu'un seul disque, celui sur lequel nous avons installé le système d'exploitation :

evenit@iscsicli1:~$ sudo fdisk -l

Disk /dev/sda: 2147 MB, 2147483648 bytes

255 heads, 63 sectors/track, 261 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Disk identifier: 0x000eedc9

   Device Boot      Start         End   Blocks   Id System

/dev/sda1               1          31   248976   82 Linux swap / Solaris

/dev/sda2   *          32         261 1847475   83 Linux

À l'instar de ce qui se fait côté serveur, nous utilisons un démon pour gérer les sessions de connexion au périphériques iSCSI. Celui-ci se nomme iscsid et est fourni par le package open-iscsi. Il s'appuie sur les modules noyau libiscsi et iscsi_tcp. L'installation du package open-iscsi se fait comme suit :

evenit@iscsicli1:~$ sudo apt-get install open-iscsi

Une fois l'installation terminée, le démon iscsid est lancé automatiquement. Nous pouvons donc commencer la configuration proprement dite. La première étape est la découverte des targets disponibles sur le serveur (10.0.1.254) ; cela permet au client de connaître les détails de la target avant de s'y connecter et cela se fait ainsi :

evenit@iscsicli1:~$ sudo iscsiadm --mode discovery \

 --type sendtargets \

 --portal 10.0.1.254

10.0.1.254:3260,1 iqn.2008-05.info.evenit.virtual:storage

La commande iscsiadm est la commande à tout faire. Dans le cas présent, elle se met en mode découverte (--mode discovery) et demande au serveur 10.0.1.254 (--portal 10.0.1.254) de lui envoyer la liste des targets (--type sendtargets). Elle renvoie la liste des targets disponibles sur le serveur.

Maintenant que notre client connaît les targets disponibles, il suffit de se connecter à celles que nous souhaitons utiliser, à savoir iqn.2008-05.info.evenit.virtual:storage. La commande est simple :

evenit@iscsicli1:~$ sudo iscsiadm --mode node \

 --targetname iqn.2008-05.info.evenit.virtual:storage \

 --portal 10.0.1.254 \

 --login

Cette fois, nous sommes en mode gestion des périphériques (--mode node) et nous demandons à nous connecter (--login) à la target dont le nom est iqn.2008-05.info.evenit.virtual:storage (--targetname iqn.2008-05.info.evenit.virtual:storage) sur le serveur 10.0.1.254 (--portal 10.0.1.254). Cette commande crée une session entre le client et le serveur qui sert à la communication avec le périphérique iSCSI.

Nous pouvons vérifier très simplement que le nouveau périphérique est présent sur le système :

evenit@iscsicli1:~$ sudo fdisk -l

Disk /dev/sda: 2147 MB, 2147483648 bytes

255 heads, 63 sectors/track, 261 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Disk identifier: 0x000eedc9

   Device Boot      Start         End   Blocks   Id System

/dev/sda1               1          31   248976   82 Linux swap / Solaris

/dev/sda2   *          32         261 1847475   83 Linux

Disk /dev/sdb: 10.3 GB, 10309599232 bytes

64 heads, 32 sectors/track, 9832 cylinders

Units = cylinders of 2048 * 512 = 1048576 bytes

Disk identifier: 0x00000000

Disk /dev/sdb doesn't contain a valid partition table

Contrairement au démon ietd, iscsid conserve les informations relatives aux périphériques iSCSI lors du reboot. La commande iscsiadm modifie le contenu du répertoire /etc/iscsi de manière dynamique, ce qui fait que la configuration est maintenue. Par contre, la configuration par défaut fait qu'au prochain reboot la session ne sera pas ouverte automatiquement. Pour remédier à cela, nous avons deux méthodes :

1. Modifier le paramètre global de démarrage des sessions dans /etc/iscsi/iscsid.conf. Pour cela, il suffit de remplacer la ligne node.startup = manual par la ligne node.startup = automatic. C'est pratique si vous êtes sûr que vous ne ferez pas d'import dynamique que vous ne souhaitez pas garder et que vous risqueriez d'oublier au prochain boot.

2. Modifier le paramètre de démarrage session par session. Personnellement, je privilégie cette méthode qui suppose que tous les périphériques sont gérés individuellement. Pour cela, il suffit de taper la commande suivante qui modifie (--op update) le paramètre node.startup (--name node.startup) en lui donnant la valeur automatic (--value automatic) :

evenit@iscsicli1:~$ sudo iscsiadm --mode node \

 --targetname iqn.2008-05.info.evenit.virtual:storage \

 --op update \

 --name node.startup \

 --value automatic

Nous avons maintenant un serveur exportant son périphérique /dev/sdb via iSCSI et un client qui importe ce même périphérique.

Vous pourriez vouloir désactiver la session sur le client (pour maintenance par exemple). Cela se fait comme suit :

evenit@iscsicli1:~$ sudo iscsiadm --mode node \

 --targetname iqn.2008-05.info.evenit.virtual:storage \

 --portal 10.0.1.254 \

 --logout

Vous pourriez aussi souhaiter ajouter des disques durs au serveur et connecter d'autres clients à ces disques en iSCSI. Il vous faudra alors vérifier que le nom d'initiator des nouveaux clients est unique sur le réseau ; cela générerait des conflits entre les clients à la manière d'une duplication d'adresse IP. Ce paramètre est défini dans le fichier /etc/initiatorname.iscsi, dans le champ InitiatorName.

4. Partitionnement, formatage et montage du périphérique

À présent que nous avons importé un disque dur iSCSI, il est grand temps de l'utiliser. Nous allons donc dérouler les étapes nécessaires pour l'intégrer à notre système.

Commençons donc par le partitionner ; pour cela, nous utiliserons sfdisk en remplacement du bon vieux fdisk. L'intérêt de sfdisk est qu'il accepte un fichier de configuration en entrée pour partitionner le disque en mode non interactif. Le jeu de commandes suivant permet de générer une seule partition de type Linux (83) sur le disque /dev/sdb que nous venons tout juste d'importer :

evenit@iscsicli1:/etc/iscsi$ echo ",,83" > /tmp/sfdisk.cfg

evenit@iscsicli1:/etc/iscsi$ sudo sfdisk /dev/sdb < /tmp/sfdisk.cfg

evenit@iscsicli1:/etc/iscsi$ rm /tmp/sfdisk.cfg

Nous pouvons vérifier simplement le résultat, une partition de 10 Go et de type Linux :

evenit@iscsicli1:/etc/iscsi$ sudo fdisk -l /dev/sdb

Disk /dev/sdb: 10.3 GB, 10309599232 bytes

64 heads, 32 sectors/track, 9832 cylinders

Units = cylinders of 2048 * 512 = 1048576 bytes

Disk identifier: 0xd38c3f35

   Device Boot      Start         End   Blocks   Id System

/dev/sdb1               1        9832 10067967+ 83 Linux

L'étape logique qui suit est bien entendu le formatage. Nous ferons de /dev/sdc1 une partition ext3 :

evenit@iscsicli1:/etc/iscsi$ sudo mke2fs -j /dev/sdb1

Et comme une partition formatée ne sert à rien tant qu'elle n'est pas montée sur une arborescence du système, nous allons tout naturellement la monter. Pour cela, nous créons l'arborescence /data et montons /dev/sdc1 dedans. Un petit df -h permet de confirmer que la partition est bien montée (la dernière de la liste).

evenit@iscsicli1:/etc/iscsi$ sudo mkdir /data

evenit@iscsicli1:/etc/iscsi$ sudo mount -t ext3 /dev/sdb1 /data

evenit@iscsicli1:/etc/iscsi$ df -h

Filesystem            Size Used Avail Use% Mounted on

/dev/sda2             1,8G 498M 1,2G 30% /

varrun                 61M   44K   61M   1% /var/run

varlock                61M     0   61M   0% /var/lock

udev                   61M   48K   61M   1% /dev

devshm                 61M     0   61M   0% /dev/shm

/dev/sdb1             9,6G 150M 8,9G   2% /data

Bien ! Si vous vous souvenez bien, le périphérique sera toujours présent au prochain boot, sans rien avoir à faire. Il faut donc faire en sorte qu'il soit utilisable aussi sans rien avoir à faire. Pour cela, il suffit d'éditer le fichier /etc/fstab pour indiquer au système que la partition /dev/sdb1 doit être montée dans /data :

evenit@iscsicli1:/etc/iscsi$ sudo sh -c \

 "echo '/dev/sdb1 /data ext3 relatime 0 0' >> /etc/fstab"

5. Gestion dynamique des targets/LUN sur le serveur

Le mode de configuration du serveur que nous venons de voir passe uniquement via le fichier de configuration /etc/ietd.conf, car c'est le seul moyen de conserver la configuration lors des futurs reboots. Il est cependant possible de gérer les targets et LUN dynamiquement au travers de la commande ietadm ; c'est pratique pour tester une configuration, mais ce n'est pas pérenne. Voici cependant quelques commandes utiles :

Création d'une target de nom iqn.2008-05.info.evenit.virtual:storage2 et d'ID 2 :

ufiler@ufiler:~$ sudo ietadm --op new \

 --tid 2 \

 --params Name=iqn.2008-05.info.evenit.virtual:storage2

Ajout d'un LUN dont le périphérique réel est /dev/sdc à la target dont l'ID est   :

ufiler@ufiler:~$ sudo ietadm --op new \

 --tid 2 \

 --lun 0 \

 --params Path=/dev/sdc,Type=fileio

Nous pouvons la voir dans /proc/net/ietf/volume :

ufiler@ufiler:~$ cat /proc/net/iet/volume

tid:1 name:iqn.2008-05.info.evenit.virtual:storage

 lun:0 state:0 iotype:blockio iomode:wt path:/dev/sdb

tid:2 name:iqn.2008-05.info.evenit.virtual:storage 2

 lun:0 state:0 iotype:blockio iomode:wt path:/dev/sdc

Suppression du Lun 0 de associé à la target 2 :

ufiler@ufiler:~$ sudo ietadm --op delete --tid 2 --lun 0

Suppression de la target dont l'ID est 2 :

ufiler@ufiler:~$ sudo ietadm --op delete --tid 2

6. Sécurisation des accès aux serveurs

Comme tout administrateur, nous développons un début de paranoïa et nous souhaitons sécuriser un minimum les droits d'accès aux ressources. Pour cela, nous avons à notre disposition 2 mécanismes :

1. Restreindre les adresses IP autorisées à voir les périphériques : une machine ne peut voir que les targets qu'on l'autorise à découvrir.

2. Mettre en place une authentification par mot de passe : permet de bloquer l'usurpation d'adresse IP (IP spoofing).

6.1 Restriction Target/IP

La règle la plus élémentaire en matière de sécurité est de tout interdire, puis d'autoriser au cas par cas. Nous allons donc appliquer ce principe pour restreindre l'accès à nos targets iSCSI. Pour cela, nous utiliserons les fichiers /etc/initiators.allow et /etc/initiators.deny. En sachant que /etc/initiators.deny est prioritaire sur /etc/initiators.allow, nous allons simplement écrire la ligne suivante dans /etc/initiators.deny et effacer tout le reste :

ALL ALL

Cela interdit l'accès à tous les targets (ALL) à partir de tous les hôtes (ALL).

Il ne nous reste plus qu'à ouvrir l'accès aux hôtes autorisés en les ajoutant dans /etc/initiators.allow comme suit :

iqn.2008-05.com.example:storage 10.0.1.10

À partir de maintenant, le target iqn.2008-05.com.example:storage est accessible uniquement à l'hôte 10.0.1.10.

6.2 Authentification par mot de passe

Maintenant que nous avons limité l'accès à certains hôtes, nous allons restreindre l'accès aux seuls utilisateurs authentifiés. Dans notre exemple, nous limitons l'accès à la ressource iqn.2008-05.com.example:storage à l'utilisateur bob dont le mot de passe est leponge. Côté target, nous devons ajouter la limitation à la définition du target dans le fichier /etc/ietd.conf :

Target iqn.2008-05.com.example:storage.lvm.share01

 IncomingUser bob leponge

 Lun 0 Path=/dev/mapper/iScsiShares_vg-iScsiShare01_lv,Type=fileio

Une fois la modification réalisée, il faut redémarrer le démon :

fabien@iscsi_srv$ sudo /etc/init.d/iscsitarget restart

Côté initiator, nous devons ajouter les mêmes informations dans le fichier /etc/iscsi/iscsid.conf :

node.session.auth.authmethod = CHAP

node.session.auth.username = bob

node.session.auth.password = leponge

Il suffit de redémarrer le démon : sudo /etc/init.d/open-iscsi restart, pour appliquer les changements. Ensuite, il ne reste plus qu'à importer le target comme vu précédemment.

7. Conclusion

Vous avez maintenant vu les bases de la configuration d'un iSCSI sur Ubuntu. Loin de faire de vous un expert du sujet (je n'en suis pas un moi-même), cela vous ouvre de nouvelles perspectives dans la gestion de votre stockage. À vous d'imaginer votre propre configuration, en fonction des besoins qui sont les vôtres : multiplication des périphériques exportés et des clients.

Il faut aussi prévoir la sécurisation des données, aussi bien sur le serveur que sur le réseau. Pour le serveur, vous devriez pouvoir vous en sortir avec du RAID. Pour le réseau, il est intéressant de mettre en place des VLAN et du filtrage pour restreindre les accès, ainsi que de la redondance de lien (bonding) en cas de panne. Mais, ces sujets pourraient faire l'objet d'un article chacun...

Liens

iSCSI sur Wikipédia : http://fr.wikipedia.org/wiki/ISCSI

iSCSI Enterprise Target : http://iscsitarget.sourceforge.net

Open iSCSI : http://www.open-iscsi.org

OpenFiler : http://www.openfiler.com