13 KiB
layout |
---|
default |
Preliminari
In più casi dovremo eseguire uno script su tutte i nodi, per farlo possiamo utilizzare il seguente script runsetup.sh
:
#!/bin/bash
# Our custom function
file=$1
cust_func(){
echo "I am ${url}"
scp $file root@$url:/root/$file
ssh root@$url chmod +x /root/$file
NUMBER=$(echo $url | tr -dc '0-9')
ssh root@$url /root/$file $NUMBER
}
while IFS= read -r url
do
cust_func "$url $file" &
done < list.txt
wait
echo "All commands have been run."
seguito dal nome script.sh
che vogliamo eseguire su tutte le macchine, e.g.,
./runsetup.sh script.sh
Script di configurazione iniziale del nodo
Script runsetup.sh
utilizzato per installare le macchine:
#!/bin/bash
mkdir /scratch
chown -R rock:rock /home/rock
# Don't ask for anything
export DEBIAN_FRONTEND=noninteractive
# Cambia il fuso orario
timedatectl set-timezone Europe/Rome
# Fixa la chiave pubblica delle repository (da https://forum.radxa.com/t/gpg-error-with-ubuntu-server-20-04/13392)
wget -O - apt.radxa.com/focal-stable/public.key | sudo apt-key add -
# Repository aggiuntive
add-apt-repository ppa:gluster/glusterfs-7 -y
# Update & Upgrade
apt update -y && apt upgrade -y
# Install required packages
apt -y install build-essential gcc openmpi-bin openmpi-common libopenmpi-dev glusterfs-server slurm python3-pip valgrind tree git curl man-db mc parallel neovim unrar atool
e che può essere eseguito come:
./runsetup.sh script.sh
Personalizzare la shell di login sul Nodo 0
Possiamo personalizzare il messaggio che appare al login sul nodo zero creando il seguente script /etc/update-motd.d/05-info
:
#! /usr/bin/env bash
export TERM=xterm-256color
# Basic info
HOSTNAME=$(uname -n)
ROOT=$(df -Ph | grep mmcblk0p5 | awk '{print $4}' | tr -d '\n')
IFS=. read -r s _ < /proc/uptime; d=$((s / 60 / 60 / 24)); h=$((s / 60 / 60 % 24)); m=$((s / 60 % 60)); [ "$d" = 0 ] || UPTIME="${UPTIME}${d}d "; [ "$h" = 0 ] || UPTIME="${UPTIME}${h}h "; [ "$m" = 0 ] || UPTIME="${UPTIME}${m}m "; UPTIME="${UPTIME:-0m}"
KERNEL=$(uname -r)
RAID=$(lsblk -b -n -d | awk '$NF!~/sd[a-z]$/ && $NF!~/md[0-9]+$/ && !/loop/ {sum+=$4} END {printf "%.0f", sum/2/1024/1024/1024}')
TEMP_BIG="$(paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp) | column -s $'\t' -t | sed 's/\(.\)..$/.\1°C'/ | head -1| cut -d' ' -f3 )"
TEMP_LITTLE="$(paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp) | column -s $'\t' -t | sed 's/\(.\)..$/.\1°C/'| tail -1| cut -d' ' -f3 )"
# System load
MEMORY1=`free -t -m | grep Total | awk '{print $3" MB";}'`
MEMORY2=`free -t -m | grep "Mem" | awk '{print $2" MB";}'`
LOAD1=`cat /proc/loadavg | awk {'print $1'}`
LOAD5=`cat /proc/loadavg | awk {'print $2'}`
LOAD15=`cat /proc/loadavg | awk {'print $3'}`
echo "$(tput setaf 1)===================================================
_______________________ _______ _______ _______ _
( ____ \__ __( ____ ( ____ ( ____ ( ____ ( )
| ( \/ ) ( | ( \/ ( \/ ( \/ ( \//
| (_____ | | | (__ | (__ | (__ | (__
(_____ ) | | | __) | __) | __) | __)
) | | | | ( | ( | ( | (
/\____) | | | | (____/\ ) | ) | (____/
\_______) )_( (_______// |/ (_______/
$(tput setaf 2)
===================================================
- Hostname............: $HOSTNAME
- Disk Space..........: $ROOT remaining
- RAID Space..........: $RAID GB remaining
$(tput setaf 4)===================================================
- CPU usage...........: $LOAD1, $LOAD5, $LOAD15 (1, 5, 15 min)
- Memory used.........: $MEMORY1 / $MEMORY2
$(tput setaf 5)===================================================
- Temperature big.....: $TEMP_BIG
- Temperature little..: $TEMP_LITTLE
$(tput setaf 3)===================================================
- Kernel..............: $KERNEL
- Uptime..............: $UPTIME
$(tput sgr0)==================================================="
dnsmasq
e rete interna
dnsmasq
è un software libero che fornisce funzionalità di memorizzazione nella cache DNS (Domain Name System), un server DHCP (Dynamic Host Configuration Protocol), router advertisement e funzionalità di avvio di rete, destinato a reti di computer di piccole dimensioni. Nel nostro caso è utilizzato come server DHCP per assegnare gli indirizzi ai nodi del cluster sulla rete interna (NAT) e offrire un servizio di DNS (nodi raggiungibili tramite il loro nome e non tramite il loro indirizzo IP).
Configurazione dnsmasq
Per lanciare questo servizio è necessario liberare la porta 53 da eventuali servizi che la occupino già, su Ubuntu questo vuol dire disabilitare systemd-resolved
.
sudo systemctl disable --now systemd-resolved
sudo apt install dnsmasq
impostare nel suo file di configurazione la funzione di DHCP de-commentando la riga dhcp-range
nel file /etc/dnsmasq.conf
, e finalmente lanciare il servizio:
sudo systemctl enable --now dnsmasq
Configurazione rete interna (NAT)
Per avere il funzionamento del nostro guarded Beowulf, abbiamo bisogno che il nodo 0, nodo di accesso, sia equipaggiato di due schede di rete. Una sarà connessa verso l'esterno, rendendo quindi il nodo un frontend per gli utenti, l'altra verso tutti i nodi del cluster. Dal punto di vista operativo, questo vuol dire che un pacchetto in arrivo dall'esterno dovrà essere tradotto di indirizzo per raggiugere i nodi interni della rete. Nell'ambito delle reti questa funzione è svolta dal network address translation (NAT), ovvero il meccanismo che permette proprio di modificare l'indirizzo IP dei pacchetti in transito attraverso un genrico apparato di rete - il nostro nodo 0 - all'interno di una comunicazione in corso tra un utente e gli altri nodi del cluster.
Su Ubuntu questo può essere fatto tramite il programma iptables
:
sudo apt install iptables
echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward
cd /etc/sysctl.d/
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/10-ip-forwarding.conf
In /etc/network/interfaces
, per configurare permanentemente l'IP statico della macchina all'interno della LAN, l'IP pubblico e per creare la NAT del cluster:
auto eth0
iface eth0 inet static
address 192.168.0.2
netmask 255.255.255.0
auto enxd03745888a34
iface enxd03745888a34 inet static
address 131.114.10.121
netmask 255.255.255.0
gateway 131.114.10.1
post-up /usr/sbin/iptables -t nat -A POSTROUTING -o enxd03745888a34 -s 192.168.0.0/24 -j MASQUERADE
Infine:
sudo systemctl restart dnsmasq
sudo reboot
Dobbiamo inoltre comunicare il DNS a tutti i nodi in modo che possano risolvere le connessioni tra loro, ad esempio creando lo script fixdns.sh
:
sudo echo "nameserver 192.168.0.2" >> /etc/resolvconf/resolv.conf.d/head
sudo ln -sf /run/resolvconf/resolv.conf /etc/resolv.conf
sudo resolvconf -u
ed eseguendo
./runsetup.sh fixdns.sh
GlusterFS
Creiamo la cartella che conterrà le home condivise in tutti i nodi e attiviamo il servizio GlusterFS:
sudo mkdir /data${i}
systemctl enable --now glusterd
Per installare GlusterFS dobbiamo per prima cosa permettere le connessioni dagli altri nodi attraverso il Firewall:
for i in {1..20}; do sudo iptables -I INPUT -p all -s steffe$i -j ACCEPT; done;
Ora dobbiamo far riconoscere i nodi tra di loro
sudo gluster peer probe steffe0
for i in {1..20}; do sudo gluster peer probe steffe${i}; done;
e creare il volume condiviso:
sudo gluster volume create data replica 3 transport tcp steffe0:/data0 steffe1:/data1 steffe2:/data2 steffe3:/data3 steffe4:/data4 steffe5:/data5 steffe6:/data6 steffe7:/data7 steffe8:/data8 steffe9:/data9 steffe10:/data10 steffe11:/data11 steffe12:/data12 steffe13:/data13 steffe14:/data14 steffe15:/data15 steffe16:/data16 steffe17:/data17 steffe18:/data18 steffe19:/data19 steffe20:/data20 force
sudo gluster volume start data
sudo gluster volume info
Possiamo quindi montare i dischi facendo
mkdir -p /mnt/data
mount -t glusterfs steffe0:data /mnt/data
(da mettere poi in /etc/fstab
come steffe0:/data /mnt/data glusterfs defaults,_netdev 0 0
)
Slurm Workload Manager
Slurm Workload Manager, precedentemente noto come Simple Linux Utility for Resource Management (SLURM), o semplicemente Slurm, è un job scheduler gratuito e open source per kernel Linux e Unix-like, utilizzato da molti dei supercomputer e cluster di computer del mondo.
Fornisce tre funzioni fondamentali:
- assegnazione di accesso esclusivo e/o non esclusivo ai nodi di calcolo agli utenti per un certo periodo di tempo in modo che possano eseguire i loro job,
- fornire un framework per l'avvio, l'esecuzione e il monitoraggio dei job che contengono (in genere) istruzioni parallele di tipo MPI sull'insieme di nodi allocati,
- arbitrare la "contesa" per le risorse gestendo una coda di lavori in sospeso.
Per prima cosa dobbiamo installare Slurm su tutti i nodi del cluster
sudo apt-get update -y
sudo apt-get install slurmd slurmctld -y
Generare un file di configurazione mediante il configuratore online e inserirne il contenuto in
/etc/slurm/slurm.conf
Al termine della configurazione avviare il servizio:
sudo systemctl enable --now slurmctld
sudo systemctl enable --now slurmd
Raid
Per controllare lo stato del raid, utilizzare
cat /proc/mdstat
NFS
Sul control node:
sudo apt install nfs-kernel-server
Configurare /etc/exports
come desiderato, ad esempio
/mnt/raid steffe1(rw,sync,no_root_squash,no_subtree_check)
...
e poi sudo systemctl restart nfs-kernel-server.service
Sui compute nodes:
mkdir -p /mnt/raid
mount -t nfs steffe0:/mnt/raid /mnt/raid
(da mettere poi in /etc/fstab
come steffe0:/mnt/raid/ /mnt/raid nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
)
Creazione utenti
Affinché un programma possa essere lanciato su tutti i nodi è necessario che l'utente sia disponibile su ciascuno di essi, il seguente script si occupa di replicare l'utente ovunque sia necessario:
#!/bin/bash
#
# Add a SLURM user to the Steffè cluster
# A good place for this script is in:
# /usr/local/bin/cluster-users
set -e
cluster_hosts="steffe1 steffe2 steffe3 steffe4 steffe5 steffe6 steffe7 steffe8 steffe9 steffe10 steffe11 steffe12 steffe13 steffe14 steffe15 steffe16 steffe17 steffe18 steffe19 steffe20"
function help {
echo "Usage: $0 COMMAND username"
echo ""
echo "Examples: "
echo " -) $0 --add utente"
echo " -) $0 --delete utente"
}
function add_user {
if [ "$1" == "" ]; then
echo "Specify a valid username for the new user"
exit 1
fi
if [ "$2" != "" ]; then
echo "Unsupported option specified"
exit 1
fi
sudo mkdir -p /mnt/raid/home
sudo adduser --home=/mnt/raid/home/$1 $1
# We obtain the UID of the new user, as the last line at the end
# of passwd
userid=$(grep $1 /etc/passwd | tail -n1 | cut -d ':' -f3)
for h in ${cluster_hosts}; do
echo -n "Creating the user $1 on $h ... "
ssh root@${h} useradd -u ${userid} $1
echo "done"
done
}
function del_user {
if [ "$1" == "" ]; then
echo "Specify a valid username to delete"
exit 1
fi
if [ "$2" != "" ]; then
echo "Unsupported option specified"
exit 1
fi
echo -n "This command will remove the user $1, proceed? [yn]: "
read ans
if [ "$ans" != "y" ]; then
echo "Exiting"
exit 0
fi
sudo userdel -f $1
for h in ${cluster_hosts}; do
echo -n "Deleting the user $1 on $h ... "
ssh root@${h} userdel -f $1
echo "done"
done
echo "Note: the home directory /mnt/raid/home/$1 has been preserved,"
echo " you may wish to delete that as well."
}
if [ "$1" == "--add" ]; then
add_user $2
exit 0
fi
if [ "$1" == "--delete" ]; then
del_user $2
exit 0
fi
help
Assicurarsi che tutto funzioni al riavvio del Cluster
- Montare RAID sul control node se non l'ha fatto in automatico (ovvero spegnere e riaccendere il case dei dischi dal power button, fa tutto
/etc/fstab
) - Riavviare glusterd sui compute nodes (sicuramente non si sono avviati tutti prima del control node): [da
rock
]:./runsetup.sh mountgluster.sh
. Se/mnt/data
non funziona dasteffe0
, riavviare il serviziomnt-data.mount
(eventualmente anche sulle altre macchine, sta già inmountgluster.sh
). - Rimettere su i nodi (in modo che vadano tutti da DOWN ad IDLE nell'output di
sinfo
):
for i in {1..20}; do sudo scontrol update nodename=steffe$i state=idle; done
- riavviare
nfs-kernel-server.service
susteffe0
(sesteffe0
si accende prima degli altri non riesce a risolvere gli hostname all'avvio) e poi rimontare dappertutto con./runsetup.sh mount-raid-nfs.sh
(TODO {anche per gluster} trovare un modo di far funzionare gli FSTAB all'avvio...)