lundi 21 février 2011

Réplication “temps réel” d’une base Postgresql

 

Objectif

La base de données d’une application est un composant sensible, surtout si l’application est une application métier en production.

De nombreux mécanismes peuvent (et doivent) être mis en place pour garantir une disponibilité de la base de données :

  1. Utilisation de disques en RAID pour prévenir les défaillances matérielles
  2. Sauvegarde (quotidienne) sur support externalisé (et bien sur vérification régulière de la restauration de ces supports)

Ces mécanismes ne sont pas à mon sens suffisants. En effet, si la base de données pour une raison ou une autre, est corrompue, soit les sauvegardes seront corrompues, soit la dernière sauvegarde sera correcte, mais l’on perd alors jusqu’à une journée de données.

Pour améliorer la sécurité, il est ainsi nécessaire de mettre en place un mécanisme de réplication “temps réel” de notre base de données. Ce mécanisme doit permettre de “remonter” la base de données à un moment dans le temps défini. Ainsi, si notre base a été corrompue à 13h05, il sera possible de remonter la base à 13h00, et de ne perdre qu’un minimum d’informations métier.

Ce mécanisme s’appelle “PITR” pour “Point In Time Recovery”.

Avec postgresql, c’est très simple à mettre en oeuvre. Il nécessite toutefois un deuxième serveur de base de données, qui sera prêt à reprendre la main en cas de chute du premier.

Mécanisme

Le mécanisme proposé par postgresql est assez simple : toutes les transactions effectuées sur la base de production sont stockées dans des fichiers de transaction (“pg_xlogs”). Une fois un fichier log rempli, il est envoyé sur le serveur de secours. Le serveur de secours peut être configuré de deux façons différentes : soit il intègre immédiatement les fichiers reçus, soit il ne fait rien et l’intégration est déclenchée manuellement en cas de besoin.

Ainsi la notion de “temps réel” est relative : en cas de crash de la base de données, on ne pourra remonter que jusqu’au dernier fichier de transaction qui a été envoyé au serveur de secours. Les fichiers étant envoyés quand ils sont remplis, on a un délai un peu aléatoire avec les paramètres par défaut. Il est toutefois possible de définir : la taille des fichiers (par défaut 16M), et le temps maximum entre deux créations de fichiers. Ces paramètres ne sont pas détaillés dans ce billet.

Détail de la mise en place

Bien, après toutes ces explications, passons à la mise en oeuvre, c’est plus rapide que d’expliquer les choses :

Serveur de production

Il suffit de dire au serveur de production d’activer l’archivage des fichiers logs de transaction (postgresql.conf) :

# - Archiving -
archive_mode = on
archive_command = 'scp -C %p 10.1.1.241:/data/Rescue/%p'

Comme je choisi de ne pas intégrer régulièrement les fichiers de transaction dans le serveur de secours, il faut ajouter un mécanisme qui va permettre de faire le ménage des fichiers logs sur le serveur de secours. Il faut pour cela, sauvegarder régulièrement la base de données depuis le serveur de production vers le serveur de secours. Cette sauvegarde effectuée, on pourra faire le ménage sur le serveur de secours. Il suffit de créer le petit script suivant qui sera lancé par cron tous les jours sur le serveur de production.

# On informe le serveur de prod que l'on passe en mode backup
echo "SELECT pg_start_backup('
backupPostgres');" | psql -U postgres [base a sauver]
# Sauvegarde de la base vers le serveur de secours
rsync -avzx --delete --exclude '
pg_xlog' /data/db [serveur de secours]:/data
# On informe le serveur de prod que la sauvegarde est terminée
echo "SELECT pg_stop_backup();" | psql -U postgres [base a sauver]
# On lance le nettoyage sur le serveur de secours
ssh [serveur de secours] "/root/bin/nettoyageBackups.sh"


Serveur de secours


Sur le serveur de secours, il n’y a pas grand chose à faire… Il faut juste préparer le script de nettoyage des logs inutiles (appelé par le script précédent) :


# Nettoyage des pg_xlogs plus anciens que le dernier dump de la base
find /data/Rescue/pg_xlog ! -newer `ls /data/Rescue/pg_xlog/*.backup | sort | tail -n 1` ! -name "*.backup" | xargs rm -f


Attention, sur le serveur de secours, postgresql doit être arrêté. En effet, on ne veut pas qu’il intègre au fur et à mesure les fichiers de transaction. Cela permettra de contrôler en cas de crash, jusqu’où les fichiers sont intégrés.


Et maintenant ?


Bien, la sauvegarde est en place, mais en cas de crash que fait-on ?


Serveur de secours


C’est, encore une fois, très très simple : il suffi de démarrer postgresql sur le serveur de secours, en lui disant d’intégrer les fichiers de transaction qui sont en attente.


Pour passer le serveur en mode ‘intégration des fichiers de transactions’ :


# nettoyage vieux pg_xlogs qui pouvaient trainer dans le repertoire de la base
rm -f /data/db/pg_xlog/0000*
# creation du fichier recovery.conf pour que postgres
# demarre en mode recovery
cat >/data/db/recovery.conf <<EOF
restore_command = 'cp /data/Rescue/pg_xlog/%f %p'
EOF

Puis, on redémarre postgresql : /etc/init.d/postresql start

Attention : on ne voit pas que la réintégration est en cours. Pour vérifier que cela fonctionne, il suffit de faire un tail -f /data/db/pg_log/[dernier log du serveur]

Une fois le recovery fini, le fichier "/data/db/recovery.conf" est renommé automatiquement en "/data/db/recovery.done"

Pour arrêter l’intégration des fichiers logs à une certaine heure, il suffit de supprimer (déplacer) les fichiers que l’on ne veut pas intégrer du répertoire /data/Rescue/pg_xlogs


Mots clés Technorati : ,,,

mercredi 16 février 2011

Connexion sécurisée entre deux PC sans mot de passe

 

Lorsqu’on travaille avec plusieurs serveurs linux, il est très pratique de pouvoir se connecter en ssh depuis l’un des serveurs sur les autres sans avoir à saisir son mot de passe.

En mettant de coté cet aspect pour fainéants, il y a d’autres bonnes raisons pour mettre en place cette facilité… Par exemple l’utilisation de screen avec une ouverture automatique d’une fenêtre pour chacun des serveurs majeurs, ou encore (et là ça devient indispensable) que l’on met en place des scripts copiant des fichiers d’un serveur vers un autre.

Bref, voici comment faire en 3 étapes :

Etape 1 Génération d’une paire de clef sur le serveur qui va envoyer les fichiers (ou depuis lequel on veut se connecter sur l’autre serveur)

ssh-keygen -t dsa -b 1024


Renseigner alors les informations



Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa): id_dsa
Enter passphrase (empty for no passphrase):(LAISSER VIDE)
Enter same passphrase again:
Your identification has been saved in id_dsa.
Your public key has been saved in id_dsa.pub.
The key fingerprint is:
1d:9a:23:a3:c3:14:42:12:52:54:a4:c6:54:3f:43:23 root@source

 


Etape 2 Copier la clé publique sur le serveur qui va recevoir les fichiers (ou sur lequel on veut se connecter)



ssh-copy-id -i /root/.ssh/id_dsa.pub root@[ip du serveur cible]

Entrer alors le mot de passe root du serveur cible


Etape 3 Oh, j’ai dit 3 étapes? C’est fini! Tester en se connectant à la machine cible :



ssh root@[serveur cible]

Vérifier le fichier .ssh/authorized_keys pour être certain qu’il n’y a que des clefs que nous y avons ajouté…


Ou bien encore tester une copie de fichier :



 
scp -i /root/.ssh/id_dsa /var/log/messages root@cible:/tmp

mardi 15 février 2011

xbmc streamer : erreur “no media found”

Pour ceux qui connaissent xbmc, il existe deux logiciels indispensables pour iPhone (pour ceux qui ne connaissent pas xbmc, tant pis pour vous) :
- xmbc remote : qui permet de piloter xbmc depuis l’iphone
- xbmc streamer : qui permet d’écouter à distance les musiques gérées par xbmc
xbmc streamer est un peu tatillon, et l’erreur “no media found” revient souvent sur les forums… La solution la plus répandue à ce problème est de supprimer le mot de passe d’accès à xbmc.
Mais j’ai rencontré ce problème, et trouvé la solution… nulle part. En regardant un peu les logs de xbmc sur le pc avec xbmc (vim /home/tof/.xbmc/temp/xbmc.log), xbmc recherche le fichier suivant : /usr/share/xbmc/addons/webinterface.default/33f3523d5004501f107fc209902c11b09d9849db-s
Or ce fichier existe dans le répertoire /usr/share/xbmc/web
Un simple
cd /usr/share/xbmc/addons/webinterface.default
ln -s ../../web/33f3523d5004501f107fc209902c11b09d9849db-s .
et le problème est résolu.

De gros caractères en ligne de commande

Il est parfois nécessaire d'avoir un terminal qui tourne avec watch pour surveiller l'avancement d'une tâche.

Par exemple :

watch -n 300 "ls -l *.r* |wc -l"

qui compte le nombre de fichiers avec .r* dans le répertoire courant.

Malheureusement, l'affichage est assez réduit et mon grand âge m'impose de plisser les yeux. Pour éviter les rides, il existe un petit logiciel qui permet de transformer un texte en son équivalent ascii art (donc plus grand) : figlet.

Un petit

watch -n 300 "ls -l *.r* |wc -l | figlet -c"

permet ainsi d'afficher le nombre de fichiers, en grand!


                                   __________
                                  |___ /___ /
                                    |_ \ |_ \
                                   ___) |__) |
                                  |____/____/

Comment générer un nom de fichier avec la date sous dos

Il est parfois nécessaire de générer des fichiers avec une date et une heure, pour sauvegarder un fichier log qui est écrasé à chaque ouverture de session par exemple.

Un petit batch à la fermeture de session permet alors de sauvegarder ce log, et pour que les fichiers ne s'écrasent pas les uns les autres, il faut les nommer différemment.

Par exemple :
copy c:\fcm_api.log c:\temp\fcm_api-%date:/=%-%time:~0,2%h%time:~3,2%m%time:~6,2%s%.log

mercredi 2 février 2011

Scripts de déconnexion ou fermeture de session

1) Via modifications de la BDR :

Script à la fermeture de session :
Clef concernée :
HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\System\Scripts\
Entrée "Logoff" (REG_SZ)

Script à la fermeture de Windows :
Clef concernée :
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System\Scripts\
Entrée "Shutdown" (REG_SZ)