Mise en place d’un SAN iSCSI hautement disponible avec DRBD et Keepalived

Un cluster infiniment disponible !

Un cluster infiniment disponible !

Attention, billet un peu plus technique que d’habitude…

Je me suis récemment lancé dans un projet de fin d’année que je dois réaliser dans le cadre de mes études. je dois mettre en place une infrastructure pour une (fausse) entreprise de 100 personnes mettant en jeu un serveur de virtualisation qui stocke ses VMs sur un SAN.

Comme j’ai prévu de partager mon expérience avec vous sur ce blog, je vous mets le sujet à disposition.

Ce SAN doit être un cluster d’au moins deux nœuds pour y configurer de la haute disponibilité. Je vais donc devoir mettre en œuvre des solutions comme iSCSI ou DRBD afin de pouvoir y « brancher » mon serveur de virtualisation.

C’est parti !


edit 1 : correction de fautes dans certaines commandes
edit 2 : après quelques déboires avec Proxmox et iSCSI, j’ai finalement délaissé ce dernier pour lui préférer NFS (qui supporte par ailleurs la migration de VMs à chaud). Cet article n’en devient pas pour autant obsolète puisque les informations qu’il contient restent vraies.

Introduction : présentation de l’architecture du SAN

On va y aller pas à pas.

Dans mon cas, je souhaite avoir deux serveurs en cluster : si j’écris une information sur le premier, elle doit être instantanément disponible sur l’autre (et vice-versa). Lorsque l’on souhaite mettre en place ce type d’architecture, on se tourne généralement vers une technologie appelée DRBD, qui permet d’avoir une synchronisation parfaite de données entre deux serveurs. Et quand je parle de synchronisation parfaite, je parle de copie bloc par bloc !

DRBD est ensuite utilisé en mode Actif / Passif (ou Maître / Esclave) et se présente simplement sous forme d’un nouveau périphérique de stockage de type /dev/drbdX sur nos machines :

Rien de compliqué pour le moment...

Rien de compliqué pour le moment…

Si le serveur Maître venait à tomber, le service qu’il héberge serait presque instantanément transféré sur le serveur Esclave, qui prendrait le relais jusqu’à la remise en place du Maître.

Schéma DRBD FailoverLe volume /dev/drbdX est alors monté sur le Passif (qui devient Actif !) et tout se fait de manière transparente pour l’utilisateur (hormis un temps de latence de quelques dizaines de secondes en fonction du service). Dans cet exemple, nous pouvons très bien utiliser un système de fichier standard type ext4 par exemple.

En gros, on va faire du RAID1 sur TCP/IP !

Oui mais voilà, je cherche à mettre en place un hyperviseur qui pourrait stocker ses machines virtuelles sur cette architecture. Hors ici, nos disques DRBD ne sont utilisables qu’en local.

C’est là qu’entre en jeu iSCSI. iSCSI c’est quoi ? C’est du SCSI sur TCP/IP. Grosso-merdo : c’est monter des disques distants (le SAN) sur des machines locales (le serveur de virtualisation) en toute transparence.

Reprenons le schéma pour y voir plus clair :

Sympa non ?

Sympa non ?

Avec ça, notre SAN est configuré en haute-disponibilité et sera toujours accessible si l’un des deux serveurs tombe en panne ! C’est très intéressant dans la mesure où la seule chose qui accèdera au SAN, c’est le serveur de virtualisation !

Enfin, petite chose importante si l’on veut faire les choses proprement : ajouter une deuxième carte réseau à nos nœuds afin de les dédier au DRBD, l’autre servira à iSCSI.

C’est parti pour la mise en place de tout ce petit monde ! Pour résumer, j’ai deux machines :

Nom de machine Adresse eth0 (LAN) Adresse eth1 DRBD) Rôle DRBD
mnemosyne 192.168.100.10 192.168.101.100 Maître
clio 192.168.100.11 192.168.101.101 Esclave

Note : je travaille sur Debian 7.

Installation et configuration de DRBD

Nous commençons par configurer DRBD afin d’obtenir un nouveau lecteur de type /dev/drbdX sur lequel nous appliquerons iSCSI.

Installation de DRBD

Commencez par installer le paquet drbd8-utils.

sudo apt-get install drbd8-utils

Configuration préable

Nos deux machines doivent pouvoir se contacter via leur hostname, mettez donc à jour votre fichier host (à adapter à votre configuration) pour que DRBD fonctionne avec la deuxième carte réseau de vos machines et que chaque machine puisse envoyer un ping à l’autre via leur hostname. Par exemple :

192.168.101.100 clio

Sur le nœud 1 (mnemosyne), et

192.168.101.101 mnemosyne

sur le deuxième nœud (clio).

Configuration de la ressource

Je propose maintenant de créer une ressource dans le dossier /etc/drbd.d/. Appelons là iscsi.res par exemple. Ce fichier doit être strictement le même sur les deux serveurs et contient les informations suivantes :

resource iscsi {
        protocol C;
        device /dev/drbd0;
        disk /dev/sdb1;
        meta-disk internal;
 
        startup {
                become-primary-on mnemosyne;
        }
        disk {
                on-io-error detach;
        }
        net {
                after-sb-0pri discard-older-primary;
                after-sb-1pri call-pri-lost-after-sb;
                after-sb-2pri call-pri-lost-after-sb;
        }
        syncer {
                rate 100M;
        }
        on mnemosyne {
                address 192.168.101.100:7788;
        }
        on clio {
                address 192.168.101.101:7788;
        }
}

A partir de maintenant, toutes les commandes qui suivent doivent être entrées en même temps sur les deux machines. Ce que je veux dire par là, c’est que si j’exécute une commande A, il faut l’exécuter sur les deux machines avant de passer à la commande B compris ? Sinon ben… vous êtes bon pour recommencer 🙂

Donc nos SAN sont configurés, il faut à présent initialiser la ressource iscsi :

sudo drbdmdadm create-md iscsi
 
  --==  Thank you for participating in the global usage survey  ==--
The server s response is:
 
you are the 438th user to install this version
Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.
success

Puis :

sudo modprobe drbd
sudo drbdadm attach iscsi
sudo drbdadm connect iscsi

Veillez à bien rentrer ces commandes en même temps sur les deux serveurs ! Normalement, vous devriez avoir le résultat suivant :

cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 41C52C8CD882E47FB5AF767
 0: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C r-----

On peut voir que nos deux nœuds sont bien connectés et sont tous les deux secondaires. La commande suivante va « élever » le premier mnemosyne en temps que serveur Maître (commandes à exécuter uniquement sur le maître donc) :

sudo drbdadm -- --overwrite-data-of-peer primary iscsi

La synchronisation devrait avoir démarré. Vous pouvez voir un avancement de tout ceci via la commande :

watch -n 1 cat /proc/drbd

Synchronisation DRBD

La synchronisation peut prendre un peu de temps… Allez donc dire bonjour à Madame :). Vous pouvez diminuer ce temps en supprimant le bridage de bande passante avec la commande

drbdsetup /dev/drbd0 syncer -r 100M

Au bout du compte, on obtient ceci :

cat /proc/drbd
version: 8.3.11 (api:88/proto:86-96)
srcversion: 41C52C8CD882E47FB5AF767
 0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate C r-----
    ns:419416540 nr:0 dw:0 dr:419417536 al:0 bm:25600 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0

On peut revenir à un débit de synchronisation moindre :

sudo drbdadm adjust iscsi

Vous voilà maintenant avec un nouveau lecteur (/dev/drbd0) que vous pouvez utiliser comme bon vous semble. Vous pourriez par exemple l’utiliser pour le mettre en partage sur le réseau avec iSCSI.

Deuxième : installation et configuration de iSCSI

sudo apt-get install iscsitarget iscsitarget-dkms

En langage iSCSI, il y a deux éléments de vocabulaire à retenir :

  • Sur le serveur qui contient le périphérique à partager, on configure ce qui s’appelle la target.
  • Sur le client, on configurera ce qui s’appelle l’initiator.

La configuration de la target iSCSI se situe dans /etc/iet/ietd.conf :

Target iqn.2013-06.com.example:drbd0
Lun 0 Path=/dev/drbd0,Type=fileio

Pour plus d’information sur le format de l’IQN (iSCSI Qualified Name), voir les RFC 3720 et 3721 ou Wikipédia.

Modifiez la valeur de ISCSITARGET_ENABLE à true dans /etc/default/iscsitarget.

On redémarre le service iscsitarget et c’est tout 🙂

Toujours un doute ? Un petit…

cat /proc/net/iet/volume

… devrait vous rassurer.

Réitérez l’opération sur le deuxième serveur, l’idée étant d’avoir exactement la même configuration. Une fois fait, nous pouvons passer à la suite !

Mise en place d’une adresse IP flottante avec Keepalived

Telle qu’elle est configurée notre architecture ne peu pas être qualifiée de hautement disponible. En effet, mon serveur de virtualisation sera configuré pour stocker ses VM sur le SAN, auquel il accèdera via l’IP 192.168.100.100. Et si cette machine venait à tomber ? Que se passerait-il ?

Mes VM seraient toujours disponibles, mais sur le serveur secondaire, accessible à une adresse différente, que mon serveur de virtualisation n’est pas censé connaître ! On aura donc un gros problème… Pour pallier à cela, nous allons mettre en place une adresse IP flottante.

Le principe est simple : on configure les deux nœuds du SAN pour qu’il « s’écoutent » mutuellement. On partira du principe que mnemosyne est mon serveur actif en cours d’utilisation. Si le deuxième nœud (clio), « n’entend plus » mnemosyne lui dire « Je suis vivant ! » toutes les X secondes, alors il s’appropriera son adresse IP et prendra le relais de manière quasi transparente pour l’utilisateur. L’outil utilisé pour gérer ce flottement et cette écoute s’appelle Keepalived.

Vous suivez toujours ?

Installation et configuration de Keepalived

Comme d’habitude, l’installation reste l’étape la plus simple.

sudo apt-get install keepalived

Vient ensuite la configuration, via le fichier /etc/keepalived/keepalived.conf. Je vous propose le contenu suivant :

# Configuration File for Keepalived
# Global configuration
 
global_defs {
        notification_email {
                admin@example.net
        }
        notification_email_from noreply@cicp2r.org
        smtp_server smtp.example.net
        smtp_connect_timeout 30
        router_id MNEMOSYNE
}
 
vrrp_instance VI_1 {
        state MASTER
        interface eth0
        virtual_router_id 51
        priority 100
        advert_int 1
        authentication {
                auth_type PASS
                auth_pass xxx
        }
        virtual_ipaddress {
                192.168.100.100/24
        }
        notify_master "service iscsitarget restart"
        notify_backup "service iscsitarget restart"
}

Pensez à éditer le fichier /etc/sysctl.conf et décommentez la ligne net.ipv4.ip_forward=1.

Installez keepalived sur le deuxième nœud, copiez / collez le fichier de configuration et modifiez la ligne « state MASTER » par « state BACKUP ». Éditez aussi /etc/sysctl.conf sur le deuxième nœud.

Redémarrez Keepalived sur vos deux machines pour vérifier qu’il n’y a pas d’erreur.

sudo service keepalived restart
[ ok ] Restarting keepalived keepalived....

Redémarrez vos machines :

sudo service shutdown -r now

Pour vérifier que ma première machine a bien été affectée de l’adresse IP 192.168.100.100, j’utilise la commande :

sudo ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:b1:04:3c brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.10/24 brd 192.168.100.255 scope global eth0
    inet 192.168.100.100/24 scope global secondary eth0
    inet6 fe80::20c:29ff:feb1:43c/64 scope link
       valid_lft forever preferred_lft forever

Donc tout est bon 🙂 Vous devez même pouvoir accéder en SSH par exemple à la première machine via l’IP 192.168.100.100.

Simulation de panne et test

Et si on s’amusait à péter la gueule du premier nœud ? Histoire de s’assurer que le deuxième prend le relai, à la bonne adresse ? Coupez brutalement la première machine et tentez de vous connecter en SSH à l’adresse 192.168.100.100.

sudo ip addr sh eth0 && hostname
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:ae:22:f8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.11/24 brd 192.168.100.255 scope global eth0
    inet 192.168.100.100/24 scope global secondary eth0
    inet6 fe80::20c:29ff:feae:22f8/64 scope link
       valid_lft forever preferred_lft forever
clio

J’ai bien réussi à accéder à l’IP 192.168.100.100, malgré le fait que mon premier nœud soit tombé et j’atterris bien sur le deuxième nœud, qui a pris le relais sans problème 🙂

Conclusion

Me voilà donc maintenant en présence d’un SAN hautement disponible. Nous pourrions bien sur aller plus loin en doublant les cartes réseau par exemple mais mes ressources matérielles ne sont malheureusement pas illimitées.

L’étape suivante consistera à installer le serveur de virtualisation. J’ai choisi pour cela l’hyperviseur open source Proxmox, qu’il faudra que je « branche » à mes targets iSCSI. Cela fera l’objet d’un prochain billet où nous partirons à la découverte de ce fabuleux outil qu’est Proxmox. D’ici là je vous souhaite bonne manip’ et n’hésitez pas à partager vos expériences ou remarques via les commentaires.

😉


Source d’inspiration :

 

Cet article vous a plu ? Partagez-le sur les réseaux sociaux !

Twitter Facebook Google Plus email