Aller au contenu | Aller au menu

/var/log/greg.log

Mot-clé - cluster

Fil des billets - Fil des commentaires

GlusterFS: création des packages Debian

Des packages existent déjà, merci à Leonardo Rodrigues de Mello. Mais ils sont en version 1.3.8, et depuis pas mal de bugs ont été corrigés, de nouvelles features sont apparues, il m'a parut nécessaire de construire mes propres packages.

Une version modifiée de FUSE est conseillée, et après l'installation et quelques mois d'utilisation non-intensive, je n'ai pas rencontré de problèmes.

  • Pour les packages fuse, je ne les ai pas recompilé, il existe déjà en version patchées.
gregbox:/usr/src/glusterfs# wget "http://lmello.virt-br.org/debian/fuse/libfuse2_2.7.2-glfs8-0_amd64.deb"
gregbox:/usr/src/glusterfs# wget http://lmello.virt-br.org/debian/fuse/libfuse-dev_2.7.2-glfs8-0_amd64.deb
gregbox:/usr/src/glusterfs# wget http://lmello.virt-br.org/debian/fuse/fuse-utils_2.7.2-glfs8-0_amd64.deb
  • l'installation :
gregbox:/usr/src/glusterfs# dpkg -i libfuse2_2.7.2-glfs8-0_amd64.deb libfuse-dev_2.7.2-glfs8-0_amd64.deb
Selecting previously deselected package libfuse2.
(Reading database ... 45253 files and directories currently installed.)
Unpacking libfuse2 (from libfuse2_2.7.2-glfs8-0_amd64.deb) ...
Selecting previously deselected package libfuse-dev.
Unpacking libfuse-dev (from libfuse-dev_2.7.2-glfs8-0_amd64.deb) ...
Setting up libfuse2 (2.7.2-glfs8-0) ...

Setting up libfuse-dev (2.7.2-glfs8-0) ...
  • pour les packages gluster, ceux de lmello datent un peu, je décide donc de construire la dernière version 1.3.12 à partir de ses sources.
# http://github.com/NeilW/deb-glusterfs/tree/master
gregbox:/usr/src/glusterfs# tar xzf NeilW-deb-glusterfs-5b5312670fa6c3a87c25df577cda8c0f8198cc06.tar.gz
gregbox:/usr/src/glusterfs# mv NeilW-deb-glusterfs-5b5312670fa6c3a87c25df577cda8c0f8198cc06 deb-glusterfs
  • on récupère les sources 1.3.12
# récupération des sources de gluster
gregbox:/usr/src/glusterfs# wget http://ftp.gluster.com/pub/gluster/glusterfs/1.3/glusterfs-CURRENT.tar.gz
gregbox:/usr/src/glusterfs# tar xzf glusterfs-CURRENT.tar.gz
# suppression de patchs inutiles avec cette version :
gregbox:/usr/src/glusterfs/deb-glusterfs# rm debian/patches/02patch-server-vol-spec.patch
# on édite le changelog pour changer la version
gregbox:/usr/src/glusterfs/deb-glusterfs# vim debian/changelog
gregbox:/usr/src/glusterfs/deb-glusterfs# aapt-get install cdbs debhelper bison flex libibverbs-dev  help2man libdb4.4-dev
  • enfin, la construction elle meme. Oui, ils sont construit sous root, c'est mal, pas bien, ne reproduisez pas ça chez vous :
gregbox:/usr/src/glusterfs/deb-glusterfs# dpkg-buildpackage
gregbox:/usr/src/glusterfs/deb-glusterfs# ls -altr .. | grep 1.3.12
drwxrwxrwx 10 mysql users    4096 2008-09-02 17:39 glusterfs-1.3.12
-rw-r--r--  1 root  src    783616 2008-09-18 15:16 glusterfs_1.3.12-0.tar.gz
-rw-r--r--  1 root  src       821 2008-09-18 15:16 glusterfs_1.3.12-0.dsc
-rw-r--r--  1 root  src     12790 2008-09-18 15:18 glusterfs-examples_1.3.12-0_all.deb
-rw-r--r--  1 root  src     17862 2008-09-18 15:18 glusterfs-client_1.3.12-0_amd64.deb
-rw-r--r--  1 root  src     10740 2008-09-18 15:18 glusterfs-server_1.3.12-0_amd64.deb
-rw-r--r--  1 root  src    363240 2008-09-18 15:18 libglusterfs0_1.3.12-0_amd64.deb
-rw-r--r--  1 root  src     84916 2008-09-18 15:18 libglusterfs-dev_1.3.12-0_amd64.deb
-rw-r--r--  1 root  src    971132 2008-09-18 15:18 glusterfs-dbg_1.3.12-0_amd64.deb
-rw-r--r--  1 root  src      1603 2008-09-18 15:18 glusterfs_1.3.12-0_amd64.changes
  • installation des packages :
gregbox:/usr/src/glusterfs/deb-glusterfs# dpkg -i ../*1.3.12*.deb
(Reading database ... 46297 files and directories currently installed.)
Preparing to replace glusterfs-client 1.3.10-1 (using .../glusterfs-client_1.3.12-0_amd64.deb) ...
Unpacking replacement glusterfs-client ...
Preparing to replace glusterfs-dbg 1.3.10-1 (using .../glusterfs-dbg_1.3.12-0_amd64.deb) ...
Unpacking replacement glusterfs-dbg ...
Preparing to replace glusterfs-examples 1.3.10-1 (using .../glusterfs-examples_1.3.12-0_all.deb) ...
Unpacking replacement glusterfs-examples ...
Preparing to replace glusterfs-server 1.3.10-1 (using .../glusterfs-server_1.3.12-0_amd64.deb) ...
Stopping GlusterFS server: glusterfsd.
Unpacking replacement glusterfs-server ...
Preparing to replace libglusterfs0 1.3.10-1 (using .../libglusterfs0_1.3.12-0_amd64.deb) ...
Unpacking replacement libglusterfs0 ...
Preparing to replace libglusterfs-dev 1.3.10-1 (using .../libglusterfs-dev_1.3.12-0_amd64.deb) ...
Unpacking replacement libglusterfs-dev ...
Setting up glusterfs-examples (1.3.12-0) ...
Setting up libglusterfs0 (1.3.12-0) ...

Setting up libglusterfs-dev (1.3.12-0) ...
Setting up glusterfs-client (1.3.12-0) ...
Setting up glusterfs-dbg (1.3.12-0) ...
Setting up glusterfs-server (1.3.12-0) ...
Installing new version of config file /etc/glusterfs/glusterfs-server.vol ...
Starting GlusterFS server: glusterfsd.

And voilà ! C'était facile, même si le package source de Leonardo m'a amplement simplifié la tâche. Une autre méthode possible aurait été d'utiliser les debhelpers (dh_make).

Présentation de GlusterFS

Présentation

  • Gluster.org
  • Création d'un cluster de fichiers à la fois serveur et client

logo glusterfs

Avantages

  • GlusterFS est comparable à NFS, en beaucoup plus performant, plus scalable et prévu pour la haute-dispo.
  • Le wiki est complet avec beaucoup de docs et de tutorials.
  • L'architecture du projet permet d'empiler les fonctionnalités, on peut donc mixer les fonctionnalités pour faire du mirroring, striping, unification, read-ahead, write-behind, encryption etc.
  • Automagic self-healing si un serveur tombe.
  • Roadmap importantes avec plein de fonctionnalités intéressantes comme le mod apache, hot-plug de brick, interface web, etc.

Inconvénients

  • Le projet est jeune.
  • pas vraiment de retour d'expériences en environnement de production.
  • Fonctionne en Userspace (FUSE) plutôt que dans un module kernel. Voir les implications sur les perfs.
  • la doc est uniquement dans le wiki, un trac serait mieux...
  • à vérifier: les données ne semble synchronisés qu'une fois lu, c'est à dire que si on écrit un fichier sur serveur B, les données sont tout de suite lisible, MAIS si on écrit d'autres fichiers sur serveur B, et qu'on ne les lit pas, ils ne sont pas synchronisés. Il faut donc forcer une lecture, par exemple:
find /mnt/rep -type f -exec head -n 1 {} \;
ou, plus efficace :
find /mnt/rep -type f -mtime -1 -exec head -c 1 {} > /dev/null \;

Dans le prochain billet: l'installation.

Session PHP: Le choix

Voilà, j'ai pu passer un peu de temps sur le gestionnaire de session mcache, enfin, surtout à compléter le peu de docs que j'avais sur ce sujet. J'ai rapidement écarté mcache de mes choix, ayant un sentiment moyen, de soft pas finit, un sentiment du genre je vais avoir des problèmes avec ce truc, je sais pas pourquoi.

Déjà, il ne fonctionne qu'en 32 bits, ce qui confirme mon sentiment de soft pas finit / plus maintenu. Ensuite, dans la doc, je suis tombé sur l'appendix B, je cite: Can mcache be set up to work across a cluster of computers? No puis; sur l'appendix C: Is mcache redundant? No J'ai du loupé un chapitre ! Exit mcache.

Passons à plus intéressant: sharedance. Trivial à installer, je l'ai d'abord mis en place sur notre serveur de développement, puis j'ai fais quelques scripts de tests: stockage d'objets énormes (24Mo), mesure des temps.... mmmh ça fonctionne bien ! Aller soyons fou, je développe un script PHP pour.... la prod. Afin de ne pas affecter le site de production en cas de plantage de sharedance, ou du serveur, je rajoute sur la page principale 2 appels AJAX sur mon script:

Le premier stocke une valeur envoyé par l'appel ajax en GET, puis sur le retour de l'ajax j'appel une 2ème fois le script avec un paramètre lui demandant de récupérer la valeur précédemment stockée et de comparer avec le meme GET. Puis, je lui demande de stocker les temps de PUT, les temps de FETCH des valeurs, temps totals, les erreurs détectés.... et je lui demande aussi de stocker une chaine de 1 millions de caractères, ce qui créé des fichiers de sessions de 1.2Mo. Histoire de le soliciter encore plus, j'ai paramétré sharedance pour que les sessions expirent au bout de seulement 60 secondes, ce qui provoque des "clean" plus souvent.

Avec ce test réel, on est monté à environ 900 sessions pour 1.2Go de données sur la partition tmpfs de 2Go.

Sharedance cpu-network

Ce graph représente à droite l'utilisation CPU, à gauche le traffic réseau. En haut le serveur sharedance, en bas un des serveurs PHP. On voit nettement quand j'ai arrêté le test à 17:13. On peut constater que le serveur sharedance encaisse 300Mb/s entrant + autant en sortant, sans broncher ! La charge du serveur n'a jamais atteint 1, le serveur ayant 4 coeurs (bi-dual). Via un top, je constate aussi que sharedance utilise de manière homogène les 4 coeurs.

Les petits pics rouge sur le graph CPU de sharedance sont du à un cron qui se lance pour analyser les temps mini, avg et max stockés dans les sessions.

Les dernières stats :

  • Sessions: 1082
  • put mini: 0.000153
  • put avg: 0.019551
  • put max: 0.260032
  • fetch mini: 0.003848
  • fetch avg: 0.041149
  • fetch max: 0.525085
  • total min: 0.001805
  • total avg: 0.343540
  • total max: 0.981712

Je n'ai pas eu le temps de faire un beau graph excel :) On voit qu'il a mis au maximum 0.9 seconde pour stocker puis récupérer 1.2Mo de données, auquel il faudrait soustraire les temps d'accès aux pages PHP x2 !!

Le choix est fait !

Les gestionnaires de sessions PHP

Actuellement, pour les sessions, nous utilisons un gros serveur et MySQL avec des tables en HEAP pour stocker les sessions. Problème, ces tables ne supportent pas les types BLOB et TEXT, ce qui implique d'utilise un champ VARCHAR, limité à 255 caractères, on atteint très vite cette limite.

Je suis donc à la recherche d'alternatives, sachant qu'on va stocker plus d'informations pour éviter au maximum les cookies, et que les performances requises sont importantes: aujourd'hui environ 2000 requêtes de sessions / secondes, demain ce sera bien pire à cause du web 2.0.

MySQL Cluster

MySQL n'est pas encore sortie en version stable en 5.1, version nécéssaire pour avoir un MySQL Cluster. Avec tous les problèmes que l'on rencontre avec 5.1 (enfin, uniquement les nouvelles fonctionnalités), le temps de mise en oeuvre, le coût des serveurs, cette solution est fortement compromise. D'autant plus que MySQL n'utilise pas sa propre solution pour ses propres besoins...

Zend Cluster

Alléchant sur le papier, mais beaucoup trop cher ! Ils vont devoir s'aligner pour espérer continuer à en vendre...

memcached

http://www.danga.com/memcached/

Comme stipulé à plusieurs endroits dans la doc, memcached est un serveur de cache avant tout. Ce qui veut dire perte de données en cas d'arrêt du démon. Il a été prévu pour faire du cache, et le fait d'ailleurs très bien. Son modèle cluster est orienté scalability et pas du tout redondance ni failover. Admettons que nous avons 3 serveurs memcached en cluster, A B et C. A chaque requête PHP en écriture (ajout, remplacement d'une session), le client se connecte à tous les serveurs, créé une clef en fonction de ces serveurs, et choisis un des serveurs: B. Seul B aura la valeur pour cette clef. La requête suivante, en lecture, veut lire cette clef, le client PHP se connecte aux 3 serveurs, génère la clef, et va chercher la valeur sur B. Très bien, on répartie la charge sur ces 3 serveurs, et la mémoire n'est pas gaspillé car les données ne sont pas duppliqué. Ainsi, si B tombe, on perd uniquement les données de sessions de ce serveur, on déconnecte donc seulement 1/3 des utilisateurs. Seulement voilà, c'est pas aussi beau. Si un noeud tombe, la liste des serveurs dans le pool change, et le client va regénérer toutes les clefs !! En d'autre terme, si un noeud tombe, on perd tout le cache ! On se retrouve donc avec autant de POF (Point Of Failure) que de serveurs. Dropped.

memcachedb

http://memcachedb.org/

Reprenant le moteur de memcached, le principe est différent, et cette fois le but n'est pas de faire du cache mais de stocker des données persistentes. En mode cluster, on a un fonctionnement identique à MySQL: un noeud est maitre, les autres noeuds répliquent et peuvent être accédé en lecture. Les performances sont là, leur benchmark indique atteindre 20000 écritures / secondes, et 45000 lectures / secondes, ce qui est amplement suffisant. Mais le principe du single master to many slaves est genant: il m'arrive régulièrement de retirer un serveur de la production, pour le mettre à jour, le restaurer, ou en cas de problèmes hardware... et si c'est le master qui a un problème ? on doit créer un autre master, et changer la config des slaves afin qu'ils répliquent leurs données depuis un autre master ! Dropped.

Sharedance

http://sharedance.pureftpd.org/

Ce logiciel a été créé pour cet usage et uniquement pour cet usage. Tout comme memcached, il excèle dans son travail. Tous les commentaires que j'ai pu trouvé sur le net en font l'éloge, et surtout on retrouve tout le temps "Ca n'a jamais planté". Un utilisateur atteint 200Mbps x 2 sur un seul serveur, époustouflant ! C'est la solution quasiment idéal... et oui, le soucis, c'est que c'est un SPOF ! Si ce serveur tombe, on n'a plus de sessions. Alors on pourrait implémenter un 2ème serveur avec Heartbeat, mais ce 2ème serveur n'aurait pas les données, en cas de crash on déconnecte alors tout le monde. Sharedance reste pour l'instant la meilleur solution, même si je ne l'ai pas encore testée, ça ne saurait tardé. Il manquerait une réplication type DRBD sur une partition tmpfs, pour allier performance et failover.

mcache

http://www.mohawksoft.org/?q=node/8

mcache semble le produit idéal, sur le papier. Il stock les données en ram et les copie (si besoin) sur disque régulièrement, possède un garbage collector pour supprimer les sessions périmées, et fonctionne en environnement distribué: un mcache par serveur PHP. Il faut que je le mette en place avec plusieurs noeuds, et vérifier les points suivants : si un noeud tombe, que se passe t'il ? Il faut aussi valider les performances.

Je vais donc créer plusieurs images Xen 32bits afin de tester mcache, et en parallèle tester sharedance. La suite aux prochains billets !