An English version of this post is available.

Logo de la fourmi Gluster

Avant de commencer à reconfigurer l'infrastructure de ma maison, j'ai réalisé que j'avais besoin de partager des données entre mes deux serveurs principaux. Ça pourrait ne pas sauter aux yeux comme ça, mais vous le comprendrez dans les prochains posts.

Je veux des données distribuées et répliquées. Un peu comme un système de fichier réseau à la sauce RAID 1.

J'avais déjà entendu parler de Gluster il y a quelques temps, mais je n'avais jamais eu la chance de l'utiliser. C'est l'occasion d'essayer !

Gluster est un système de fichiers réseau scalable gratuit et open source

Voyons quelques termes que l'on va utiliser dans ce post:

  • Le Trusted pool décrit tous les hôtes dans le cluster Gluster.
  • Un Nœud ou Pair (Node ou Peer) est un des serveurs de notre cluster.
  • Une Brique (Brick) est un système de fichier utilisé par Gluster comme stockage.
  • Un Volume est une collection d'une ou plusieurs Briques.

On va créer un cluster Gluster composé de trois nœuds, chacun d'entre eux possèdera une brique. Ces briques feront partie d'un unique volume où les données seront répliquées.

  • Le nœud 1 sera ryokan.onsen.lan, IP 192.168.0.1
  • Le nœud 2 sera uchiyu.onsen.lan, IP 192.168.0.2
  • Le nœud 3 sera buro.onsen.lan, IP 192.168.0.7
  • Le volume Gluster sera onsen-gv0

Installer tout ce qui est nécessaire

Nos trois nœuds utilisent le système d'exploitation Debian. Y installer Gluster est trivial :

$ sudo apt install glusterfs-server

Gérer le service Gluster

On veut que le service Gluster démarre automatiquement au boot du serveur. Activons le service et démarrons le dès maintenant.

Sur tous les serveurs :

$ sudo systemctl enable glusterd
$ sudo service glusterd start

Gérer le trusted pool

Gluster utilise un pool de nœuds approuvés communiquant entre eux pour partager des données. Faisons que chaque serveur reconnaisse ses pairs.

Sur tous les serveurs, attention à l'IP:

$ sudo gluster peer probe 192.168.0.2
Probe successful

On peut vérifier le status des pairs et voir la liste des pairs du trusted pool :

$ sudo gluster peer status
Number of Peers: 1

Hostname: 192.168.0.2
Uuid: 98b75cb8-12d3-477d-b2e8-a54e1df926ed
State: Peer in Cluster (Connected)

Hostname: 192.168.0.7
Uuid: bfb6a644-21f2-440d-920d-317a0cbdd836
State: Peer in Cluster (Connected)
$ sudo gluster pool list
UUID                    Hostname    State
98b75cb8-12d3-477d-b2e8-a54e1df926ed    192.168.0.2 Connected
bfb6a644-21f2-440d-920d-317a0cbdd836    192.168.0.7 Connected
406cdbd7-f748-40f4-850d-2230aa1f5431    localhost   Connected

Configurer le stockage

Gluster fonctionne avec des briques. Chaque nœud doit avoir sa propre brique pour qu'elle puisse être utilisée dans un volume. Créons les systèmes de fichiers requis pour les briques sur tous les nœuds.

Chacun de nos 3 nœuds a un groupe de volume LVM avec un peu d'espace restant. On va créer deux volumes logiques et les formater en système de fichiers btrfs.

Gluster recommende XFS mais n'importe quel système de fichiers supportant les attributs étendus fera l'affaire. On peut aussi configurer un volume logique thinly provisioned puis un thin volume, mais j'ai voulu garder les choses simples pour le moment.

On ajoute ensuite les systèmes de fichiers créés aux fichiers /etc/fstab des nœuds, on les monte et on y crée un sous-répertoire pour y stocker les données de la brique. On va suivre la convention de nommage des briques Gluster. Plutôt que d'utiliser /data j'ai décidé d'utiliser /srv dans la FHS car je considère les données de cette brique comme des données spécifique à ce site.

Sur chaque serveur, attention au nom d'hôte :

$ sudo lvcreate -L 1G -n lvgluster vgryokan
$ sudo mkfs.btrfs /dev/mapper/vgryokan-lvgluster
$ sudo echo "/dev/mapper/vgryokan-lvgluster /srv/glusterfs btrfs defaults 0 0" >> /etc/fstab
$ sudo mount /srv/glusterfs
$ sudo mkdir -p /srv/glusterfs/onsen-gv0/brick1

Configurer le volume

On crée un volume distribué répliqué en utilisant les briques créées et on le démarre.

Depuis un seul nœud :

$ sudo gluster volume create onsen-gv0 replica 3 192.168.0.1:/srv/glusterfs/onsen-gv0/brick1 192.168.0.2:/srv/glusterfs/onsen-gv0/brick1 192.168.0.77:/srv/glusterfs/onsen-gv0/brick1
volume create: onsen-gv0: success: please start the volume to access data
$ sudo gluster volume start onsen-gv0
volume start: onsen-gv0: success

Accéder aux données du volume

Pour accèder aux données du volume, on doit monter un système de fichiers de type glusterfs. On crée un point de montage et on y monte le volume.

Sur tous les serveurs :

$ sudo mkdir -p /srv/glusterfs/mnt
$ sudo mount -t glusterfs localhost:onsen-gv0 /srv/glusterfs/mnt

Enfin, on crée un fichier dans le volume nouvellement monté et on vérifie sur les autres systèmes que le fichier est correctement répliqué.

$ sudo touch /srv/glusterfs/mnt/test # Répliqué sur les autres nœuds !

Monter le volume Gluster au démarrage

Comme on veut que les données du volume soit disponible dès que possible, on ajoute l'entrée suivante dans les /etc/fstab de chaque nœud :

localhost:/onsen-gv0 /srv/glusterfs/mnt glusterfs defaults,_netdev 0 0

On utilise l'option suivante :

  • _netdev : Le système de fichiers réside sur un appareil qui requiert un accès réseau (utilisé pour éviter que le système n'essaye de monter ces systèmes de fichiers tant que le réseau n'a pas été activé sur le système).

Roulement de tonnerre

Voici quelques choses opérationnelles ou des problèmes que j'ai rencontré et comment je les ai gérés.

Brick is already part of a volume

Quand j'ai essayé d'ajouter une brique qui avait été utilisée par un autre volume, j'ai eu cette erreur :

failed: /srv/glusterfs/onsen-gv0/brick1/ is already part of a volume

Pour pouvoir la réutiliser, j'ai dû supprimer les attributs spécifiques et les métadonnées Gluster sur la brique :

$ sudo setfattr -x trusted.glusterfs.volume-id /srv/glusterfs/onsen-gv0/brick1/
$ sudo setfattr -x trusted.gfid /srv/glusterfs/onsen-gv0/brick1/
$ sudo rm -Rf /srv/glusterfs/onsen-gv0/brick1/.glusterfs/

Erreurs quand on essaye de supprimer une brique d'un volume répliqué

Après avoir ajouté ofuro.onsen.lan en tant que 4ème nœud pour remplacer buro.onsen.lan, j'ai eu ces message lorsque j'ai essayé de supprimer la brique de buron.onsen.lan.

$ sudo gluster volume remove-brick onsen-gv0 192.168.0.7:/srv/glusterfs/onsen-gv0/brick1 start
Running remove-brick with cluster.force-migration enabled can result in data corruption. It is safer to disable this option so that files that receive writes during migration are not migrated.
Files that are not migrated can then be manually copied after the remove-brick commit operation.
Do you want to continue with your current cluster.force-migration settings? (y/n) y
...

Mais mon volume n'a pas été configuré avec cluster.force-migration :

$ sudo gluster volume get onsen-gv0 force-migration
Option                                  Value
------                                  -----
cluster.force-migration                 off

Un bug est ouvert ici, et une nouvelle formulation a été proposée . Cependant, à mon avis, il serait plus convivial de n'afficher ce message que quand le volume a vraiment l'option d'activée.

...
volume remove-brick start: failed: Removing bricks from replicate configuration is not allowed without reducing replica count explicitly.

Évidemment, si on supprimer une brique d'une configuration répliquée de 4 briques, on doit indiquer que l'on veut aussi réduire le nombre de réplicats.

Essayons de nouveau :

$ sudo gluster volume remove-brick onsen-gv0 replica 3 192.168.0.7:/srv/glusterfs/onsen-gv0/brick1 start
...
volume remove-brick start: failed: Migration of data is not needed when reducing replica count. Use the 'force' option

Et bien... mmh okay? 🤷 Gluster, pourquoi tu ne préviens pas avant ? Ou, mieux, pourquoi tu ne t'en occupes pas toi même ?

root@ryokan:~# gluster volume remove-brick onsen-gv0 replica 3 192.168.0.7:/srv/glusterfs/onsen-gv0/brick1 force
Remove-brick force will not migrate files from the removed bricks, so they will no longer be available on the volume.
Do you want to continue? (y/n) y
volume remove-brick commit force: success