Gentoo Linux OpenMosix Tutorial
1.Introduzione
OpenMosix cos'è
OpenMosix è uno dei sistemi di clustering più avanzati per gli
ambienti di calcolo scientifico. Si contraddistingue per la facilità
d'uso e per le alte prestazioni. OpenMosix è in grado di implementare
il concetto di Single System Image, cioè un insieme di nodi individuali
che danno all'utente e agli applicativi la visione di un unico grande computer.
L'utente quindi non sa se un processo sta andando su un nodo che non è
il suo. Attraverso algoritmi di bilanciamento, un processo in esecuzione
su un nodo può 'migrare' in modo trasparente su di un altro nodo dove può
attingere maggiori risorse. Infatti gli algoritmi di bilanciamento di OpenMosix
fanno sì che i programmi abbiano sempre a disposizione le risorse
necessarie. Fino a quando le risorse necessarie sono disponibili localmente,
il processo rimarrà sul nodo sul quale è stato lanciato.
Quando invece le risorse richieste superano quelle locali, il processo 'migra'
in tempo reale verso un altro nodo che in quel momento ha un minor carico di
lavoro.
OpenMosix è in sostanza una patch da applicare al kernel standard
di Linux e riguarda esclusivamente il cluster vero e proprio. Per la sua
gestione, configurazione e monitoraggio, ci sono delle utility che girano
nello user-space.
2.Installazione
Note sull'installazione
Il processo di installazione e configurazione di un cluster OpenMosix è
attualmente abbastanza semplice. Prima di tutto dovremo installare un kernel
Linux con OpenMosix abilitato su ogni macchina che diventerà un nodo
del cluster. Quindi installeremo le utility OpenMosix userland tools su
ogni sistema. Alla fine dovremo configurare un paio di files in /etc e,
se non esiste, creare uno script di startup.
Installazione di OpenMosix
Per installare il software sul nostro nodo Gentoo dobbiamo avvalerci
del mitico emerge:
Esempio 1 |
# emerge sys-apps/openmosix-user
|
Il comando precedente dovrebbe installare un OpenMosix kernel insieme alle
utility OpenMosix. Questo tutorial è stato scritto per il kernel 2.4.22
che al momento è quello installato di default e per la versione 0.3.4 di
openmosix-user.
Creazione di un kernel OpenMosix
La prima cosa da fare è andare nella directory dei sorgenti del kernel ;-)) e inizializzare la procedura:
Esempio 2: Inizializzare la compilazione del kernel |
# cd /usr/src/linux
# make mrproper
|
Fatto questo possiamo proseguire con la configurazione, compilazione e installazione
del kernel. Tutto ciò di cui abbiamo bisogno è di abilitare gli
appropriati set sotto la nuova sezione openMosix:
Esempio 3: Opzioni da attivare nel kernel |
# make menuconfig
[*] openMOSIX process migration support
[*] Stricter security on openMOSIX ports
[*] Direct File-System Access
[*] openMOSIX File-System
[*] Poll/Select exceptions on pipes
|
Il resto della fase di configurazione, compilazione e installazione del
kernel dovrebbe proseguire normalmente. Una volta che tutti i nodi hanno un
kernel openMosix installato, è il momento di installare le utility
userland su ogni nodo.
Nota:
Un suggerimento. Installate anche un vanilla-kernel nel caso qualcosa
non vada a buon fine col kernel openMosix. Usando gentoo 1.4 col
kernel openMosix 2.4.22, ci potrebbe essere un problema al riavvio
del PC. Il kernel si blocca senza errori apparenti prima di montare
il devfs. Sembra che il problema sia l'ottimizzazione troppo aggressiva
che viene attivata di default durante l'installazione di gentoo.
Se in /etc/make.conf troviamo -O3, proviamo a porla uguale
a -O2 e ricompilare il kernel, ricordandosi di dare un bel make mrproper
prima di partire.
|
Configurazione delle utility userland
Gli OpenMosix userland tools sono facili da configurare.
Prima di tutto dobbiamo creare il file /etc/openmosix.map. Questo
file ha la seguente sintassi:
Esempio 4: Sintassi di /etc/openmosix.map |
numero_nodo indirizzo_IP range
|
"numero_nodo" dovrebbe essere il numero ufficiale di ogni nodo partendo
da 1 con incremento di 1 per ogni linea successiva. Segue l'"indirizzo_IP" di ogni nodo e
1 per "range". Per esempio un openmosix.map che consiste in due nodi
con IP 192.168.1.1 e 192.168.1.9
dovrebbe apparire nel seguente modo:
Esempio 5: Esempio di /etc/openmosix.map |
1 192.168.1.1 1
2 192.168.1.9 1
|
Se invece avete ad esempio 10 nodi con IP consecutivi che partono dal 192.168.1.1
al 192.168.1.10 potete trarre vantaggio dal "range", infatti l' openmosix.map
conterrà solo una riga come segue:
Esempio 6 |
1 192.168.1.1 10
|
Senza l'argomento "range" avreste dovuto creare un openmosix.map
di 10 righe, una per ogni nodo.
Attenzione:
Notate che il file openmosix.map NON DEVE contenere righe di commento. Altrimenti alla partenza di openMosix avrete un errore del tipo "tabella
non ben formattata" ("table is not well-formatted").
|
Dobbiamo ora creare il punto di montaggio per l'oMFS (l'openMosix File System) e
configurare appropriatamente il file /etc/fstab affinché
il mounting avvenga automaticamente ad ogni riavvio del nodo:
Esempio 7: Configurazione per l'oMFS |
# mkdir /mfs
# vi /etc/fstab
oMFS /mfs mfs dfsa=1 0 0
|
Non ci resta che testare il nodo:
Esempio 8: Start del cluster |
# /etc/init.d/openmosix start
|
Se il comando ha successo, proviamo ad eseguire il seguente comando
(il numero indica il nodo, possiamo sostituirlo col numero del nodo
da testare):
Esempio 9 |
# mosctl status 1
Up.
|
Se il risultato è "Up" siamo a cavallo!!! Il nodo è correttamente
configurato e funzionante. Non resta
che aggiungere al sistema di startup lo script openmosix per
farlo partire ad ogni riavvio:
Esempio 10: Aggiungere openmosix al runlevel di default |
# rc-update add openmosix default
|
3.Testiamo il cluster
Una volta che abbiamo più di un nodo installato e funzionante, possiamo
testare veramente il cluster. Possiamo creare un piccolo script con le seguenti righe:
Esempio 11: Script di test |
# vi test
for x in 1 2 3 4
do
awk 'BEGIN{for(i=0;i<10000;i++)for(j=0;j<10000;j++);
done
|
Ne mandiamo in esecuzione un paio in background e controlliamo con l'utility
mosmon cosa succede:
Esempio 12 |
# ./test &
# ./test &
# mosmon
|
mosmon mostra in modalità testuale un grafico dell'attività di ogni
singolo nodo. Dovremmo quindi vedere un paio di nodi la cui attività
è notevole.
Figura 1: openMosix monitor |
 |
Se vogliamo proprio stressare il nostro cluster possimo installare l'openmosixtest,
una serie di tools che testano il cluster in vari modi, generando alla fine
un report su file molto dettagliato dei risultati ottenuti.
Per installare openmosixtest e iniziare il test:
Esempio 13 |
# emerge app-admin/openmosixtest
# cd /opt/omtest
# ./compile_tests.sh
# ./start_openMosix_test.sh
|
Potete ora andare a mangiare una pizza, a farvi una partita a scacchi o a
leggervi "Il Signore degli anelli", perché il test durerà abbastanza.
4.L'oMFS (openMosix File System)
Nel paragrafo sull'installazione e configurazione abbiamo visto come
abilitare nel kernel il supporto per l'oMFS e come montare l'openMosix
File System al ravvio del nodo, ma in pratica cos'è l'oMFS e a cosa
serve?
L'oMFS è un file system che dà una visione globale di tutti i file
system locali di ogni nodo, da ogni nodo. Sembra un'affermazione astratta e forse lo è.
Il suo creatore Moshe Bar lo definisce "uno strato astratto che mi permette
questa visione unificata globale, ma non è un file system che scrive
dati su un proprio disco. Per lo storage, oMFS si basa su qualsiasi
file system supportato da Linux" (L&C - Anno 4 Numero 24).
In pratica una volta che l'oMFS è montato in /mfs
su ogni nodo, ogni file systems di ogni nodo (escluso /proc),
è accessibile attraverso
/mfs/[openMOSIX_ID]/directory, e questo da ogni nodo.
Se andiamo dentro /mfs e facciamo un ls...:
Esempio 14: Test di oMFS |
# cd /mfs
# ls -l
total 16
drwxr-xr-x 20 root root 4096 Mar 8 22:13 1
drwxr-xr-x 20 root root 4096 Mar 8 1996 2
drwxr-xr-x 21 root root 4096 Mar 8 23:25 3
drwxr-xr-x 20 root root 4096 Mar 8 22:59 4
lr-xr-xr-x 1 root root 1 Dec 31 1969 here -> 1
lr-xr-xr-x 1 root root 1 Dec 31 1969 home -> 1
lr-xr-xr-x 1 root root 1 Dec 31 1969 lastexec -> 1
lr-xr-xr-x 1 root root 1 Dec 31 1969 magic -> 1
lr-xr-xr-x 1 root root 1 Dec 31 1969 selected -> 1
# ls 3
bin dev home lib mfs mnt proc sbin usr work
boot etc initrd lost+found misc opt root tmp var
|
È possibile quindi copiare file tra i vari nodi o accedere a file
residenti su nodi diversi, direttamente attraverso /mfs.
Questo permette ad un processo migrato su un nodo remoto di poter eseguire
chiamate di sistema (lettura, scrittura, apertura, creazione, chiusura, etc.)
senza dover tornare al nodo di origine.
Con l'aiuto di link simbolici, tutti i nodi del cluster possono accedere
agli stessi dati, p.e. /home_n01 sul nodo1:
Esempio 15 |
sul nodo2: # ln -s /mfs/1/home_n01 /home_n01
sul nodo3: # ln -s /mfs/1/home_n01 /home_n01
...
...
|
5.E se ho tanti nodi da montare?
Ecco un suggerimento per utenti più smaliziati e smanettoni che si trovano
a installare un certo numero di nodi su macchine con le stesse caratteristiche
hardware. In questi giorni mi sono trovato a dover installare un 'piccolo'
cluster di 12 nodi. Le macchine sono tutte nuove e hanno tutte le stesse
caratteristiche hardware. Installare Gentoo e configurare tutti i files per
arrivare ad avere un nodo funzionante richiede tempo e concentrazione per
questo ho pensato ad un modo 'rapido' per 'clonare' i nodi.
I passi che ho seguito sono semplici (altri suggerimenti sono veramente
apprezzati). Ho installato Gentoo su un nodo, facendo molta attenzione
ad installare tutto il necessario per il suo funzionamento. Quando tutto
funzionava perfettamente ho stoppato il sistema.
Quindi ho tolto il disco di sistema da un secondo nodo,
ho cambiato il jumper per renderlo slave, e l'ho messo in cascata al master
del nodo precedentemente installato.
Ho fatto ripartire il nodo che a questo punto ha due dischi.
Dopo il login come root:
Esempio 16 |
# fdisk /dev/hdb
|
Ho naturalmente creato le stesse partizioni del nodo funzionante, settato il
bootable flag su /dev/hdb1, salvato la tabella e creato lo swap e i filesystem ext3:
Esempio 17 |
# mkswap /dev/hdbX
# mke2fs -j /dev/hdbX
Dove X è la partizione da creare.
|
A questo punto col buon vecchio dd ho 'clonato' le partizioni:
Esempio 18 |
# dd if=/dev/hdaX of=/dev/hdbX
Anche in questo caso sostituire a X il numero della partizione.
|
Al termine della clonazione, ho montato la partizione / del secondo disco in /mnt per cambiare alcuni settaggi del nuovo nodo:
Esempio 19 |
# mount /dev/hdbX /mnt
# vi /mnt/etc/hostname
Cambio l'hostname.
# vi /mnt/etc/conf.d/net
Cambio l'IP del nuovo nodo.
|
Smontiamo quindi /mnt e stoppiamo il nodo:
Esempio 20 |
# umount /mnt
# halt
|
Rimontiamo fisicamente il disco sul nuovo nodo (ricordando di rimettere a posto
il jumper per renderlo nuovamente master), lo ricolleghiamo al sistema e
accendiamo il nuovo nodo. Se tutto va come dovrebbe abbiamo un nodo funzionante
con una fatica minima.
6.DSH, Distributed Shell
Introduzione
Ci sono dei momenti che dobbiamo lanciare dei comandi su ciascuno dei nodi
del nostro cluster. Collegarsi a ciascun nodo non è una soluzione valida.
Usare ssh o rsh richiede comunque la ridigitazione del comando col cambio dell'IP
o del nome del nodo.
Per farlo in modo più semplice ci viene in aiuto dsh una shell
distribuita. Ho scritto personalmente l'ebuild per l'installazione sia
della dsh che delle libdshconfig dalle quali è dipendente.
dsh usa rsh o ssh per l'esecuzione finale dei comandi.
Installazione
Per installare dsh usiamo il solito comando emerge:
Esempio 21 |
# emerge app-shells/dsh
|
Essendo dsh dipendente in fase di compilazione dalle libdshconfig, il
precedente comando dovrebbe installare anche queste ultime.
Configurazione
La configurazione è altrettanto semplice. Occorre creare il file mosix
(il nome del file può essere anche cambiato) dentro
$HOME/.dsh/group/ con al suo interno la lista degli ip dei nodi
che fanno parte del cluster.
Esempio 22: Configurazione di DSH |
# mkdir $HOME/.dsh
# mkdir $HOME/.dsh/group
# vi $HOME/.dsh/group/mosix
192.168.1.1
192.168.1.2
192.168.1.3
...
...
|
Uso
Vediamo come usare dsh per eseguire ls su tutti i nodi. Useremo
il flag -g per specificare il gruppo (in questo modo possiamo avere
più gruppi con differenti configurazioni).
Esempio 23 |
# dsh -r ssh -g mosix ls
192.168.1.1: anaconda-ks.cfg
192.168.1.1: install.log
192.168.1.1: install.log.syslog
192.168.1.2: anaconda-ks.cfg
192.168.1.2: install.log
192.168.1.2: install.log.syslog
192.168.1.3: anaconda-ks.cfg
192.168.1.3: install.log
192.168.1.3: install.log.syslog
...
...
|
Notate che nessuna delle macchine richiede la password. Questo perchè
ho configurato l'autenticazione rsa tra i vari nodi. Se volete eseguire
comandi con dei parametri devete racchiudere il comando tra virgolette:
Esempio 24 |
# dsh -r ssh -g mosix "uname -c"
|
o usare l'opzione -c:
Esempio 25 |
# dsh -r ssh -g mosix -c -- uname -a
|
7.Configurare SSH senza password
Il primo passo è generare un paio di chiavi per SSH sul nodo master
con ssh-keygen:
Esempio 26: Generazione della chiave rsa |
# ssh-keygen -t rsa
verrà richiesto l'inserimento e la conferma della passphrase
|
Questo comando creerà due file dentro $HOME/.ssh, id_rsa
(che è la chiave privata e non va data a nessuno) e id_rsa.pub (che è la chiave pubblica). Copiamo la chiave pubblica in un file chiamato authorized_keys:
Esempio 27 |
# cp $HOME/.ssh/id_rsa.pub $HOME/.ssh/authorized_keys
|
Il file $HOME/.ssh/authorized_keys va copiato sui nodi sempre in
$HOME/.ssh.
Esempio 28 |
# scp -p $HOME/.ssh/authorized_keys nodeX:$HOME/.ssh/authorized_keys
|
Se proviamo ad aprire una connessione SSH con un nodo
ci verrà richiesto l'inserimento della passphrase. Una volta immessa
dovremmo essere loginati. Ma qual è il vantaggio? La passphrase di solito
è più lunga di una normale password.
Ebbene, il vantaggio risiede nel fatto che possiamo usare ssh-agent
che amministra la passphrase durante un login ssh.
Facciamo una prova:
Esempio 29: Uso di ssh-agent |
# ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XXYqbMRe/agent.1065; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1066; export SSH_AGENT_PID;
echo Agent pid 1066;
|
L'esecuzione di ssh-agent produce la visualizzazione di due variabili
ambiente con tanto di valore che dovrebbero essere settate se già non
lo sono. Proviamo:
Esempio 30 |
# echo $SSH_AUTH_SOCK
# echo $SSH_AGENT_PID
|
Se non otteniamo risultati:
Esempio 31 |
Per la bash shell:
# export SSH_AUTH_SOCK=/tmp/ssh-XXYqbMRe/agent.1065
# export SSH_AGENT_PID=1066
Per la csh/tcsh shell:
# setenv SSH_AUTH_SOCK=/tmp/ssh-XXYqbMRe/agent.1065
# setenv SSH_AGENT_PID=1066
|
Con queste variabili il daemon sshd sull'host remoto può connettersi
al nostro ssh-agent locale usando il socket-file in /tmp (nel nostro esempio
/tmp/ssh-XXYqbMRe/agent.1065). ssh-agent può ora
passare la passphrase al nodo remoto usando questo socket (naturalmente
in modo cryptato).
Dobbiamo ora aggiungere la nostra chiave pubblica all'ssh-agent usando
ssh-add:
Dovremmo ora essere in grado di eseguire un login via ssh su un nodo remoto
senza la richiesta della passphrase.
Per evitare di eseguire tutte le operazioni che abbiamo visto in modo
manuale ad ogni login, possiamo inserire i seguenti comandi all'interno
del nostro login-profile (.bash_profile o .cshrc):
Esempio 33 |
# vi $HOME/.bash_profile
eval `ssh-agent`
ssh-add
|
Al prossimo login ci verra' richiesto l'inserimento della passphrase, e
potremmo per tutta la sessione di lavoro loginarci su un nodo remoto o usare
dsh senza che ci venga richiesto l'inserimento di alcuna password.
8.Script di partenza
Se per qualche motivo non fosse stato installato lo script di partenza,
potete ricopiarvi il seguente:
Esempio 34 |
# vi /etc/init.d/openmosix
#!/sbin/runscript
depend() {
need net
}
stop() {
ebegin "Stopping openMosix"
setpe -off
rm -f /var/lock/subsys/mosix
eend
}
start() {
ebegin "Starting openMosix"
if [ -s /etc/overheads -a -f /proc/mosix/admin/overheads ]
then
egrep -v '^#' /etc/overheads > /proc/mosix/admin/overheads
fi
if [ -s /etc/mfcosts -a -f /proc/mosix/admin/mfcosts ]
then
egrep -v '^#' /etc/mfcosts > /proc/mosix/admin/mfcosts
fi
local a1
local a2
a1=
[ -s /etc/mospe ] && a1=" -p `cat /etc/mospe`"
s2=
[ -s /etc/mosgates ] && a2=" -g `cat /etc/mosgates`"
setpe -W $a1 $a2 -f /etc/mosix.map
touch /var/lock/subsys/mosix
eend
}
|
|