03 juil 2009

    Ubuntu/Serveur iSCSI

    Catégorie : Administration système     Tags :      2 Commentaires

    Retrouvez cet article dans : Linux Magazine 109

    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.

    Sans titre-1 copie.TIF

    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.

    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 :

    2

    Export du disque côté serveur

    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 aux 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 0 :

    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 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

    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

    Sécurisation des accès aux serveurs

    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...

    Auteur : Fabien Dupont

    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

    Retrouvez cet article dans : Linux Magazine 109

    Posté par (La rédaction) | Signature : Fabien Dupont | Article paru dans Creative Commons License

    Il y a actuellement 2 commentaires dans “Ubuntu/Serveur iSCSI”

    1. 1 Le 6 juillet 2009, kortex[10] ecrivait:

      Bonjour,

      Je ne sais pas si c’est le lieux pour ça mais j’aurais une question concernant l’article (qui je dois l’avouer correspond exactement à ce que je cherchais)

      Supposons avoir plusieurs disques durs réunis dans un VG de LVM.
      Est-il possible d’avoir pour target les LV créés à partir du VG ?
      Cela augmenterait la flexibilité de la gestion des disques.
      Je vous cache pas que je cherche à faire un SAN maison pour pas grand chose !!!

      Cordialement

    2. 2 Le 7 août 2009, lgautrot[10] ecrivait:

      Une target iSCSI est un périphérique bloc.

      On peut donc utiliser un disque, une partition, un volume logique, une grappe de RAID, une LUN d’un SAN, etc.

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.