architecture
Réplication de serveurs Memcached
par guiguiabloc le 08 sept, 2009, sous architecture, linux
C’est la rentrée, j’espère que les vacances se sont bien passées pour tout le monde, et que, comme moi, vous avez énormément pris sur vous en croisant un panneau « Wi-Fi libre accès » sous les regards noirs et appuyés de Madame… :-p (le même regard qu’elle vous jettera d’ailleurs quand, sur la plage, refoulant le souvenir de cette borne Wi-Fi, vos yeux glisseront subrepticement sur le corps de la jeune demoiselle à quelques pas de vous, quand elle dégrafera son haut de maillot de bain…) BREF !!!
Fin de l’encart « vacances perverses »
et je vous souhaite une bonne reprise quand même
Nul besoin de vous refaire une présentation de Memcached dont j’avais abordé le sujet précédemment.
Vous l’utilisez parce que vous avez une forte charge sur vos serveurs et vous avez été conquis par ses performances, et c’est bien
Comme vous le savez, fidèles lecteurs (ou pas) de ce blog (et je vous en remercie, c’est toujours très agréable de savoir que le temps passé a tester et écrire des articles est au moins lu par quelques milliers dizaines de personnes
), j’aborde assez souvent la notion de haute-disponibilité.
Outre l’incomparable avantage de permettre au Sysadmin de pouvoir terminer sa nuit tranquillement sans devoir se rendre a 4h du matin au Datacenter pour remettre en service un serveur capricieux, elle permet surtout de disposer d’une infrastructure solide et disponible de façon quasi-permanente qui feront les joies de votre DI/RSI/DRH/DAF etc. etc. (liste non exhaustive).
Dans cette architecture hautement disponible, vous avez greffé un serveur memcached (ou pour soulager vos serveurs de base de données, ou pour distribuer du contenu statique, ou gérer vos sessions utilisateurs, ou que sais-je encore…).
Oui mais voila, si le serveur Memcached tombe, et bien ca colle quand même un frein à vos performances en attendant qu’il reparte.
Nous aurions bien évidemment pu installer un deuxième serveur Memcached en secours et basculer une ip flottante type fail-over/carp sur l’esclave en cas de panne du Maître mais il faut repeupler le cache… Pas très sexy comme méthode (même si efficace).
Je vous propose donc une autre solution, une réplication Memcached entre X serveurs de ce type.
(et là vous pouvez faire « Oooohhh »)
- REPCACHED
Pour cette solution, nous allons utiliser le projet REPCACHED qui ajoute a Memcached les fonctions de réplication dont vous trouverez les sources sur :
http://sourceforge.net/projects/repcached/files/
Parmi ses fonctionnalités :
- multi master replication.
- asynchronous data replication.
- support all memcached command (set, add, delete, incr/decr, flush_all, cas)
Par contre, si l’on peut reprocher quelque chose à ce projet dans l’état actuel des choses, c’est son manque quasi total de documentation
Deux types de sources sont disponibles :
- 1 patch version 2.2 pour Memcached (version 1.2.8 à l’heure où j’écris)
ou
- L’ensemble complet Repcached 2.2 + Memcached 1.2.8
Le seul pré-requis est d’avoir l’API libevent (un apt-get install libevent-dev sous Debian suffira)
L’installation en mode patch est la suivante :
$ wget http://memcached.googlecode.com/files/memcached-1.2.8.tar.gz $ tar zxf memcached-1.2.8.tar.gz $ cd memcached-1.2.8.tar.gz $ wget http://downloads.sourceforge.net/project/repcached/repcached/2.2-1.2.8/repcached-2.2-1.2.8.patch.gz $ gzip -cd repcached-2.2-1.2.8.patch.gz | patch -p1
Pour les deux modes (patch ou full sources) :
$ ./configure --enable-replication $ make $ make install
Désormais, vous avez des options supplémentaires pour le lancement du démon :
Guiguiabloc-a:/opt/memcached/bin$ ./memcached -h memcached 1.2.8 repcached 2.2 ... -x hostname or IP address of peer repcached -X TCP port number for replication (default: 11212)
Le fonctionnement est assez basique.
Vous démarrez le premier serveur en lui passant l’option -x adresse_ou_ip_partenaire
memcached@Guiguiabloc-a:~/bin$ ./memcached -d -x Guiguiabloc-b memcached@Guiguiabloc-a:~/bin$
Le serveur Memcached utilise par défaut le port 11212 pour la réplication, pensez à ouvrir votre firewall.
Maintenant nous allons démarrer le deuxième serveur en lui passant l’option -x
memcached@Guiguiabloc-b:~/bin$ ./memcached -d -x Guiguiabloc-a memcached@Guiguiabloc-b:~/bin$
Ne reste qu’à tester.
Injectons un couple clé/valeur sur le maître directement par telnet.
NB: Vous trouverez sur http://lzone.de/articles/memcached.htm un récapitulatif des commandes existantes (Merci a Fred (le seul geek que je connaisse qui écoute « Oh chéri chéri » de Karen Cheryl » en boucle sur son Ipod) pour le lien)
memcached@Guiguiabloc-a:~/bin$ telnet Guiguiabloc-a 11211 Trying 192.168.50.1... Connected to guiguiabloc-a. Escape character is '^]'. get url END set url 1 0 19 blog.guiguiabloc.fr STORED get url VALUE url 1 19 blog.guiguiabloc.fr END
En détails, je vérifie s’il existe une valeur pour la clé « url » (get url).
La réponse est négative, je stocke donc la clé « url », 1 signifiant « arbitrary metadata », 0 « n’expire jamais », 19 bytes de longueur, et la valeur.
On redemande la clé « url », c’est bon.
Maintenant sur le deuxième serveur :
memcached@Guiguiabloc-b:~/bin$ telnet guiguiabloc-b 11211 Trying 192.168.50.2... Connected to guiguiabloc-b. Escape character is '^]'. get url VALUE url 1 19 blog.guiguiabloc.fr END
Un succès !
Vous pouvez tester dans l’autre sens, en modifiant la valeur de la clé « url » sur le deuxième serveur, elle sera modifiée sur le premier.
En coupant brutalement l’un des deux et en le relancant, vous verrez que son cache se met a jour automatiquement via la réplication Memcached.
memcached@Guiguiabloc-a:/opt$ telnet guiguiabloc-a 11211 Trying 192.168.50.1... Connected to Guiguiabloc-a. Escape character is '^]'. get url VALUE url 1 19 blog.guiguiabloc.fr END quit Connection closed by foreign host. memcached@Guiguiabloc-a:/opt$ killall memcached memcached@Guiguiabloc-a:/opt$ ps aux | grep memcached 1002 5927 0.0 0.2 4168 1068 pts/0 S 19:26 0:00 su - memcached 1002 5966 0.0 0.1 3344 744 pts/0 S+ 19:39 0:00 grep memcached memcached@Guiguiabloc-a:~/bin$ ./memcached -d -x guiguiabloc-b memcached@Guiguiabloc-a:~/bin$ telnet guiguiabloc-a 11211 Trying 192.168.50.1... Connected to guiguiabloc-a. Escape character is '^]'. get url VALUE url 1 19 blog.guiguiabloc.fr END
Bilan, un excellent outil de haute-disponibilité qui inclut enfin le double sens de réplication (dans les versions antérieures (1.0), il fallait définir le Maître en le démarrant sans paramètres et l’esclave en lui passant l’option -x. En cas de crash du Maître, l’esclave devenait Maître. Le failback se réglait en lancant l’ancien Maître avec l’option -x.
On peut juste regretter l’absence quasi totale de documentation et même si le projet a bientôt 2 ans, il semble particulièrement mature pour de la production. A suivre donc.
Amusez-vous bien
MogileFS, un système de fichier distribué différent
par guiguiabloc le 13 mai, 2009, sous architecture, linux
J’ai souvent abordé sur ce blog les différents moyens de disposer de données redondantes dans une architecture en Haute-disponibilité.
Aujourd’hui je vais vous présenter une solution un peu plus méconnue pour certains d’entre vous, mais qui mérite tout son intérêt.
MogileFS est un système de fichier distribué en mode user.
Philippe Nicolas, sur son blog, en donne une définition parfaite :
« MogileFS est une émanation de Danga Interactive, acquis par Six Apart, qui pour ses projets de développement Web a mis au point ses propres souches logicielles.
MogileFS est un système de fichiers distribué open source en mode user, attention non conforme au standard POSIX, complètement redondant offrant un mécanisme de réplication de fichiers,
sans contrainte de systèmes de fichiers locaux, dont l’esprit est un mode shared-nothing par simple agrégation de machines indépendantes.
L’approche est asymétrique avec la notion de noeuds de stockage, de machines dites « trackers » et de machines database sachant que certains de ces fonctions peuvent résider sur le même système.
L’évolutivité vient de ce « collage » de machines afin de constituer un ensemble de taille importante.
MogileFS est donc une solution simple, gratuite et facile à mettre en place sans risque de planter le système. »
Par les avantages de MogileFS :
- il agit au niveau applicatif et ne dépend donc pas d’un module du noyau
- Les trois composants de MogileFs peuvent fonctionner indépendamment et sur plusieurs serveurs
- MogileFS gère la réplication automatisée
- Il détient sa propre base d’identification des fichiers
etc…
(je vous laisse lire la présentation sur leur site http://www.danga.com/mogilefs/ et http://mogilefs.pbwiki.com/HighLevelOverview
Si vous doutez encore de ses capacités, sachez que son auteur n’est autre que Bradley Fitzpatrick qui, pour ceux qui ne le connaîtrait pas encore, fait partie de l’équipe Danga Interactive a qui l’on doit, entre autre, Memcached.
Sachez enfin que MogileFS est utilisé par Digg (220 millions de pages vues par mois…) ou la plateforme Skyrock (5 milliards de pages vues par mois), voila qui devrait piquer votre curiosité.
- Présentation générale
MogileFS est constitué de 3 composants :
- une base de données MySQL
- le « Tracker » ou client de transfert (terme bien connu chez certains
) - le noeud de stockage (mogstored)
Chaque composant est indépendant, vous pouvez donc les mixer (2 serveurs tracker+stockage, 2 serveurs stockage + 3 serveurs trackers etc….)
Concernant la base Mysql, tout dépend de votre infrastructure. Si vous disposez déjà d’une ferme Mysql, autant l’utiliser, sinon vous pouvez installer une simple solution master/slave sur 2 machines.
- Installation
Les prérequis sont assez importants, un serveur Mysql bien sûr et plusieurs modules Perl dont MogileFS a besoin.
Sous une Debian :
apt-get install libio-socket-ssl-perl libbsd-resource-perl libcompress-zlib-perl libnet-netmask-perl libio-stringy-perl libwww-perl
Création de l’utilisateur dédié :
useradd mogilefs mkdir /etc/mogilefs
Je vous conseille de récupérer les dernières sources via Subversion
apt-get install subversion cd /etc/mogilefs svn checkout http://code.sixapart.com/svn/mogilefs/trunk/
Récupérons les modules Perl nécessaires :
perl -MCPAN -e shell
(si vous n’avez jamais utilisé le shell CPAN, laisser les choix par défaut, et sélectionnez Europe/France puis un site FTP)
cpan> install Danga::Socket CPAN: Storable loaded ok ... Writing Makefile for Danga::Socket ---- Unsatisfied dependencies detected during [B/BR/BRADFITZ/Danga-Socket-1.61.tar.gz] ----- Sys::Syscall Shall I follow them and prepend them to the queue of modules we are processing right now? [yes] ... Running make install Installing /usr/local/share/perl/5.8.8/Danga/Socket.pm Installing /usr/local/man/man3/Danga::Socket.3pm Writing /usr/local/lib/perl/5.8.8/auto/Danga/Socket/.packlist Appending installation info to /usr/local/lib/perl/5.8.8/perllocal.pod /usr/bin/make install -- OK cpan>
faites de même pour
install DBI install IO::AIO install Path::Class install List::MoreUtils install Perlbal install Gearman::Client install Gearman::Server install Gearman::Client::Async
Installation de MogileFS (mogilefsd, mogstored) et des outils
cd /etc/mogilefs/trunk/server perl Makefile.PL make make install cd /etc/mogilefs/trunk/ Guiguiabloc-a:/etc/mogilefs/trunk# cd api/perl/MogileFS-Client Guiguiabloc-a:/etc/mogilefs/trunk/api/perl/MogileFS-Client#perl Makefile.PL make install Guiguiabloc-a:/etc/mogilefs/trunk/server# cd ../utils/ Guiguiabloc-a:/etc/mogilefs/trunk/utils# perl Makefile.PL
Installation de la base de données
Guiguiabloc-a:~# mysql -u root -p -h guiguiabloc-mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 Server version: 5.0.51 Guiguiabloc distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> create database mogilefs ; Query OK, 1 row affected (0.00 sec) mysql> grant all on mogilefs.* TO 'mogile'@'%' identified by 'password' ; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges ; Query OK, 0 rows affected (0.00 sec)
On charge le schéma :
Guiguiabloc-a:~# mogdbsetup --dbhost=guiguiabloc-mysql --dbname=mogilefs --dbuser=mogile --dbpass=password This will attempt to setup or upgrade your MogileFS database. It won't destroy existing data. Run with --help for more information. Run with --yes to shut up these prompts. Continue? [N/y]: y Guiguiabloc-a:~#
Configuration de Mogstored (noeud de stockage)
Pour les noeuds de stockage, création du répertoire dédiée à cela :
Guiguiabloc-a:~# mkdir /data Guiguiabloc-a:~# chown -R mogilefs /data
Puis création d »un « device » (un répertoire spécifique pour une application par exemple)
Attention, 1 device par noeud de stockage
Guiguiabloc-a:~# mkdir /data/dev1 Guiguiabloc-a:~# chown -R mogilefs /data/dev1
On prépare le fichier de configuration pour le démon de stockage :
/etc/mogilefs/mogstored.conf httplisten=0.0.0.0:7500 mgmtlisten=0.0.0.0:7501 docroot=/data
Fichier de configuration de mogilfsd
cp /etc/mogilefs/trunk/server/conf/mogilefsd.conf /etc/mogilefs/mogilefsd.conf #daemonize = 1 db_dsn = DBI:mysql:mogilefs:host=guiguiabloc-mysql db_user = mogile db_pass = password listen = 192.168.0.1:7001 conf_port = 7001 listener_jobs = 10 delete_jobs = 1 replicate_jobs = 5 mog_root = /data reaper_jobs = 1
Maintenant que tout cela est paramétré, lançons les services :
TRACKER :
su mogilefs -c ‘mogilefsd -c /etc/mogilefs/mogilefsd.conf –daemon’
STORAGE :
mogstored –daemon
Les commandes d’administration se font avec « mogadm ».
Vérifions les trackers (les miens écoutent sur le port 7001) :
mogadm --tracker=192.168.0.1:7001 check Checking trackers... 192.168.0.1:7001 ... OK Checking hosts... No devices found on tracker(s).
Maintenant, peuplons la base de données en lui indiquant les noeuds de stockages
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 host add Guiguiabloc-b --ip=192.168.0.2 --port=7500 --status=alive Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.2:7001 check Checking trackers... 192.168.0.2:7001 ... OK Checking hosts... [ 1] Guiguiabloc-a ... OK [ 2] Guiguiabloc-b ... OK Checking devices... host device size(G) used(G) free(G) use% ob state I/O% ---- ------------ ---------- ---------- ---------- ------ ---------- ----- ---- ------------ ---------- ---------- ---------- ------ total: 0.000 0.000 0.000 0.00%
Il faut ajouter les « devices »:
Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device add guiguiabloc-a 1 Guiguiabloc-a:/etc/mogilefs# mogadm --tracker=192.168.0.1:7001 device list Guiguiabloc-a [1]: alive used(G) free(G) total(G) dev1: alive 0.767 2.897 3.664 Guiguiabloc-b [2]: alive used(G) free(G) total(G) dev2: alive 0.762 2.902 3.664
Vous pouvez maintenant faire vos premiers tests :
Création d’un « domaine » et d’une « class » de test
(lire http://mogilefs.pbworks.com/Definitions)
Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 domain add testguiguiabloc Guiguiabloc-a:/var# mogadm --tracker=192.168.0.2:7001 class add testguiguiabloc classguiguiabloc
Faisons un petit test à la mano pour insérer un fichier
Guiguiabloc-a:/etc# mogtool --tracker=192.168.0.2:7001 --domain=testguiguiabloc --class=classguiguiabloc inject motd motd file motd: a46d249bd6d5f650b29048b4a2e7d610, len = 357 Spawned child 9943 to deal with chunk number 1. chunk 1 saved in 0.11 seconds. Child 9943 successfully finished with chunk 1. Replicating: 1
Une petite vérification sur nos deux noeuds de stockage nous montre que le fichier a bien était dupliqué :
Guiguiabloc-a:/etc# ls /data/dev1/0/000/000/ 0000000003.fid Guiguiabloc-b:/etc# ls /data/dev2/0/000/000/ 0000000003.fid
Sympa, non ?
Il ne vous reste plus qu’à utiliser la librairie cliente de votre choix (Ruby, Perl, Java, Python, Php etc…) dans votre application pour appeler vos trackers et vos fichiers stockés.
Amusez vous bien
Interception des erreurs applicatives dans Nagios avec SEC et Prelude-lml
par guiguiabloc le 18 mar, 2009, sous architecture, linux
Ce billet est né d’une demande de mon ami « Poupinade » qui connaissant mon goût pour les challenges divers et variés, me demanda avec fourberie innocemment comment je ferais, moi, pour intercepter des erreurs applicatives dans Nagios.
Nagios est un outil de surveillance système et réseau. Largement éprouvé, il est déployé fréquemment pour monitorer les équipements, services etc…
Pour moi, il reste un outil d’alerte et doit être utilisé comme tel. Je ne pense pas que ce soit à lui de remonter des informations détaillées sur un problème quelconque, mais de permettre au « superviseur » de débrancher sur un autre outil s’il veut peaufiner la cause de la panne/alerte (ceux qui utilisent un Nagios avec plus de 1000 hôtes et une dizaine de services par machine me comprendront aisément
).
Je ne m’étendrais pas sur Nagios ici, encore moins sur son installation et son paramétrage.
Vous trouverez de nombreuses références et tutos sur le Nain Ternet pour vous aider à sa mise en place.
La problématique qui se pose ici est de permettre d’être informer rapidement en cas d’erreur dans les logs d’une application.
Car oui on peut surveiller le bon fonctionnement du serveur httpd, de la Base de Données, du lien réseau etc… , mais il peut arriver qu’un autre problème surgisse et que Nagios ne supervise pas.
Je simplifie à l’extrême le concept « application » et prenant comme exemple une application « web », libre à vous d’adapter ce billet à autre chose.
Dans les exemples qui suivront et pour la maquette d’architecture choisie, j’ai pris un simple site en php (en l’occurrence un FlySpray ) qui me sert au suivi de mes « travaux » (a la manière d’OVH).
Les erreurs rencontrées par une « application » sont dans la majorité des cas lisibles dans un fichier de log dédié.
Première chose, faire « tomber » les erreurs php dans le log d’erreur du Vhost d’apache :
Edition du php.ini : error_reporting = E_ALL & ~E_NOTICE display_errors = On Configuration du vhost : ServerName application.guiguiabloc.fr DocumentRoot /var/www/application ErrorLog /var/log/apache2/application-error.log LogLevel warn CustomLog /var/log/apache2/application-access.log combined
Toujours a des fins de test, je simule une erreur critique, la perte de liaison avec le serveur de base de données.
En l’occurrence, j’ajoute une entrée dans le /etc/hosts du serveur httpd avec une fausse adresse IP vers le serveur Mysql, ce qui génère l’erreur suivante :
[Sun Mar 15 17:27:09 2009] [error] [client 192.168.0.2] PHP Warning: mysqli_real_connect(): (HY000/2003): Can't connect to MySQL server on 'mysql-serveur' (113) in /var/www/application/adodb/drivers/adodb-mysqli.inc.php on line 108
Erreur je l’avoue très sournoise, Nagios me disant que mon serveur Mysql répond très bien et que le réseau entre le serveur applicatif et le serveur de base de données est opérationnel.
Comment surveiller ce genre de fichier et alerter Nagios quand quelque chose se produit ?
- SEC Simple Event Correlator
SEC est un programme écrit en Perl, extrêmement puissant et configurable à souhait, qui permet de scruter des fichiers de logs et d’y détecter des événements divers et variés.
Le site est ICI
Côté installation sur le serveur applicatif, pas de soucis :
srv-appli:/usr/local/src# wget http://prdownloads.sourceforge.net/simple-evcorr/sec-2.5.1.tar.gz srv-appli:/usr/local/src# tar xzvf sec-2.5.1.tar.gz srv-appli:/usr/local/src# cd sec-2.5.1 srv-appli:/usr/local/src/sec-2.5.1# mkdir /usr/local/bin/sec srv-appli:/usr/local/src/sec-2.5.1# mkdir /usr/local/bin/sec/etc srv-appli:/usr/local/src/sec-2.5.1# cp sec.pl /usr/local/bin/sec/
Une configuration toute simple :
srv-appli:/usr/local/bin/sec/etc# cat sec.conf type=Single ptype=RegExp pattern=error desc=$0 action=shellcmd /opt/nagios/libexec/eventhandlers/submit_check_result_via_nsca srv-appli 'Application' 2 "$0"
Ici, nous demandons à SEC de réagir sur la chaîne « error » (bien évidemment, vous pouvez affiner vos expression régulières…) et en cas de détection, d’exécuter la commande « /opt/nagios/libexec/eventhandlers/submit_check_result_via_nsca » avec en paramètre, le nom du host dans Nagios, le nom du service, le code retour Nagios et le message d’erreur.
Auparavant, vous avez ajouté une entrée de type « Passive » dans Nagios :
# NSCA
define service{
use passive_checkservice
host_name srv-appli
service_description Application
# ici la commande check_smtp n'a aucune signification particuliere
# c'est simplement que sans check_command cela ne marche pas !
check_command check_smtp
}Et oui, ce type de fonctionnement implique que vous utilisez NSCA sur le serveur d’application (surveillance passive de Nagios, c’est le serveur d’appli qui envoie l’alerte)
Vous devez sur votre Nagios, avoir une entrée de ce genre
Ne reste plus qu’à lancer le script SEC :
srv-appli:/# perl -w /usr/local/bin/sec/sec.pl -conf=/usr/local/bin/sec/etc/sec.conf -input=/var/log/apache2/application-error.log -log /var/log/sec.log SEC (Simple Event Correlator) 2.5.1 Reading configuration from /usr/local/bin/sec/etc/sec.conf 1 rules loaded from /usr/local/bin/sec/etc/sec.conf Stdin connected to terminal, SIGINT can't be used for changing the logging level
On provoque l’erreur
Executing shell command '/opt/nagios/libexec/eventhandlers/submit_check_result_via_nsca srv-appli 'Application' 2 "[Tue Mar 17 11:13:34 2009] [error] [client 192.168.99.14] PHP Warning: mysqli_real_connect(): (HY000/2003): Can't connect to MySQL server on 'mysql-serveur' (113) in /var/www/application/adodb/drivers/adodb-mysqli.inc.php on line 108"' Child 10131 created for command '/opt/nagios/libexec/eventhandlers/submit_check_result_via_nsca srv-appli 'Application' 2 "[Tue Mar 17 11:13:34 2009] [error] [client 192.168.99.14] PHP Warning: mysqli_real_connect(): (HY000/2003): Can't connect to MySQL server on 'mysql-serveur' (113) in /var/www/application/adodb/drivers/adodb-mysqli.inc.php on line 108"' 1 data packet(s) sent to host successfully.
Et l’alerte remonte dans Nagios :
Cela fonctionne mais bon…
Premier point bloquant, cela signifie que l’on utilise la surveillance Passive de Nagios (NSCA) sur le srv-appli, ce qui n’est pas forcément le cas.
Deuxième point bloquant, si une deuxième erreur surgit à la suite (pas de chance hein :-p), c’est celle ci qui sera affichée dans Nagios.
Je peux très bien acquitter l’alarme et passer à côté d’un problème plus crucial…
Pour le test :
srv-appli:/# echo « [Mon Mar 17 14:25:42 2009] [error] Une autre erreur » >> /var/log/apache2/application-error.log
Donc, obligation d’aller sur le serveur, de vérifier le /var/log/Sec.log….
Autre solution
- PRELUDE IDS
Prelude est un « Security Information Management » (SIM) Universel. Prelude collecte, normalise, catégorise, agrège, corrèle et présente tous les événements sécurité indépendamment de la marque ou de la licence du produit dont ces événements sont issus : il est « Agentless ».
Cela tombe très bien, j’avais déjà écrit un billet sur Prelude l’année dernière
http://blog.guiguiabloc.fr/index.php/2008/01/27/installer-et-configurer-prelude/
Vous ne serez pas pas dépaysé.
Pour scruter nos logs, nous allons utiliser un des modules de Prelude : Prelude-lml
Ce n’est pas le rôle premier de ce logiciel (qui est surtout un centralisateur d’alertes IDS/NIDS), mais rien nous interdit de le détourner de sa voie.
Je vous passe l’installation du module sur le serveur d’application ainsi que son enregistrement dans le Prelude Manager, tout est expliqué dans le billet précité.
srv-appli:/# prelude-adduser register prelude-lml "idmef:w admin:r" IP_Prelude_Manager --uid 1000 --gid 1000 prelude-manager:/:# prelude-adduser registration-server prelude-manager ... - prelude-lml registration to IP_Prelude_Manager successful
Une configuration succincte pour nos tests :
prelude-lml.conf : file = /var/log/apache2/application-error.log /etc/prelude-lml/ruleset/pcre.rules : regex=(\[error\]); include = appli.rules; include = single.rules; /etc/prelude-lml/ruleset/appli.rules : #LOG:[Sun Mar 15 17:27:09 2009] [error] [client 192.168.0.1] PHP Warning: mysqli_real_connect( ): regex=\[error\] \[client ([\d\.]+)\] ; \ classification.text=server error; \ id=44100; \ revision=1; \ analyzer(0).name=Appli; \ analyzer(0).manufacturer=blog.guiguiabloc.fr; \ analyzer(0).class=Service; \ assessment.impact.severity=high; \ assessment.impact.completion=failed; \ assessment.impact.type=other; \ assessment.impact.description=Erreur applicative; \ source(0).node.address(0).category=ipv4-addr; \ source(0).node.address(0).address=$1; \ source(0).service.iana_protocol_name=tcp; \ source(0).service.iana_protocol_number=6; \ target(0).service.iana_protocol_name=tcp; \ target(0).service.iana_protocol_number=6; \ last;
Je ne m’étendrais pas sur les expressions régulières, ni sur les normes IDMEF utilisées (cela prendrait un billet complet) et je vous invite à consulter ses pages :
https://trac.prelude-ids.org/wiki/PreludeLml
http://www.rfc-editor.org/rfc/rfc4765.txt
http://www.gscore.org/blog/index.php/post/2007/08/13/IDMEF-for-dummies-part-1
On reproduit de nouveau l’erreur qui maintenant est interceptée par Prelude-lml et envoyée au Manager
Déjà plus classieux comme système de centralisations, non
Et là vous me dites « Et comment je le sais tout cela dans Nagios ????? »
Grâce à la communauté Nagios
http://www.nagiosexchange.org/cgi-bin/page.cgi?g=Detailed%2F2287.html;d=1
Vous y trouverez le check_prelude.pl , fonctionnant en NRPE, qui vous permet d’aller vérifier le nombre d’entrées HIGH ou MEDIUM dans la base Mysql Prelude
Nagios remontera donc une alerte Critique ou Warning que vous acquitterez (ou pas :-p) avant d’aller vous connecter sur le Prelude Manager et vérifier la teneur exacte du message d’erreur applicatif et de le supprimer dès sa résolution.
Tout ceci est bien sûr un simple exercice de style, à prendre comme une piste de travail.
Je suis certain que vous trouverez d’autres solutions à mettre en oeuvre.
Amusez vous bien
Mise en oeuvre d’un système de fichier distribué et accès concurrents en SAN avec DRBD, ISCSI ,OCFS2 et DM-Multipath
par guiguiabloc le 16 fév, 2009, sous architecture, linux
Difficile de faire plus court en titre…
Je vous préviens tout de suite, ce billet risque d’être un peu long car après tout, j’ai passé du temps dessus, autant que vous en passiez, vous aussi, a me lire
Tous ceux qui ont déjà eu à mettre en oeuvre une quelconque solution de Haute-Disponibilité, se sont retrouvés un jour devant une problématique assez angoissante :
L’accès simultané (ou concurrent) à une ressource de données.
Si en lecture cela pose rarement des problèmes, en écriture, cela comment à devenir « légèrement » complexe.
Petit exemple.
Vous avez deux serveurs load-balancés (web ou autre), si vous écrivez une information sur le premier serveur, comment être sur qu’elle soit disponible sur le deuxième, et vice-versa.
Après tout, je peux aussi bien écrire sur le serveur A que sur le serveur B.
Retour en arrière donc pour vous expliquer la progression de mon raisonnement et la solution que j’ai mise en oeuvre.
Lorsque l’on désire avoir une synchronisation parfaite des données entre deux serveurs, la première méthode est d’utiliser un mode Actif/Passif (ou maître/esclave).
Le moyen le plus simple est de se baser sur DRBD dont j’avais déjà abordé le sujet ICI qui est une sorte de RAID Over IP.
La mise en place de drbd vous donne un nouveau périphérique de stockage (ou nouveau disque pour simplifier) de type /dev/drbdX.
En cas de panne du Maître, le service est basculé sur l’Esclave et les données accessibles par celui ci.
Le volume DRBD, appelé par exemple /dev/drbd0 est alors « monté » en système de fichier sur la machine passive qui devient alors, active.
Je parle bien entendu de synchronisation en mode « bloc », pas d’une synchronisation de fichiers comme le fait rsync ou autre.
Dans cet exemple, le système de fichier reste standard (ext2, ext3, reiser etc…).
Si maintenant vous avez décidé de mettre en oeuvre un loadbalancing suite à la lecture de cet excellent billet
, les choses se compliquent.
En effet, nous nous trouvons dans un cas de figure où les deux serveurs sont Maîtres, donc Actif.
Heureusement, depuis la version 0.8 de DRBD, les deux noeuds peuvent être « Primary ».
(nb. : la version 0.9 devrait apporter le support de plus de 2 noeuds)
Par contre, pour pouvoir utiliser ses deux noeuds en mode Primaire, il faut un système de fichier « distribué » (vous trouverez souvent le terme « shared disk file system »).
Il en existe peu et les principaux sont GFS et OCFS2.
Le premier est issu de RedHat et le second d’Oracle. Sachez que le support de ses deux systèmes de fichiers est inclus dans les noyaux Linux récents.
J’ai testé les deux quelques temps et suite à mon retour personnel d’expérience et les discussions avec d’autres « geeks » ayant joué avec les deux, j’ai une nette préférence pour OCFS2. La suite de ce billet se basera donc sur ce système de fichier.
(je vous laisse bien sûr à vos propres expériences et recherches, si vous préférez GFS ou Lustre, je ne vous jetterai pas de pierres
)
Une fois mise en place, nous nous retrouvons donc avec ce type d’architecture :
La, on commence à être « poilu » non ?
Oui, MAIS, cette architecture est valable uniquement si on utilise les ressources locales des 2 serveurs (i.e. leurs disques durs).
Si je ne veux pas utiliser les disques durs de mes serveurs mais les disques d’un autre groupe de serveurs dédiés a cela ? Comment je fais ? HEIN ! Comment ???
Du calme, jeune Padawan, tu sais bien que Guiguiabloc est… à bloc…
Nous allons utiliser un SAN pour connecter nos disques distants à nos serveurs.
Un SAN !?! Mais j’ai pas de sous moi !!!
Allons, jeune Youngling, tu n’auras nul besoin de casser ton petit cochon qui te sert de tirelire, nous allons utiliser le protocole Iscsi.
L’ISCSI est du SCSI sur TCP/IP, nous allons connecter via ce protocole nos disques distants sur nos serveurs qui les verront comme s’il s’agissait de disques locaux.
(j’avais déjà abordé le sujet dans ce billet)
De plus en plus « poilu »… Mais pas encore assez. Poussons le bouchon un peu plus loin (hein Maurice ?) , je veux bien sûr de la redondance sur mes connexions Iscsi.
Et comment je fais de la haute disponibilité sur des iniatiators Iscsi ???
En utilisant un Device Mapper Multipath.
Bien sûr là vous vous dites : Guiguiabloc est fou/malade/a bloc/allumé (rayez les mentions inutiles) , et je vous répondrais… oui.
Schématisons le bouzin :
C’est beau hein ?
Après la théorie, passons à la phase la plus dure, la pratique.
- DRBD
Récuperer les souces :
http://oss.linbit.com/drbd/8.3/drbd-8.3.0.tar.gz
tar xzvf drbd-8.3.0.tar.gz cd drbd-8.3.0 cd drbd make cd .. make tools make install make install-tools
Edition du fichier /etc/drbd.conf (bien sur, remplacer les valeurs par les votres)
#/etc/drbd.conf
global {
usage-count yes;
}
resource r0 {
protocol C;
startup {
become-primary-on both;
}
disk {
on-io-error detach;
}
net {
allow-two-primaries;
after-sb-0pri discard-least-changes;
after-sb-1pri violently-as0p;
after-sb-2pri violently-as0p;
rr-conflict violently;
}
syncer {
rate 44M;
}
on DISK-GUIGUIABLOC-A { # nom du serveur 1
device /dev/drbd0;
disk /dev/sda4; # partition a prendre en compte
address 192.168.30.1:7788; # adresse ip et port d'écoute
meta-disk internal;
}
on DISK-GUIGUIABLOC-B { # nom du serveur 2
device /dev/drbd0;
disk /dev/sda3; # partition a prendre en compte
address 192.168.30.2:7788; # adresse ip et port d'écoute
meta-disk internal;
}
}Sur chacun des noeuds :
drbdadm create-md r0 modprobe drbd drbdadm attach r0 drbdadm connect r0 Puis sur le noeud1 par exemple drbdadm -- --overwrite-data-of-peer primary r0 /etc/init.d/drbd start
Vous suivez la synchro via un cat /proc/drbd
Je ne m’étends pas la dessus, j’en avais déjà parlé dans un autre billet.
- ISCSI Target Entreprise
Sur les deux « serveurs disques », on va installer un Target ISCSI.
(en terminologie ISCSI, on parle de Target pour la cible (soit la machine qui « offre » son disque) et d’Initiator pour la machine qui va se connecter au Target).
Je vous invite cet excellent article :
http://www.unixgarden.com/index.php/administration-reseau/le-support-du-protocole-iscsi-dans-linux
Nous allons utiliser les sources du projet iSCSI Entreprise Target , ici en version 0.4.17.
wget http://kent.dl.sourceforge.net/sourceforge/iscsitarget/iscsitarget-0.4.17.tar.gz tar xzvf iscsitarget-0.4.17.tar.gz cd iscsitarget-0.4.17 make make install
On prépare son /etc/ietd.conf (volontairement simplifié a l’extrème).
Vous remarquerez que j’exporte via ISCSI le volume DRBD0.
Target iqn.2009-02.fr.guiguiabloc:disk-a.disk
Lun 0 Path=/dev/drbd0,Type=blockio
Alias diskOn configure le fichier d’autorisation d’accès (comme les hosts.allow des wrappers tcp)
DISK-GUIGUIABLOC-a# cat /etc/initiators.allow iqn.2009-02.fr.guiguiabloc:disk-a.disk ALL
Même chose sur le deuxième serveur (changer juste le nom du target).
on démarre /etc/init.d/iscsi-target start, et on vérifie
DISK-GUIGUIABLOC-a:/etc/iscsi/ifaces# /etc/init.d/iscsi-target status
iSCSI enterprise target is running at pid 7715
DISK-GUIGUIABLOC-a:/etc/iscsi/ifaces# cat /proc/net/iet/volume
tid:2 name:iqn.2009-02.fr.guiguiabloc:disk-a.disk
lun:0 state:0 iotype:blockio iomode:wt path:/dev/drbd0- Open-ISCSI
Sur nos deux serveurs srv-guiguiabloc-a et srv-guiguiabloc-b, nous allons installer l’Initiator (le client ISCSI si vous préférez).
Récupérons des sources sur le site http://www.open-iscsi.org/
wget http://www.open-iscsi.org/bits/open-iscsi-2.0-870.2.tar.gz tar xzvf open-iscsi-2.0-870.2.tar.gz make make install
On donne un nom explicite à notre Initiator, puis on démarre le service.
srv-guiguiabloc-a:/etc/iscsi# cat initiatorname.iscsi InitiatorName=iqn.2009-02.fr.guiguiabloc:srvA srv-guiguiabloc-a:/etc/iscsi# /etc/init.d/open-iscsi start Starting iSCSI initiator service: iscsid. Setting up iSCSI targets:iscsiadm: No records found!
Lançons une découverte du service
srv-guiguiabloc-a:/etc/iscsi# iscsiadm -m discovery -t sendtargets -p 192.168.30.1:3260 192.168.30.1:3260,1 iqn.2009-02.fr.guiguiabloc:disk-a.disk srv-guiguiabloc-a:/etc/iscsi# iscsiadm -m discovery -t sendtargets -p 192.168.30.2:3260 192.168.30.2:3260,1 iqn.2009-02.fr.guiguiabloc:disk-b.disk
Un succès
(Bien sûr vous reproduisez tout cela sur srv-guiguiabloc-b)
Maintenant, montons les sessions ISCSI sur nos deux Targets, sur nos deux serveurs
srv-guiguiabloc-a:~# iscsiadm -m node -T iqn.2009-02.fr.guiguiabloc:disk-a.disk -p 192.168.30.1 -l Login session [iface: default, target: iqn.2009-02.fr.guiguiabloc:disk-a.disk, portal: 192.168.30.1,3260] srv-guiguiabloc-a:~# iscsiadm -m node -T iqn.2009-02.fr.guiguiabloc:disk-b.disk -p 192.168.30.2 -l Login session [iface: default, target: iqn.2009-02.fr.guiguiabloc:disk-b.disk, portal: 192.168.30.2,3260] srv-guiguiabloc-b:~# iscsiadm -m node -T iqn.2009-02.fr.guiguiabloc:disk-a.disk -p 192.168.30.1 -l Login session [iface: default, target: iqn.2009-02.fr.guiguiabloc:disk-a.disk, portal: 192.168.30.1,3260] srv-guiguiabloc-b:~# iscsiadm -m node -T iiqn.2009-02.fr.guiguiabloc:disk-b.disk -p 192.168.30.2 -l Login session [iface: default, target: iiqn.2009-02.fr.guiguiabloc:disk-b.disk, portal: 192.168.30.2,3260] Vous devriez voir vos disques en local désormais : srv-guiguiabloc-a:~# cat /proc/scsi/scsi Attached devices: Host: scsi1 Channel: 00 Id: 00 Lun: 00 Vendor: IET Model: VIRTUAL-DISK Rev: 0 Type: Direct-Access ANSI SCSI revision: 04 Host: scsi2 Channel: 00 Id: 00 Lun: 00 Vendor: IET Model: VIRTUAL-DISK Rev: 0 Type: Direct-Access ANSI SCSI revision: 04
Pour l’inclure en démarrage automatique :
iscsiadm -m node -T iqn.2009-02.fr.guiguiabloc:disk-a.disk -p 192.168.30.1 -o update -n « node.conn[0].startup » -v automatic
(je vous laisse lire la documentation et/ou l’article sur Unix Garden.)
- Device Mapper MULTIPATH I/O
Nous allons utiliser une des couches du système Linux, le Device Mapper.
Son rôle est tout simplement de mapper un ou plusieurs périphériques de blocs sur un autre périphérique.
En fait, vous l’utilisez souvent sans peut-être le savoir avec LVM.
Vous trouverez un excellent billet la dessus sur : http://linux-attitude.fr/post/La-carte-du-peripherique
Et l’une des fonctions offertes par DM et le ISCSI, c’est le Multipath.
C’est à dire accéder à un périphérique par plusieurs chemins différents
Vous voyez ou je veux en venir ?….
Si notre Target A tombe, pas de soucis, srv-guiguiabloc-x passera par l’autre chemin, en l’occurrence le Target B, tout cela grâce au Multipath (pas celui LA hein
)
(hi hi hi, désolé, il fallait que je la fasse)
Sur Debian : apt-get install multipath-tools
Editer votre fichier /etc/multipath.conf
blacklist {
devnode "sda" # ici le disque local que j'exclue
}
defaults {
user_friendly_names yes
}
srv-guiguiabloc-a:# /etc/init.d/multipath-tools restart
srv-guiguiabloc-a:/dev/mapper# ll
total 0
crw-rw---- 1 root root 10, 63 2009-02-14 19:57 control
brw-rw---- 1 root disk 254, 0 2009-02-16 15:16 mpath0
brw-rw---- 1 root disk 254, 1 2009-02-16 15:16 mpath1Vous voyez vos périphériques de blocs que vous pouvez utiliser comme n’importe quel autre.
En cas de déconnexion d’un Target, Multipath retirera le périphérique de la liste automatiquement.
(bien sûr, même punition pour srv-guiguiabloc-b).
- OCFS2
On arrive « enfin » au système de fichier proprement dit.
Sur les 2 srv-guiguiabloc :
apt-get install ocfs2-tools
On créer le répertoire /etc/ocfs2
On édite un fichier cluster.conf (identique sur les deux noeuds)
node:
ip_port = 7777
ip_address = 192.168.30.1
number = 0
name = srv-guiguiabloc-a
cluster = ocfs2
node:
ip_port = 7777
ip_address = 192.168.30.2
number = 1
name = srv-guiguiabloc-b
cluster = ocfs2
cluster:
node_count = 2
name = ocfs2Changer la valeur « O2CB_ENABLED=false » en « O2CB_ENABLED=true » dans /etc/default/o2cb
Démarrer le cluster :
srv-guiguiabloc-a:/etc/ocfs2# /etc/init.d/o2cb start Loading module "configfs": OK Mounting configfs filesystem at /sys/kernel/config: OK Loading module "ocfs2_nodemanager": OK Loading module "ocfs2_dlm": OK Loading module "ocfs2_dlmfs": OK Creating directory '/dlm': OK Mounting ocfs2_dlmfs filesystem at /dlm: OK Starting Oracle cluster ocfs2: OK
Et on formate
srv-guiguiabloc-a:/etc/ocfs2# mkdir /data srv-guiguiabloc-a:/etc/ocfs2# mkfs -t ocfs2 -L GUIGUIABLOCFS /dev/mapper/mpath0 mkfs.ocfs2 1.2.1 Filesystem label=GUIGUIABLOCFS Block size=4096 (bits=12) Cluster size=4096 (bits=12) Volume size=1439338496 (351401 clusters) (351401 blocks) 11 cluster groups (tail covers 28841 clusters, rest cover 32256 clusters) Journal size=67108864 Initial number of node slots: 4 Creating bitmaps: done Initializing superblock: done Writing system files: done Writing superblock: done Formatting Journals: done Writing lost+found: done mkfs.ocfs2 successful
Et c’est tout !
N’essayer pas de formater /dev/mapper/mpath1, ou /dev/mapper/mpath0 sur srv-guiguiabloc-b, vous aurez ce message :
srv-guiguiabloc-a:/etc/ocfs2# mkfs -t ocfs2 -L GUIGUIABLOCFS /dev/mapper/mpath1 mkfs.ocfs2 1.2.1 Overwriting existing ocfs2 partition. Proceed (y/N): n Aborting operation. srv-guiguiabloc-b:/etc/ocfs2# mkfs -t ocfs2 -L GUIGUIABLOCFS /dev/mapper/mpath0 mkfs.ocfs2 1.2.1 Overwriting existing ocfs2 partition. Proceed (y/N): n Aborting operation.
Ce qui prouve bien que notre volume est bien vu de srv-guiguiabloc-b, par le chemin /dev/mapper/mpath0 ou /dev/mapper/mpath1
C’est pas magnifique tout cela ?
Et maintenant, le test final :
srv-guiguiabloc-a:/etc/ocfs2# mount /dev/mapper/mpath1 /data srv-guiguiabloc-a:/etc/ocfs2# mount /dev/sda1 on / type ext3 (rw,errors=remount-ro) tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755) proc on /proc type proc (rw,noexec,nosuid,nodev) sysfs on /sys type sysfs (rw,noexec,nosuid,nodev) udev on /dev type tmpfs (rw,mode=0755) tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev) devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620) configfs on /sys/kernel/config type configfs (rw) ocfs2_dlmfs on /dlm type ocfs2_dlmfs (rw) /dev/mapper/mpath1 on /data type ocfs2 (rw,_netdev,heartbeat=local) srv-guiguiabloc-b:/etc/ocfs2# mount /dev/mapper/mpath0 /data srv-guiguiabloc-b:/etc/ocfs2# mount /dev/sda1 on / type ext3 (rw,errors=remount-ro) tmpfs on /lib/init/rw type tmpfs (rw,nosuid,mode=0755) proc on /proc type proc (rw,noexec,nosuid,nodev) sysfs on /sys type sysfs (rw,noexec,nosuid,nodev) udev on /dev type tmpfs (rw,mode=0755) tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev) devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=620) configfs on /sys/kernel/config type configfs (rw) ocfs2_dlmfs on /dlm type ocfs2_dlmfs (rw) /dev/mapper/mpath0 on /data type ocfs2 (rw,_netdev,heartbeat=local) srv-guiguiabloc-a:/data# touch test srv-guiguiabloc-b:/data# ls test lost+found
Vous pouvez vous amuser à écrire des deux côtés, couper un Target, vautrer un disque etc…
Après plusieurs essais intensifs, je vous avoue que j’ai été bluffé par le fonctionnement, que, je l’avoue, j’ai poussé à l’extrême.
Ne reste qu’à le greffer sur votre architecture « Altéonisée » que vous avez montée après la lecture de :
http://blog.guiguiabloc.fr/index.php/2009/01/14/switch-applicatif-avec-openbsd-un-alteon-a-la-maison/
Ce qui nous donne un joli résultat au final :
Très « poilu », non ?
Comme dirais mon pote `g0rt :
[17:53] <`g0rt> ca c’est de la redondance vindiousse
Bon courage dans le peaufinage de votre cluster






