Avviare un sistema senza disco, con PXE, dnsmasq e syslinux

Si può far funzionare un computer senza hard disk? In una rete in cui sia presente un altro computer capace di erogare un kernel e un filesystem si può, senza rinunciare a nulla.
Vediamo come, con PXE, dnsmasq e syslinux, in GNU/Linux.

Obiettivo

Si può aver bisogno di un sistema operativo interamente remoto per diverse ragioni. Ad esempio per risparmiare il costo di un hard disk – magari uno per decine di postazioni, o perché abbiamo un dispositivo molto piccolo e non abbiamo spazio, oppure per amministrare un unico sistema da replicare in diversi computer o per svolgere gli interventi di manutenzione offline, quando il computer destinatario è spento. O altro.

Ingredienti

Occorrono un po’ di cose.

  • Il firmware del computer destinatario, che chiameremo slave, deve essere dotato di sistema di boot PXE (quasi sempre vero nei normali computer).
  • Occorre almeno un altro computer che fornisca il necessario allo slave, e lo chiameremo master. In scenari complessi, il ruolo di master può essere suddiviso tra diverse postazioni. Il master dovrà a sua volta agire come:
    • DHCP server, per avviare la partecipazione alla rete dello slave;
    • TFTP serve, per fornire almeno un bootloader e un kernel;
    • NFS server, per fornire un filesystem al computer senza disco.
  • Una rete Ethernet o WiFi o mista.
  • Un bootloader capace di avviare il sistema in queste condizioni.

E inoltre un po’ di destrezza e un paio di pomeriggi di pioggia.

Questo scenario ammette delle varianti, alle quali faremo soltanto cenno alla fine dell’articolo.

Lo slave

In termini strettamente fisici, lo slave deve solo disporre di un firmware in grado di avviarsi in modalità PXE. Questo si verifica nella quasi totalità dei computer moderni, con la sola eccezione di sistemi molto piccoli, come il Raspberry PI.

Questo non vuol dire che non occorre occuparsene. Il master deve fornire allo slave un kernel e un impianto di programmi adeguati all’hardware ricevente e agli scopi prefissati. In altre parole, dovremo comunque costruire un sistema operativo completo adeguato allo slave, anche se i file risiedono in hard disk remoti.

Come fare a costruire un sistema completo in queste condizioni esula dagli scopi di questo articolo. Possiamo immaginare di usare una distribuzione live, oppure di trovare in rete dei filesystem generici. Alcuni sanno perfettamente come costruire un sistema operativo per un computer che ancora non c’è, come i coraggiosi utilizzatori di LFS o i più prosaici utilizzatori di Arch Linux e Gentoo Linux.

Il metodo più semplice, anche se probabilmente meno utile, è quello di disporre inizialmente di un hard disk anche per lo slave, installare o avere già installato lì il nostro sistema operativo e copiare tutto il materiale necessario con rsync, poi possiamo rimuovere l’hard disk in prestito.

Per semplicità, facciamo riferimento a quest’ultimo metodo, anche se è quello che appare meno utile e interessante. Immaginiamo quindi di avere già a disposizione il sistema operativo necessario.

Preparazione del sistema slave

Dovremo assicurarci che il sistema dello slave abbia alcune caratteristiche.

Caratteristiche dello slave

Chi configura il proprio kernel deve assicurarsi di compilare monoliticamente gli elementi necessari per il funzionamento della rete e del client NFS. Anche se le operazioni iniziali verranno eseguite dal bootloader, infatti, il sistema ha bisogno di questi elementi per funzionare. Appoggiarsi ad una initrd può essere una soluzione, tanto più che ormai va fatta per forza, ma probabilmente è più intelligente adottare una configurazione di questo genere.

Inoltre avremo bisogno dei pacchetti necessari per la gestione user-space del client NFS. Ad esempio, in Gentoo:

Nel corso dell’articolo utilizzeremo NFSv4, ma non è indispensabile.

D’altro canto non avremo più bisogno di alcuni pacchetti. Ad esempio non avremo più bisogno del bootloader, ma nemmeno di tutte quelle utility di gestione del disco, come LVM, hdparm o i gestori dei filesystem. Potremo fare dopo un po’ di pulizia.

Trasferimento dei file dello slave nel master

Prepariamo pertanto una directory del master per ospitare il filesystem che forniremo. In questo articolo useremo

Ora non dovremo fare altro che trasferirlo in una directory del master, con un comando simile a:

Sarà bene controllare attentamente questo comando, secondo le caratteristiche specifiche del sistema slave.

Preparazione finale

Occorrono ancora un paio di accorgimenti.

Per rispettare i vincoli di sicurezza del TFTP, sarà utile spostare il kernel e l’eventuale initrd in una directory diversa, in quella che sarà fra poco la nostra tftp-root.

Ovviamente i nomi dei file possono essere differenti. Alla fine la directory /diskless/filesystems/slave/boot potrebbe essere cancellata, ma sarà utile tenerla per gli aggiornamenti futuri.

Inoltre abbiamo omesso del materiale importante: alcune directory di sistema e una coppia di device che saranno utili per l’avvio. Rimettiamo tutto a posto.

Infine, in paio di accorgimenti di configurazione.

Terminato il processo di avvio, li kernel rimonta nuovamente il filesystem utilizzato dal bootloader in sola lettura, utilizzando le indicazioni contenute in /etc/fstab. Dunque dobbiamo rimuovere tutti i montaggi concepiti per il disco locale e avere una riga assomigliante alla seguente:

Inoltre potremo eliminare gli script di avvio della rete, che risulterà già configurata prima ancora che il processo init sia stato avviato. Oppure, per non spezzare le dipendenze tra gli script di avvio, il servizio rete rete dovrà avviarsi senza modificare lo stato dell’interfaccia.
Ad esempio, in Gentoo:

Fatto questo, lo slave è pronto.

Il sistema master

Per due degli scopi del master, utilizziamo un unico software: dnsmasq.
dnsmasq riunisce in un unico demone i servizi di DHCP, DNS e TFTP server. È un software delizioso per soluzioni piccole e medie e anche per questo esempio. Ha una configurazione molto versatile e convive facilmente con sistemi di rete più complessa, operando come cache dove l’infrastruttura è più potente.

Non ci addentreremo in tutta la movimentata configurazione di dnsmasq, ma ci occuperemo solo di quella manciata di opzioni che serviranno al nostro bootstrap remoto.

Installiamo dunque dnsmasq. In Gentoo:

Come bootloader utilizziamo syslinux. È un bootloader pensato per agire in situazioni non convenzionali e una di queste è proprio PXE.

Installiamo subito anche syslinux. In Gentoo:

Si osservi che syslinux dovrà avviare lo slave, ma viene installato nel master. Niente di strano, visto quel che dobbiamo fare, ora abbiamo a disposizione un equipaggiamento di file da utilizzare più avanti. E nessun timore: il bootloader del master non verrà toccato.

Il server DHCP

Abbiamo detto che il sistema che si avvia in PXE inizia la sua attività con la ricerca di un server DHCP. dnsmasq agisce per default come server DHCP. Tutto quello che dobbiamo fare è gestire la specificità di PXE. In /etc/dnsmasq.conf :

La prima opzione seleziona una signature del richiedente e un indirizzo IP. Anzi, nel caso dell’esempio non seleziona nulla, offrendo a qualsiasi richiesta PXE quanto necessario.
La seconda opzione indica il nome del bootloader che dovrà essere caricato tramite TFTP.

Poiché non ci sono altre opzioni, lo slave considererà che l’host che fa da server TFTP è lo stesso del DHCP. Nello slave è ancora il firmware ad agire e una volta configurata la propria rete chiederà il bootloader al server TFTP.

Il server TFTP

Dobbiamo preparare dnsmasq per agire anche come server TFTP:

La prima opzione non fa altro che abilitare il server. La seconda stabilisce il punto d’origine dei file che possono essere trasferiti. La directory è stata già creata quando abbiamo preparato il kernel dello slave.

Con questa semplice configurazione, il server TFTP è pronto a ricevere la richiesta dello slave, che chiede, come abbiamo stabilito, il bootloader pxelinux.0.

syslinux

Copiamo il bootloader dall’equipaggiamento di syslinux nella tftp-root:

Non basta. La prima operazione del bootloader è interrogare di nuovo il server TFTP per ottenere un file di configurazione. Questo è un comportamento predefinito.
Il file di configurazione verrà cercato nella directory pxelinux.cfg, sempre all’interno della tftp-root. Creiamo quindi la directory:

Il nome del file di configurazione da fornire viene ricavato da una sequenza. Il primo file che viene cercato è quello il cui nome è costruito sulla base del MAC address dello slave. In mancanza di questo, vengono cercati in sequenza file il cui nome è ottenuto dalla rappresentazione esadecimale dell’indirizzo IP che è stato fornito, o di tutte le parti sinistre di quella rappresentazione. In mancanza di questi, infine, viene fornito un file chiamato default.

Ad esempio, per uno slave di tipo Ethernet (ARP type 1) con MAC address 88:99:AA:BB:CC:DD e che abbia ricevuto un indirizzo IP 192.0.2.91, la sequenza di ricerca è:

Questa sequenza consente di preparare configurazioni personalizzate, raggruppate o generalizzate. Per saperne di più basta leggere How do I Configure PXELINUX?, nel wiki di syslinux (da cui ho copiato l’esempio).

Nel nostro caso, poiché abbiamo un sistema operativo costruito per una macchina in particolare, utilizziamo il nome di file basato sul MAC address. Il file di configurazione dunque è:

syslinux supporta i menu di avvio, come lilo e grub. Dunque la prima riga indica il blocco da avviare per default e il blocco successivo, che in questo caso è l’unico, indica la configurazione da utilizzare.

La riga SAY è evidentemente un testo che verrà stampato a video.
KERNEL indica il file che dovrà essere prelevato come kernel, ovviamente sempre attraverso il TFTP. E infatti si tratta proprio del file che abbiamo copiato nella sezione relativa alla preparazione dello slave.
APPEND sono le opzioni di boot del kernel. Come si vede è una riga articolata, dove possiamo divertirti a utilizzare le opzioni più raffinate, che già conosciamo. Alcune, però, sono specifiche per questo scenario:

  • bootif indica di esegure il bootstrap solo se il MAC è quello indicato; in questo caso è una ridondanza, visto che lo stesso file di configurazione è destinato al quel MAC;
  • root  è apparentemente la solita opzione, ma assume un valore simbolico che indica che la directory root (/) verrà prelevata tramite NFS; si osservi che è una notazione simbolica, il device /dev/nfs non esiste;
  • nfsroot  è il percorso della root (/), che verrà montata tra poco.

Come si vede, la procedura di avvio inizia ad assumere forme più simili a quelle già note. Resta solo da allestire il server NFS.

Il server NFS

Questo è un lavoro che sappiamo già fare.

Per agire come NFS server il master deve avere un kernel adeguato:

Deve inoltre disporre delle stesse utility user-space dello slave:

Una volta equipaggiati a dovere, il nostro /etc/exports deve apparire più o meno come segue:

Questa configurazione in realtà è un po’ troppo permissiva, ma funzionerà. In un caso meno scolastico, converrà assegnare staticamente un indirizzo IP al MAC address e fornire quel filesystem solo al destinatario desiderato. Oppure concepire scenari più complessi. Per il nostro esercizio la lasciamo così.

Non resta che avviare lo slave.

Riepilogo dei file del master

È utile, probabilmente, riepilogare la struttura di file che abbiamo utilizzato.

A partire da questo assetto, è possibile costruire configurazioni più complesse, in grado di avviare più macchine con diversi scenari.

Avvio dello slave

Tra le opzioni di boot fornite dal BIOS dello slave, dovrebbe essercene una che riguarda l’avvio tramite rete. Non occorre fare altro che selezionarla.

PXE boot selection
PXE boot selection

Con un po’ di fortuna il computer si avvierà regolarmente e sarà pronto per l’uso.

Opportunità e limitazioni

Ci sono dei pro e dei contro.

Iniziamo dai contro. Sebbene lo slave sia una macchina funzionante a tutti gli effetti, patirà le sofferenze di una rete lenta pure essendo libero da quelle di un eventuale disco lento.Ad esempio, l’avvio di X attraverso una connessione WiFi di media qualità si è rivelato faticoso, in quanto talmente lento da incappare nel timeout di 60 secondi che lo stesso X da a se stesso per partire. Questo scenario è stato riscontrato nel tentativo di utilizzare KDM (il dispaly manager di KDE) ed è stato facilmente aggirato utilizzando al suo posto LXDM (il display manager di LXDE). Con LXDM, poi, è stato possibile avviare KDE in modo un po’ lento ma sostanzialmente normale.
Un altra limitazione, in uno scenario del genere, potrebbe essere la swap. L’uso del file di swap è generalmente abbastanza avvilente, ancora più drammatico sarebbe in una postazione senza disco con una rete lenta. Con l’equipaggiamento di RAM dei computer moderni, comunque, l’uso dello swap è sempre più raro.

In generale, se la rete è lenta, l’avvio dei programmi potrebbe essere altrettanto lento. Una volta avviati, però, i programmi si comportano in modo sostanzialmente normale e l’esperienza d’uso del computer è quella di sempre.

Ci sono anche dei vantaggi, però. Primo tra tutti quello di effettuare la manutenzione offline, cioè quando lo slave è spento.

È immediato, infatti, comprendere che i file di configurazione dello slave sono immediatamente disponibili nel master. Ma non è tutto qui, si può animare il sistema slave (purché sia costruito per la stessa architettura del master) e renderlo vivo, accedendovi in modo quasi normale.

Questo si può fare con tutti i sistemi Linux. La magia, perché appare proprio una magia, è quella di preparare il filesystem dello slave e poi eseguire il chroot:

chroot  esegue un programma (il secondo argomento) considerando come root (/) il primo argomento. In pratica ci si ritrova esattamente nello slave e si può operare.

Di fatto, occorrono alcuni accorgimenti: una volta fatto il chroot occorre ricaricare tutte le variabili d’ambiente dello slave, rileggere il file  /etc/profile  e considerare che la configurazione di rete e i servizi sono quelli ereditati dal master.

Una volta compresi tutti i dettagli di questa manovra – come sono abituati a comprendere gli utenti di Gentoo Linux e Arch Linux – sarà possibile aggiornare e installare i pacchetti, compilare nuovi kernel (ricordiamo di portarne una copia in tftp-root!) e gestire tutte le caratteristiche del sistema, in attesa di un vero avvio.

Un esempio diverso: SystemRescueCD

Una delle applicazioni più interessanti di questa tecnologia è la possibilità di garantire un avvio di emergenza a tutti i computer della rete, con SystemRescueCD o con altri sistemi live.

Poiché quasi tutti i computer possiedono PXE come opzione di boot, si può fornire un avvio di questo tipo a tutta la rete, per tutti quei casi in cui il sistema operativo ordinario sia danneggiato al punto da non consentire un avvio normale.

SystemRescueCD possiede già al momento del download tutti gli ingredienti necessari: è sufficiente un montaggio di tipo loop della iso scaricata e la copia del kernel e della initrd associata nella tftp-root.

Poi bisogna costruire una configurazione (file default) di questo genere:

Infine, aggiungere una riga corrispondente a /etc/exports:

Non ci addentriamo ulteriormente, ma se si vuole un buon esempio si può leggere il wiki di Funtoo, attraverso il link qui in basso, che usa proprio SystemRescueCD per descrivere PXE.

Scenari alternativi

Tutto quello che è stato descritto adesso si può ottenere in modi leggermente diversi.

Non è detto che il filesystem debba essere fornito in NFS. Se ci accontentiamo di un filesystem in sola lettura, possiamo montare un filesystem in HTTP. Se invece abbiamo bisogno di piena funzionalità, possiamo considerare anche NBD ed eventualmente altri scenari ancora.

Anche l’uso di dnsmasq è assolutamente soggettivo. Una scelta più tradizionale potrebbe suggerire di usare dhcpcd e tftp-hpa.

Una volta compreso il meccanismo, insomma, si aprono scenari a ventaglio.

Riferimenti

Leave a Comment

Your email address will not be published.

Analisi degli accessi a www.istat.it
×
', 'auto'); ga('require', 'displayfeatures'); ga('set', 'forceSSL', true); ga('send', 'pageview');