Limiter la RAM disponible pour Mongo

Pour des besoins de test, et notamment dans le but de mesurer les performances et d’analyser le comportement de Mongo avec différentes quantités de mémoire vive, je me suis penché sur la façon de restreindre les ressources pour un processus donné sous GNU/Linux.

Je me suis d’abord tourné vers ulimit qui semblait permettre de restreindre explicitement la ram, avec en particulier la commande suivante:

ulimit -Hm 30000

Pour la mémoire virtuel, on remplace le m par un v, par exemple:

ulimit -Sv 200000

Cette façon de faire n’était malheureusement pas satisfaisante. En surveillant mon mongo avec mongostat, je constate que celui-ci dépasse largement les limites imposées. Je me tourne donc vers une autre solution: les cgroups.

Reprenons la définition de Wikipédia, les cgroups sont une fonctionnalité du noyau Linux permettant de « limiter, compter et isoler l’utilisation des ressources ». Ça tombe bien, c’est exactement ce que je cherche à faire. En bonus, les cgroups sont utilisés par les LinuX Containers (LXC), procédé de « virtualisation légère », une raison de plus de s’y intéresser.

Revenons à notre problématique de limitation de la ram de mongo. Dans un premier temps, il est nécessaire de préparer l’environnement:

aptitude install libcgroup1

Si le paquet n’est pas disponible sous ce nom là, une simple recherche de cgroup devrait permettre de le trouver. Nous allons tout d’abord créer un nouveau cgroup qui nous permettra d’appliquer les limitations:

sudo cgcreate -t <user> -a <user> -g memory,cpu:<groupname>

Ici, notre cgroup pourra imposer des limites sur la mémoire (memory) et le processeur (cpu).  Nous pouvons maintenant définir les paramètres de notre groupe, en terme de mémoire notamment:

echo 33000000 > /sys/fs/cgroup/memory/<groupname>/memory.limit_in_bytes

Ici, nous limitons la mémoire vive à 33 Mo pour notre cgroup. Des raccourcis existent pour l’écriture des quantités d’octets, on pourrait par exemple remplacer 33000000 par 33M. Il ne nous reste plus qu’à démarrer notre processus mongo avec ces restrictions:

cgexec -g memory:<groupname> mongod

En surveillant notre mongo avec mongostat, nous pouvons ainsi constater une augmentation du nombre de « page faults » lorsque nous réduisons la mémoire disponible de manière significative et constater que mongo prend bien en compte la limite.

Voilà donc un court exemple qui permet d’éviter de saturer sa ram en totalité avant de pouvoir commencer des tests sur mongo, notamment en ce qui concerne l’étude du nombre de « page faults » en fonction du working set et de la ram disponible. Ce procédé peut bien sûr être appliquer à d’autres processus pour éviter qu’ils ne consomment toutes les ressources de la machine. Pour de plus amples d’informations sur le sujet, on se tournera vers le wiki Arch Linux ou encore ce guide Red Hat.