===== Serveur Clafoutis: Créer une grappe de calcul Super-Clafoutis ======
===== Introduction =====
* En bioinformatique, une analyse ne demande pas de faire une simple opération sur un seul fichier mais la même opération (ou l'usage du même programme mais avec des paramètres modifiés) sur des dizaines, sinon, des milliers de fichiers. Est-ce qu'on fait ça de manière sérielle, une tâche à la fois? Non, ça prendrait trop de temps :-) . Donc on utilise un ensemble d'ordinateurs, exécutant les opérations de manière parallèle ou pseudo-parallèle, et interconnectés par un réseau de communication à haute vitesse: c'est un //cluster// ou une grappe de calcul.
* Une grappe peut-être une bête très impressionnante. Ici au Québec, les grappes de calcul [[https://docs.alliancecan.ca/wiki/Narval|Narval]] et [[https://docs.alliancecan.ca/wiki/Rorqual|Rorqual]] ont respectivement plus de 81000 et 136000 coeurs de calcul! Alors comment des Raspberry Pi peuvent-ils se comparer?
* Primo: ce sont de merveilleux outils d'enseignement et d'apprentissage. Une grappe de calcul ne s'emploie pas comme un ordinateur simple et il est nécessaire d'apprendre comment exécuter les tâches. Apprendre sur de grosses infrastructures peut poser problème…
* Secundo: pour certains usagers, faire du calcul parallèle n'est peut-être pas possible sur une infrastructure partagée. Les faibles coûts du RPi rend la construction d'une grappe basée sur eux plus facile et abordable.
===== Installation du matériel =====
* Donc, quel est le matériel nécessaire? Dans l'ordre:
* Plusieurs Raspberry Pi 4B avec 8Gb ou Raspberry Pi 5 avec 8/16Gb et leur espace de stockage système (au minimum, des cartes MicroSD ou des clés USB de qualité avec une capacité minimale de 64Gb);
* Idéalement, autant de carte HAT PoE ou PoE+ (pour le Raspberry Pi 5) que de RPi pour l'alimentation électrique via le commutateur Ethernet.
* Une alternative est une alimentation électrique capable d'alimenter plusieurs dispositifs USB, procurant 15W/20W par port (5V/3A ou 5V/4A).
* Un commutateur Gigabit Ethernet, idéalement capable d'alimenter en électricité les RPi via le protocole PoE ou PoE+ (pour des Raspberry Pi 5).
* Une caractéristique souhaitable est la capacité de [[https://en.wikipedia.org/wiki/Link_aggregation#IEEE_link_aggregation|lier]] (//bonding//) plusieurs interfaces pour créer une interface à plus forte capacité pour le NAS.
* Si votre NAS possède un port 10Gb Ethernet, trouver un commutateur avec un port 10Gb Ethernet disponible.
* Un stockage partagé de type NAS, idéalement avec 4 ports réseau 1Gb capables d'être mis en commun via [[https://en.wikipedia.org/wiki/Link_aggregation#IEEE_link_aggregation|LACP]].
* Si votre NAS possède un port 10Gb Ethernet ou bien peut accueillir une carte 10Gb Ethernet, c'est encore mieux :-).
* Un système physique d'installation des RPi, ou bien en rack ou en bloc.
* Exemple [[https://www.uctronics.com/raspberry-pi/uctronics-19-1u-raspberry-pi-rack-mount-with-ssd-mounting-brackets.html|ici]] et [[https://www.uctronics.com/raspberry-pi/uctronics-desktop-cluster-enclosure-4-raspberry-pis-2-5-ssd-front-removable-trays.html|ici]] (à titre de démonstration)
* Qu'en est-il de l'utilisation du processeur graphique (//GPU//) dans un contexte de calcul distribué? Il est très utile de déléguer au GPU certaines/plusieurs tâches de calcul et la bio-informatique ne fait pas exception :-) Cependant, faire ça avec les Raspberry Pi n'est pas une très bonne idée... Pourquoi?
* Les meilleurs GPU demandent beaucoup, beaucoup de puissance et dégagent beaucoup, beaucoup de chaleur :-(
* Le GPU installé sur les RPI 4/5 sont bien pour gérer une interface graphique à la Xfce mais ne sont pas très puissants pour faire autre chose.
* Mais le plus gros problème reste un problème logiciel. La pile logicielle la plus souvent utilisée en HPC est CUDA de Nvidia qui n'existe tout simplement pas pour les RPi. Il existe une alternative, OpenCL, mais l'utiliser sur RPi demande une interface logicielle de compatibilité, ce qui vient bouffer une partie de la puissance du GPU pour faire la conversion entre les deux éléments. De plus, il existe très peu de logiciels en bio-informatique qui utiliser OpenCL...
===== Configuration logicielle en pré-requis =====
* Ces instructions assument que vous êtes l'usager ayant les privilèges de ''super user'', capable d'utiliser la commande ''sudo''.
* Tous les RPi ont accès aux volumes partagés par le NAS (via NFS) sous ''/opt/bio'' (afin d'avoir les mêmes applications), ''/home'' (pour que les RPi puissent écrire sur le même espace) et tout autre répertoire nécessaire (par exemple, ''/shares/data'' pour le stockage des données partagées).
* Si nécessaire. installer les librairies nécessaires sur les noeuds de calcul.
* Nous installerons le système de gestion des tâches [[https://slurm.schedmd.com/overview.html|SLURM]] et ses dépendances, le système d'authentification pour grappe de calcul [[https://github.com/dun/munge|MUNGE]] et le système de base de données [[https://www.mariadb.com|MariaDB]] pour la gestion des données provenant des tâches exécutées.
===== Protocole d'installation =====
* Si ça n'a pas été encore fait, il faut changer le nom de chaque machine pour que ça corresponde au fichier ''/etc/hosts'':
# Sur gru
% sudo hostnamectl set-hostname gru
# Sinon, sur chaque noeud de calcul:
% sudo hostnamectl set-hostname minion0x
* Modifiez le fichier ''/etc/hosts'' de tous les ordis qui feront partie de la grappe en inscrivant les infos associant nom de serveur et adresse IP. Par exemple, pour une grappe de 5 ordis où ''gru'' est le contrôleur et les ordis ''minion01'' à ''minion04'' seront les noeuds de calcul, on écrit ceci à la fin du fichier (les valeurs *.a.xy0 à *.a.xy4 sont évidemment spécifiques à votre réseau):
# Super Clafoutis
192.168.a.xy0 gru
192.168.a.xy1 minion01
192.168.a.xy2 minion02
192.168.a.xy3 minion03
192.168.a.xy4 minion04
* Ubuntu a la fâcheuse manie d'effacer tout ce qui se trouve dans le fichier ''/etc/hosts'' pour y mettre ses propres entrées à chaque mise à jour :-( Il faut lui dire de ne pas faire ça! Ouvrer le fichier ''cloud.cfg'' qui se trouve sous ''/etc/cloud'':
% sudo nano /etc/cloud/cloud.cfg
* Éditer le fichier en mettant un dièse (''#'') devant cette ligne et sauvegarder le fichier:
# Cette ligne...
update_etc_hosts: true
# ...devient:
#update_etc_hosts: true
* Pour faciliter l'accès inter-machines, utilisons l'accès SSH sans mot de passe via la création et l'installation d'une clé d'authentification:
# Sur gru | Pas besoin d'utiliser de phrase d'accès donc simplement presser enter lorsque demandé
% ssh-keygen -t rsa
# On copie la clé sur chaque minion
% for i in {1..4}; do ssh-copy-id monUsager@minion0$i;done
* Pour le bon fonctionnement de ''slurm'' et des scripts exécutés, les identificateurs d'usager (UUID) et de groupe (GUID) **doivent être identiques à ceux du serveur NFS** pour tous les RPi de la grappe. Si nécessaire, il faudra les modifier dans les fichiers ''/etc/passwd'' et ''/etc/group'' de chaque RPi.
* Il faut installer MUNGE sur tous les ordinateurs de la grappe:
% sudo apt install -y munge libmunge-dev
* À la suite de cette opération, l'usager ''munge'' sera créé sur chaque système, le processus ''munged'' sera démarré par cet usager et les permissions nécessaires seront données au répertoire ''/etc/munge'' et ''/etc/default/munge''
* Dans le fichier ''/etc/default/munge'' de chaque ordi de la grappe, insérer la ligne suivante dans le fichier ''/etc/default/munge'' (par ex., via ''nano'') ou retirer le dièse (#) pour décommander la ligne si elle est présente:
OPTIONS="–syslog –key-file /etc/munge/munge.key"
* Créer une clé d'encryption sur le contrôleur ''gru'' qui sera utilisée pour les communications entre les noeuds. L'installation de ''munge'' via ''apt'' en crée une mais je suis un tantinet parano...:
% sudo -u munge mungekey --force --verbose
* Par défaut, ''mungekey'' crée une clé de 1024 bits, bien assez pour un usage de labo, sous ''/etc/munge'';-) De plus, il aura les bonnes permissions.
* Démarrer/re-démarrer le service ''munge'' et vérifier qu'il fonctionne (les lignes affichées ne devraient pas contenir le mot ''ERROR'' ou ''FAILED''…):
% sudo -u munge systemctl start munge && systemctl status munge
* Il faut maintenant copier la clé d'encryption qui se trouve sur le contrôleur.
% for i in `seq 1 4`; do sudo scp /etc/munge/munge.key minion0${i}:/etc/munge/munge.key; done
# Sur chaque minion:
% sudo chown munge:munge /etc/munge/munge.key
% sudo chmod 400 /etc/munge/munge.key
% sudo systemctl restart munge
# Vous ne devriez pas voir de message d'erreur...
% systemctl status munge
* Il reste à vérifier que les RPi se reconnaissent:
# Sur chaque minion
# A faire pour tous les minions pour s'assurer que ça fonctionne entre tout le monde.
% ssh minion01 munge -n | unmunge
# Vous devriez voir une sortie au terminal qui ressemble à ça:
STATUS: Success (0)
ENCODE_HOST: minion01 (192.168.1.xy1)
ENCODE_TIME: 2022-07-02 10:36:24 -0400 (1656772584)
DECODE_TIME: 2022-07-02 10:36:30 -0400 (1656772590)
TTL: 10
CIPHER: aes128 (4)
MAC: sha256 (5)
ZIP: none (0)
UID: bioubuntu (1030)
GID: users (100)
LENGTH: 0
* Pour s'assurer que le service ''munge'' soit démarré à chaque redémarrage des serveurs:
# Sur chaque RPi de la grappe
% sudo systemctl enable munge
* Une grappe de calcul est la plupart du temps une ressource partagée par un ensemble. Pour assurer le suivi des opérations et de l'usage fait d'une grappe, il est nécessaire d'avoir des fonctions de journalisation spécifiques aux programmes de la suite SLURM: c'est le programme ''sacct''. Dans une grappe Super-Clafoutis, surtout destinée à une recherche individuelle, ''sacct'' est aussi très utile car c'est avec lui qu'il est possible de comprendre pourquoi des tâches ne pourraient avoir été exécutées ou complétées.
* SLURM utilise MySQL (ou sa version libre MariaDB) comme application externe pour stocker et gérer les données sur les tâches exécutées. Une installation Impilo installe le serveur et le client MariaDB mais n'en fait pas l'initialisation… Un tutoriel pour ce faire se trouve [[https://www.digitalocean.com/community/tutorials/how-to-install-mariadb-on-ubuntu-22-04|ici]]; essentiellement, il faut suivre les instructions présentées dans l'étape 2 du processus d'installation.
* En exécutant le script ''mysql_secure_installation'', choisissez les paramètres les plus robustes tel que:
- Donner un mot de passe robuste pour l'usager ''root'' (faire attention: ''root'' de MySQL n'est pas le même que ''root'' du système);
- Effacer l'usager ''anonymous'';
- Ne pas permettre de connexion externe pour ''root'';
- Effacer la base de données de démonstration appelée ''test''.
* Il faut ajouter quelques paramètres dans le fichier de config ''/etc/mysql/mariadb.conf.d/50-server.cnf''; dans la section ''InnoDB'', mettre ou décommenter les lignes suivantes:
# Sur un RPi 5 16Gb; la moitié si 8Gb
innodb_buffer_pool_size=8192M
innodb_log_file_size=256M
innodb_lock_wait_timeout=900
* Les premières étapes se font dans MariaDB ;-) Commençons par créer l'usager ''slurm'', qui effectuera toutes les opérations sur les bases de données de SLURM:
# On opère MariaDB comme si c'était MySQL, en tant qu'usager root de MariaDB
% mysql -u root -p
# On entre dans MariaDB et le prompt mysql> vous le démontre!
# Evidemment, le mot de passe est à votre discrétion… Ici, ce n'est que pour
# des fins de démonstration; vous êtes averti…
mysql> CREATE USER 'slurm'@'localhost' IDENTIFIED BY 'bioubuntu';
Query OK, 0 rows affected (0.16 sec)
* Ensuite on crée les bases de données nécessaires:
#
mysql> create database slurm_acct_db;
Query OK, 1 row affected (0.04 sec)
* On termine la mise en place sur MySQL en donnant les permissions nécessaires à l'usager ''slurm'':
#
mysql> grant all privileges on slurm_acct_db.* to 'slurm'@'localhost';
Query OK, 0 rows affected (0.02 sec)
* On installe le package ''slurmdbd'' sur ''gru'' uniquement:
% sudo apt install slurmdbd
* Il faut créer un fichier de configuration pour ''slurmdbd'', appelé ''/etc/slurm/slurmdbd.conf'' avec les infos suivantes:
AuthType=auth/munge
AuthInfo=/var/run/munge/munge.socket.2
DbdHost=localhost
DbdAddr=localhost
StoragePort=3306
StorageUser=slurm
# Evidemment, mettre celui que vous aurez choisi ci-dessus
# Ici, c'est pour l'exemple :-)
StoragePass=bioubuntu
StorageType=accounting_storage/mysql
LogFile=/var/log/slurm/slurmdbd.log
PidFile=/var/run/slurmdbd/slurmdbd.pid
SlurmUser=slurm
* Assurez-vous d'avoir les bonnes permissions:
% sudo touch /etc/slurm/accounting_password
% sudo echo 'votre_mot_de_passe_mariadb_pour_usager_slurm' > /etc/slurm/accounting_password
% sudo chown slurm:slurm /etc/slurm/accounting_password
% sudo chown slurm:slurm /etc/slurm/slurmdbd.conf
% sudo chmod 600 /etc/slurm/slurmdbd.conf
% sudo systemctl enable --now slurmdbd
% sudo systemctl status slurmdbd
* Vous ne devriez pas voir de message d'erreur :-)
* On commence par l'installation de ''SLURM'' via ''apt'' sur tous les RPi:
% sudo apt install -y slurmctld
* À la suite de cette opération, tous les RPi auront les bons répertoires avec les bonnes permissions ;-)
* Il faut maintenant créer un fichier de configuration ''slurm.conf'' sous ''/etc/slurm''.
#
sudo nano /etc/slurm/slurm.conf
* Il vous suffit de l'éditer pour qu'il ressemble à ceci:
# Le nom de la grappe
ClusterName=superclafoutis
# Le nom du serveur sur lequel fonctionne le processus slurmctld
SlurmctldHost=gru
AuthType=auth/munge
ProctrackType=proctrack/cgroup
SchedulerType=sched/backfill
SelectType=select/cons_tres
# Le nom de l'usager à qui appartient le processus slurmctld
SlurmUser=slurm
StateSaveLocation=/var/spool/slurmctld
SlurmdSpoolDir=/var/spool/slurmd
SlurmctldPidFile=/var/run/slurm/slurmctld.pid
SlurmdPidFile=/var/run/slurm/slurmd.pid
# L'information pour slurmdbd
AccountingStorageType=accounting_storage/slurmdbd
AccountingStorageHost=gru
AccountingStorageUser=slurm
# Les infos sur les noeuds qui feront les tâches
NodeName=minion01 Sockets=1 CoresPerSocket=4 ThreadsPerCore=1 State=UNKNOWN
NodeName=minion02 Sockets=1 CoresPerSocket=4 ThreadsPerCore=1 State=UNKNOWN
NodeName=minion03 Sockets=1 CoresPerSocket=4 ThreadsPerCore=1 State=UNKNOWN
NodeName=minion04 Sockets=1 CoresPerSocket=4 ThreadsPerCore=1 State=UNKNOWN
# On regroupe tous les noeuds dans une même partition
PartitionName=biobunch Nodes=ALL Default=YES MaxTime=120 State=UP
* Remarquez que ''gru'' ne fait pas partie de la liste de noeuds de travail de la grappe. Si il y était, il recevrait des tâches ce qui le ralentirait pour le travail interactif ou bien gérant une interface graphique. Cependant, si ''gru'' n'accomplit aucune de ces tâches, vous pourriez l'inclure.
* Il faut terminer la configuration avec les commandes suivantes:
% sudo mkdir -p /var/spool/slurmctld
% sudo chown slurm:slurm /var/spool/slurmctld
% sudo chmod 755 /var/spool/slurmctld
% sudo touch /var/log/slurm/slurmctld.log
% sudo touch /var/log/slurm/slurm_jobacct.log
% sudo touch /var/log/slurm/slurm_jobcomp.log
% sudo chown -R slurm:slurm /var/log/slurm
* Assurez vous maintenant de copier le fichier ''slurm.conf'' sur tous les RPi faisant partie de la liste des noeuds de travail au même endroit sous ''/etc/slurm''.
* Sur ''gru'', faites les commandes suivantes:
% sudo systemctl enable slurmctld
% sudo systemctl restart slurmctld
% sudo systemctl status slurmctld
* Vous ne devriez pas voir de messages d'erreur après la dernière commande.
* N'oubliez pas de copier le fichier ''/etc/slurm/slurm.conf'' sur vos noeuds de travail!! Assurez-vous d'avoir les bonnes permissions:
# Sur chaque RPi de calcul
% sudo clown root:root /etc/slurm/slurm.conf
* Sur chaque noeud de travail, on installe ''slurmd'' et on s'assure que ça fonctionne:
% sudo apt install -y slurmd libpmix-dev
% sudo systemctl enable slurmd
% sudo systemctl restart slurmd
% systemctl status slurmd
* Encore une fois, vous ne devriez pas voir d'erreur ;-) Sur chacun des noeuds de calcul, il faut ajuster les paramètres pour le stockage des journaux:
% sudo chown -R slurm:slurm /var/spool/slurmd
% sudo chmod 755 /var/spool/slurmd
% sudo touch /var/log/slurm/slurmd.log
% sudo chown -R slurm:slurm /var/log/slurm/slurmd.log
* Vérifier que le serveur ''gru'' voit les machines:
% sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
biobunch* up 2:00:00 4 idle minion[01-04]
* Si l'état (''STATE'') d'une machine est à ''drain'' ou à ''down'', exécuter la commande suivante sur le serveur ''gru'' et refaite la commande ''sinfo'' pour vérifier le retour à la normale:
% Sur minion01 par ex.:
% sudo scontrol update nodename=minion01 state=idle
* Note: si à tout moment, un noeud "tombe" et doit être redémarré, il faut refaire cette commande en spécifiant le noeud en défaut.
* Si tout fonctionne, le commande suivante devrait vous retourner les noms de tous les noeuds de travail:
% srun --nodelist=minion[01-04] hostname
minion01
minion02
minion03
minion04
===== Comment utiliser SLURM pour exécuter des tâches sur une grappe de calcul =====
==== En utilisant la commande srun ====
Page man pour ''srun'': [[https://manpages.ubuntu.com/manpages/noble/man1/srun.1.html|Manuel]]
* La commande ''srun'' exécutée sur le noeud contrôleur (dans notre cas, ''gru'') délèguera l'exécution d'une //commande// à un des noeuds de calcul. À moins que le noeud soit spécifié, l'exécution se fera via SLURM en choisissant un noeud selon la configuration utilisée par ''slurmctld''.
* Un exemple banal:
% srun hostname
minion01
% srun --nodelist=minion02 hostname
minion02
% srun --nodelist=minion0[1,2] hostname
minion02
minion01
==== En utilisant la commande sbatch ====
Page man pour ''sbatch'': [[https://manpages.ubuntu.com/manpages/noble/man1/sbatch.1.html|Manuel]]
* La commande ''sbatch'' exécutée sur le noeud contrôleur (dans notre cas, ''gru'') délèguera l'exécution d'un //script//; c'est un nuance importante car le script est capable de permettre l'exécution d'une série complexe de commandes. À moins que le noeud soit spécifié, l'exécution se fera via SLURM en choisissant un noeud selon la configuration utilisée par ''slurmctld''.
* Un exemple simple de script:
À venir...
===== Comment suivre les opérations d'une grappe SLURM =====
* Dans une grappe de calcul, on a le plus souvent besoin de suivre les paramètres suivants:
* Suivre les ressources disponibles;
* Comment s'exécute les tâches.
* SLURM dispose d'outils de gestion permettant de voir ces paramètres:
* Avec ''sinfo'', on peut voir la santé des noeuds de calcul de la grappe et avoir une vue d'ensemble des ressources;
* Avec ''scontrol'', on peut voir plus spécifiquement les tâches en action et les ressources disponibles pour un noeud spécifique;
* Avec ''sstat'', on peut voir en temps réel les détails sur une tâche en particulier;
* Avec ''squeue'', on voit les tâches en cours et les tâches en attente de manière globale.
* Ces outils sont pratiques (évidemment!) mais une vue d'ensemble regroupant des informations de toutes ses applications est très utile :-) Il existe quelques solutions libres pour faire le suivi via une page web mais ce sont souvent des outils complexes en installation et qui en vaillent la peine pour de grosse grappes... Deux solutions plus rudimentaires mais tout à fait fonctionnelles sont disponibles:
* Avec [[https://gitlab.com/lkeb/slurm_viewer|Slurm Viewer]], on utilise le terminal pour suivre les opération de la grappe, soir en regardant les nous, soit en suivante les tâches;
* Avec [[https://github.com/hunoutl/slurmtop|slurmtop]], on fait pas mal la mème chose mais la présentation est différente.
* C'est votre choix :-)
===== Références =====
[[https://medium.com/@hghcomphys/building-slurm-hpc-cluster-with-raspberry-pis-step-by-step-guide-ae84a58692d5|Building a Slurm HPC Cluster with Raspberry Pi’s: Step-by-Step Guide]]
[[https://glmdev.medium.com/building-a-raspberry-pi-cluster-784f0df9afbd|Building a Raspberry Pi cluster: Part I - The basics]]
[[https://glmdev.medium.com/building-a-raspberry-pi-cluster-aaa8d1f3d2ca|Building a Raspberry Pi cluster: Part II - Some simple jobs]]
[[https://glmdev.medium.com/building-a-raspberry-pi-cluster-f5f2446702e8|Building a Raspberry Pi cluster: Part III - OpenMPI, Python, and Parallel Jobs]]
[[https://implement.pt/2018/09/slurm-in-ubuntu-clusters-pt1/|SLURM in Ubuntu clusters - Part 1]]
[[https://implement.pt/2018/09/slurm-in-ubuntu-clusters-pt2/|SLURM in Ubuntu clusters - Part 2]]
[[https://www.linkedin.com/pulse/slurm-setup-easy-way-ubuntu-2404-practical-guide-building-nagaraj-s-tj7cc/|Slurm Setup the Easy Way on Ubuntu 24.04: A practical guide to building your first HPC Cluster]]
[[https://southgreenplatform.github.io/trainings/hpc/slurminstallation/|HPC Cluster Administration]]