Stocker les données de Munin sur de la mémoire flash, via tmpfs ou ramfs

Munin écrit beaucoup de données toutes les 5 minutes, ce qui n’est pas très adapté quand le filesystem est sur une carte SD ou clé USB par exemple.

Pendant longtemps, j’ai placé ces données sur une carte micro-SD dédiée (via un convertisseur USB), qui finissait par rendre l’âme au bout d’un an environ (logique : la mémoire flash n’est pas adaptée à tant d’écritures). Je faisais ça en mettant simplement des liens symboliques vers /var/cache/munin et /var/lib/munin.

Pour limiter les écritures, j’ai d’abord essayé de jouer sur le paramétrage du filesystem (ext4) pour qu’il garde longtemps les informations en cache mémoire avant écriture. Je me disais qu’en passant le paramètre « commit » à 15 minutes par exemple, ça aurait évité des écritures. Hélas, ça ne suffit pas : je suppose qu’il y a d’autres appels système « sync » qui rendent ce paramétrage peu utile.

Ensuite j’ai eu une autre idée : placer ces données dans un filesystem en RAM, et les synchroniser (programmatiquement) de temps en temps avec la carte SD. Ça a très bien fonctionné, et c’est ce que je décris ci-dessous :

Paramétrage du disque mémoire

Il faut définir la taille dont on a besoin. Avec 5 serveurs, ces données prennent actuellement 178 Mo : 7 Mo dans /var/cache/munin, et 171 Mo dans /var/lib/munin. Il y a également 14 Mo dans /var/log/munin, que j’ai préféré ne pas mettre dans le disque mémoire.

Il y a principalement deux implémentations possibles pour le disque mémoire : ramfs et tmpfs. Les exemples ci-dessous sont avec ramfs (j’expliquerai pourquoi plus bas), mais il suffit de mettre tmpfs à la place de ramfs dans le fstab pour passer de l’un à l’autre.

Dans /etc/fstab :

none /mnt/ramfsmunin ramfs defaults,size=200M,mode=755,nofail 0 0

Attention à ce que la taille soit raisonnable par rapport à la RAM de la machine (1 Go dans mon cas). Une autre précaution consiste à avoir au moins autant de swap sur la machine, pour que le kernel puisse (si besoin) déplacer des données sur disque s’il a besoin de mémoire vive. Dans mon cas, j’ai ajouté un fichier de swap sur la carte SD (déjà montée sur /mnt/usb) :

sudo dd if=/dev/zero of=/mnt/usb/swapfile bs=1024 count=200000

sudo mkswap /mnt/usb/swapfile
sudo chmod 0600 /mnt/usb/swapfile

Et configurer ce swap dans /etc/fstab :

/mnt/usb/swapfile swap swap defaults 0 0

Puis monter tous ces filesystems :

sudo mount -a

Déplacer les données dedans, et faire les liens symboliques pour que /var/cache/munin et /var/lib/munin pointent dessus.

Alimentation du disque mémoire au démarrage

Après chaque redémarrage, /mnt/ramfsmunin est vidé (ce n’est pas un filesystem persistent). Il faut donc le ré-alimenter depuis la carte SD.

J’ai donc créé un script copier_donnees_munin_sd_vers_ramfs.sh dans /root qui fait cette copie :

#!/bin/bash
mkdir -p /mnt/ramfsmunin/lib
mkdir -p /mnt/ramfsmunin/cache
chmod go+w /mnt/ramfsmunin/lib
chmod go+w /mnt/ramfsmunin/cache
rsync -a /mnt/usb/lib/munin /mnt/ramfsmunin/lib/
rsync -a /mnt/usb/cache/munin /mnt/ramfsmunin/cache/

Et on peut configurer systemd pour que ce script soit lancé à chaque redémarrage, ou plutôt à chaque fois que /mnt/ramfsmunin est monté (ce qui est encore mieux). Il suffit pour cela de créer un fichier /etc/systemd/system/copie-donnees-munin-vers-ramfs.service avec un contenu de ce type :

[Unit]
Description=Copie des données de Munin depuis la carte SD vers /mnt/ramfsmunin
Requires=mnt-usb.mount mnt-ramfsmunin.mount
After=mnt-usb.mount mnt-ramfsmunin.mount

[Service]
ExecStart=/root/copier_donnees_munin_sd_vers_ramfs.sh
ExecStop=/root/copier_donnees_munin_ramfs_vers_sd.sh

[Install]
WantedBy=mnt-ramfsmunin.mount

(adapter le nom des .mount en fonction du point de montage où sont votre carte SD et votre disque mémoire : il faut mettre le path de chaque point de montage, en remplaçant les / par des -)

Pour l’activer :

sudo systemctl enable copie-donnees-munin-vers-ramfs.service

 

Synchronisation périodique du disque mémoire avec le filesystem persistant

Pour que la carte SD ait les données lors du prochain redémarrage, il faut les y mettre de temps en temps.

J’ai fait ça avec un rsync dans l’autre sens, lancé par cron une fois par heure, via le script /root/copier_donnees_munin_ramfs_vers_sd.sh :

#!/bin/bash
rsync -a --bwlimit=500K --delete /mnt/ramfsmunin/lib/munin /mnt/usb/lib
rsync -a --bwlimit=500K --delete /mnt/ramfsmunin/cache/munin /mnt/usb/cache

Le paramètre « bwlimit » permet de ralentir la copie (à 500 Ko/s maximum). Oui, parce que ce filesystem est surveillé par munin, justement. Et s’il est sollicité un peu trop fort, on atteint un seuil de latence en écriture (si la carte SD n’est pas très rapide), qui fait que Munin m’envoie un SMS…

Le paramètre « delete » permet de supprimer de la carte SD les fichiers qui auraient disparu dans le disque mémoire : c’est utile car munin y crée des fichiers temporaires.

La ligne que j’ai rajoutée dans le crontab de root :

53 * * * * /root/copier_donnees_munin_ramfs_vers_sd.sh

(elle permet de lancer ce script à 53 minutes de chaque heure. Puisque munin tourne toutes les 5 minutes, je l’ai décalé 3 minutes après, de sorte que munin ait eu le temps de terminer, et que le script ait le temps de finir la copie avant la prochaine exécution de munin)

En cas de crash du système, je vais perdre une partie de l’historique de Munin (1h maximum), mais ce n’est pas très grave. Par contre, dans le cas d’un reboot normal, l’exécution de ce script est assurée par la ligne ExecStop du service systemd ci-dessus.

Pourquoi ramfs plutôt que tmpfs?

Sur le papier, tmpfs a de gros avantages sur ramfs : possibilité de limiter la taille du disque, de la superviser avec df, d’utiliser le swap si le système manque de RAM.

C’est donc tmpfs que j’ai essayé en premier. Hélas, j’ai constaté un phénomène étrange, que je n’ai pas réussi à comprendre ni à résoudre : les fichiers .rrd (utilisés par Munin pour stocker les données) n’étaient pas mis à jour dans le tmpfs, alors que les fichiers .storable et .html l’étaient sans problème. Résultat : je perdais mon historique de données à chaque redémarrage.

Si le tmpfs est vide, les fichiers .rrd sont bien créés, mais jamais mis à jour. Les graphiques, eux, étaient bien mis à jour au fur est à mesure.

En changeant simplement le type de fylesystem tmpfs en ramfs dans le fstab, cela a résolu le problème. Si quelqu’un a une explication logique, je suis preneur…

Résultat

Ouf, ma carte SD se porte mieux, et il y a beaucoup moins d’I/O wait :

 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *