RAID e LVM sono entrambe tecniche per astrarre i volumi montati dalle loro controparti fisiche (gli effettivi dischi fissi o le loro partizioni); il primo garantisce la sicurezza e la disponibilità dei dati in caso di guasto hardware introducendo la ridondanza, l'ultimo rende la gestione dei dati più flessibile e indipendente dall'effettiva dimensione dei dischi sottostanti. In entrambi i casi, il sistema acquisisce nuovi dispositivi a blocchi, che possono essere usati per creare filesystem o spazio di swap, senza necessariamente essere mappati su un unico disco fisico. RAID e LVM provengono da ambienti molto diversi, ma le loro funzionalità spesso si possono sovrapporre, che è il motivo per cui spesso vengono menzionati insieme.
Sia nel RAID che nell'LVM, il kernel fornisce un file di device a blocchi, simile a quelli corrispondenti a un disco fisso o a una partizione. Quando un'applicazione o un'altra parte del kernel richiede l'accesso a un blocco di questo device, il sottosistema appropriato dirige il blocco allo strato fisico di competenza. A seconda della configurazione, questo blocco può essere memorizzato su uno o più dischi fisici e la sua posizione fisica potrebbe non essere direttamente correlata alla posizione del blocco nel device logico.
RAID significa Redundant Array of Independent Disks (array ridondante di dischi indipendenti). Lo scopo di questo sistema è di impedire la perdita di dati e garantire la disponibilità in caso di guasto di un disco fisso. Il principio generale è molto semplice: i dati sono memorizzati su diversi dischi fisici piuttosto che su uno solo, con un livello di ridondanza configurabile. A seconda della quantità di ridondanza e anche in caso di guasto inatteso di un disco, i dati possono essere ricostruiti dai dischi rimanenti, senza alcuna perdita.
Il RAID può essere implementato sia tramite hardware dedicato (moduli RAID integrati in schede con controllori SCSI o SATA) sia tramite astrazione software (il kernel). Che sia hardware o software, un sistema RAID con sufficiente ridondanza può rimanere operativo in modo trasparente quando un disco si guasta; gli strati superiori della pila (applicazioni) possono perfino continuare ad accedere ai dati nonostante il guasto. Ovviamente questa «modalità degradata» può avere un impatto sulle prestazioni e inoltre viene ridotta la ridondanza, quindi un ulteriore guasto di un disco può provocare perdita di dati. In pratica, perciò, si cerca di rimanere in questa modalità degradata solo per il tempo necessario a sostituire il disco guasto. Una volta che il nuovo disco è al suo posto, il sistema RAID può ricostruire i dati richiesti e così tornare in modalità sicura. Le applicazioni non si accorgeranno di alcunché, a parte per la velocità di accesso potenzialmente ridotta, mentre l'array è in modalità degradata o durante la fase di ricostruzione.
Quando il RAID è implementato via hardware, la sua configurazione avviene generalmente all'interno dello strumento di configurazione del BIOS, ed il kernel considererà l'array RAID come un disco singolo, che funzionerà come un tradizionale disco singolo, anche il nome del dispositivo potrebbe essere differente (a seconda del driver).
In questo libro ci focalizzeremo sul RAID software.
12.1.1.1. Diversi livelli di RAID
Il RAID non è effettivamente un singolo sistema, ma una serie di sistemi identificati dai rispettivi livelli; che si distinguono per la loro disposizione e la quantità di ridondanza che forniscono. Più è ridondante, più è a prova di guasti, dal momento che il sistema sarà in grado di continuare a funzionare con più dischi rotti. Il rovescio della medaglia è che lo spazio utilizzabile diminuisce per un dato insieme di dischi; visto in un altro modo, servono più dischi per memorizzare la stessa quantità di dati.
- RAID lineare
Anche se il sottosistema del kernel permette di creare un «RAID lineare», questo non è un RAID vero e proprio, poiché questa configurazione non prevede alcuna ridondanza. Il kernel semplicemente aggrega diversi dischi in fila e mette a disposizione il volume aggregato che ne risulta come un unico disco virtuale (un unico device a blocchi). Questa è praticamente la sua unica funzione. Questa configurazione è raramente usata da sola (vedere più avanti per le eccezioni), soprattutto in quanto la mancanza di ridondanza implica che basta un guasto a un singolo disco per rendere l'intero aggregato, e dunque tutti i dati, indisponibile.
- RAID-0
Anche questo livello non fornisce alcuna ridondanza, ma i dischi non sono semplicemente messi in fila uno dietro l'altro: sono divisi in strisce e i blocchi sul device virtuale sono memorizzati su strisce su dischi fisici alternati. In un'impostazione RAID-0 a due dischi, per esempio, i blocchi di numero pari del device virtuale saranno memorizzati sul primo disco fisico, mentre i blocchi di numero dispari finiranno sul secondo disco fisico.
Questo sistema non mira ad aumentare l'affidabilità, in quanto (come nel caso del lineare) la disponibilità di tutti i dati è a rischio non appena un disco si guasta, ma ad aumentare le prestazioni: durante l'accesso sequenziale a grandi quantità di dati contigui, il kernel potrà leggere da entrambi i dischi (o scrivere su di essi) in parallelo, il che aumenta la velocità di trasferimento dei dati. I dischi vengono utilizzati interamente dal dispositivo RAID, quindi dovrebbero avere le stesse dimensioni per non avere perdita di prestazioni.
L'uso del RAID-0 sta diminuendo a favore di LVM (vedere più avanti).
- RAID-1
Questo livello, noto anche come «RAID mirroring», è la configurazione più semplice e più usata. Nella sua forma standard, usa due dischi fisici della stessa grandezza e fornisce un volume logico anch'esso della stessa grandezza. I dati sono memorizzati in modo identico su entrambi i dischi, da cui il soprannome «mirror». Quando un disco si guasta, i dati sono ancora disponibili sull'altro. Per dati veramente critici, il RAID-1 può ovviamente essere impostato su più di due dischi, il che ha delle conseguenze sul rapporto fra costo dell'hardware e spazio disponibile.
Questo livello di RAID, sebbene costoso (dal momento che al massimo è disponibile metà dello spazio fisico dei dischi), è ampiamente usato in pratica. È semplice da capire e permette di fare dei backup in modo molto semplice: dal momento che entrambi i dischi hanno gli stessi contenuti, uno di essi può essere temporaneamente estratto senza conseguenze sul sistema in funzione. Inoltre, spesso le prestazioni in lettura aumentano in quanto il kernel può leggere metà dati da ciascun disco in parallelo, mentre le prestazioni in scrittura non ne risentono troppo. Nel caso di un array RAID-1 di N dischi, i dati restano disponibili anche in caso si guastino N-1 dischi.
- RAID-4
Questo livello di RAID, non molto usato, usa N dischi per memorizzare dati utili e un disco in più per memorizzare le informazioni di ridondanza. Se quel disco si guasta, il sistema può ricostruire i suoi contenuti a partire dagli altri N. Se uno degli N dischi con i dati si guasta, i rimanenti N-1 insieme al disco di «parità» contengono abbastanza informazioni per ricostruire i dati richiesti.
Il RAID-4 non è eccessivamente costoso, dal momento che richiede un aumento dei costi di appena uno-su-N e non ha un impatto notevole sulle prestazioni in lettura, ma le scritture ne risultano rallentate. Inoltre, dal momento che la scrittura su uno qualunque degli N dischi richiede anche una scrittura sul disco di parità, quest'ultimo riceve molte più scritture del primo e di conseguenza la sua vita può ridursi notevolmente. I dati su un array RAID-4 sono sicuri solo fino alla rottura di un solo disco (degli N+1).
- RAID-5
Il RAID-5 risolve il problema di asimmetria del RAID-4: i blocchi di parità sono distribuiti su tutti gli N+1 dischi, senza che un unico disco abbia un ruolo particolare.
Le prestazioni in lettura e scrittura sono identiche al RAID-4. Anche qui il sistema rimane in funzione fino al guasto di un unico disco (degli N+1).
- RAID-6
Il RAID-6 si può considerare un'estensione del RAID-5, in cui ciascuna serie di N blocchi richiede due blocchi di ridondanza e ciascuna di queste serie di N+2 blocchi viene distribuita su N+2 dischi.
Questo livello di RAID è leggermente più costoso dei due precedenti, ma fornisce un po' di sicurezza in più, dal momento che possono guastarsi fino a due dischi (degli N+2) senza compromettere la disponibilità dei dati. Il difetto è che le operazioni di scrittura ora richiedono la scrittura di un blocco di dati e due blocchi di ridondanza, il che le rende ancora più lente.
- RAID-1+0
This isn't strictly speaking, a RAID level, but a stacking of two RAID groupings. Starting from 2×N disks, one first sets them up by pairs into N RAID-1 volumes; these N volumes are then aggregated into one, either by “linear RAID” or (increasingly) by LVM. This last case goes farther than pure RAID, but there is no problem with that.
Il RAID-1+0 può sopravvivere al guasto di più dischi: fino a N nell'array 2×n descritto sopra, a condizione che almeno un disco continui a funzionare in ciascuna coppia RAID-1.
Ovviamente, il livello di RAID verrà scelto a seconda dei vincoli e dei requisiti di ciascuna applicazione. Notare che un solo computer può avere diversi array RAID distinti con diverse configurazioni.
12.1.1.2. Impostazione di un RAID
L'impostazione di volumi RAID richiede il pacchetto mdadm; esso fornisce il comando mdadm
, che permette di creare e manipolare array RAID, oltre che script e strumenti per integrarlo al resto del sistema, compreso il sistema di monitoraggio.
Questo esempio mostrerà un server con un certo numero di dischi, alcuni dei quali sono già usati e i rimanenti sono disponibili per impostare il RAID. All'inizio si hanno i seguenti dischi e partizioni:
il disco sdb
, 4 GB, è interamente disponibile;
il disco sdc
, 4 GB, è anch'esso interamente disponibile;
sul disco sdd
, solo la partizione sdd2
(circa 4 GB) è disponibile;
infine, un disco sde
, di nuovo di 4 GB, interamente disponibile.
Questi elementi fisici verranno usati per costruire due volumi, un RAID-0 e un mirror (RAID-1). Si inizia col volume RAID-0:
#
mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sdb /dev/sdc
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
#
mdadm --query /dev/md0
/dev/md0: 7.99GiB raid0 2 devices, 0 spares. Use mdadm --detail for more detail.
#
mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Mon Feb 28 01:54:24 2022
Raid Level : raid0
Array Size : 8378368 (7.99 GiB 8.58 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Update Time : Mon Feb 28 01:54:24 2022
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0
Layout : -unknown-
Chunk Size : 512K
Consistency Policy : none
Name : debian:0 (local to host debian)
UUID : a75ac628:b384c441:157137ac:c04cd98c
Events : 0
Number Major Minor RaidDevice State
0 8 0 0 active sync /dev/sdb
1 8 16 1 active sync /dev/sdc
#
mkfs.ext4 /dev/md0
mke2fs 1.46.2 (28-Feb-2021)
Discarding device blocks: done
Creating filesystem with 2094592 4k blocks and 524288 inodes
Filesystem UUID: ef077204-c477-4430-bf01-52288237bea0
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
#
mkdir /srv/raid-0
#
mount /dev/md0 /srv/raid-0
#
df -h /srv/raid-0
Filesystem Size Used Avail Use% Mounted on
/dev/md0 7.8G 24K 7.4G 1% /srv/raid-0
The mdadm --create
command requires several parameters: the name of the volume to create (/dev/md*
, with MD standing for Multiple Device), the RAID level, the number of disks (which is compulsory despite being mostly meaningful only with RAID-1 and above), and the physical drives to use. Once the device is created, we can use it like we'd use a normal partition, create a filesystem on it, mount that filesystem, and so on. Note that our creation of a RAID-0 volume on md0
is nothing but coincidence, and the numbering of the array doesn't need to be correlated to the chosen amount of redundancy. It is also possible to create named RAID arrays, by giving mdadm
parameters such as /dev/md/linear
instead of /dev/md0
.
La creazione di un RAID-1 segue un percorso simile, la differenza si nota solo dopo la creazione:
#
mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdd2 /dev/sde
mdadm: Note: this array has metadata at the start and
may not be suitable as a boot device. If you plan to
store '/boot' on this device please ensure that
your boot-loader understands md/v1.x metadata, or use
--metadata=0.90
mdadm: largest drive (/dev/sdc2) exceeds size (4189184K) by more than 1%
Continue creating array?
y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md1 started.
#
mdadm --query /dev/md1
/dev/md1: 4.00GiB raid1 2 devices, 0 spares. Use mdadm --detail for more detail.
#
mdadm --detail /dev/md1
/dev/md1:
Version : 1.2
Creation Time : Mon Feb 28 02:07:48 2022
Raid Level : raid1
Array Size : 4189184 (4.00 GiB 4.29 GB)
Used Dev Size : 4189184 (4.00 GiB 4.29 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Update Time : Mon Feb 28 02:08:09 2022
State : clean, resync
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0
Consistency Policy : resync
Rebuild Status : 13% complete
Name : debian:1 (local to host debian)
UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8
Events : 17
Number Major Minor RaidDevice State
0 8 34 0 active sync /dev/sdd2
1 8 48 1 active sync /dev/sde
#
mdadm --detail /dev/md1
/dev/md1:
[...]
State : clean
[...]
Bisogna fare alcune osservazioni. Prima di tutto, mdadm
si accorge che gli elementi fisici hanno dimensioni diverse; poiché ciò implica che verrà perso dello spazio sull'elemento più grande, è richiesta una conferma.
Cosa ancora più importante, notare lo stato del mirror. Lo stato normale di un mirror RAID è che entrambi i dischi abbiano esattamente gli stessi contenuti. Tuttavia, nulla garantisce che ciò sia vero quando il volume viene creato. Il sottosistema RAID perciò fornirà esso stesso questa garanzia, e appena dopo la creazione del device RAID ci sarà una fase di sincronizzazione. Dopo un certo tempo (l'esatta durata dipenderà dall'effettiva dimensione dei dischi…), l'array RAID passa allo stato "attivo" o "pulito". Notare che durante questa fase di ricostruzione, il mirror è in modalità degradata, e la ridondanza non è assicurata. Il guasto di un disco durante questa fase potrebbe comportare la perdita di tutti i dati. Ad ogni modo, è raro che grandi quantità di dati critici vengano memorizzati su un array RAID appena creato prima della sincronizzazione iniziale. Notare che anche in modalità degradata, /dev/md1
è usabile, e vi si può creare sopra un file system, oltre a copiarvi sopra dei dati.
Ora si mostrerà cosa succede quando uno degli elementi dell'array RAID 1 si guasta. mdadm
, in particolare la sua opzione --fail
, permette di simulare uno guasto:
#
mdadm /dev/md1 --fail /dev/sde
mdadm: set /dev/sde faulty in /dev/md1
#
mdadm --detail /dev/md1
/dev/md1:
Version : 1.2
Creation Time : Mon Feb 28 02:07:48 2022
Raid Level : raid1
Array Size : 4189184 (4.00 GiB 4.29 GB)
Used Dev Size : 4189184 (4.00 GiB 4.29 GB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Update Time : Mon Feb 28 02:15:34 2022
State : clean, degraded
Active Devices : 1
Working Devices : 1
Failed Devices : 1
Spare Devices : 0
Consistency Policy : resync
Name : debian:1 (local to host debian)
UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8
Events : 19
Number Major Minor RaidDevice State
0 8 34 0 active sync /dev/sdd2
- 0 0 1 removed
1 8 48 - faulty /dev/sde
I contenuti del volume sono ancora accessibili (e, se montato, le applicazioni non si accorgono di nulla), ma la sicurezza dei dati non è più assicurata: se il disco sdd
dovesse a sua volta guastarsi, i dati andrebbero persi. Poiché è meglio evitare questo rischio, si va a sostituire il disco guasto con uno nuovo, sdf
:
#
mdadm /dev/md1 --add /dev/sdf
mdadm: added /dev/sdf
#
mdadm --detail /dev/md1
/dev/md1:
Version : 1.2
Creation Time : Mon Feb 28 02:07:48 2022
Raid Level : raid1
Array Size : 4189184 (4.00 GiB 4.29 GB)
Used Dev Size : 4189184 (4.00 GiB 4.29 GB)
Raid Devices : 2
Total Devices : 3
Persistence : Superblock is persistent
Update Time : Mon Feb 28 02:25:34 2022
State : clean, degraded, recovering
Active Devices : 1
Working Devices : 2
Failed Devices : 1
Spare Devices : 1
Consistency Policy : resync
Rebuild Status : 47% complete
Name : debian:1 (local to host debian)
UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8
Events : 39
Number Major Minor RaidDevice State
0 8 34 0 active sync /dev/sdd2
2 8 64 1 spare rebuilding /dev/sdf
1 8 48 - faulty /dev/sde
#
[...]
[...]
#
mdadm --detail /dev/md1
/dev/md1:
Version : 1.2
Creation Time : Mon Feb 28 02:07:48 2022
Raid Level : raid1
Array Size : 4189184 (4.00 GiB 4.29 GB)
Used Dev Size : 4189184 (4.00 GiB 4.29 GB)
Raid Devices : 2
Total Devices : 3
Persistence : Superblock is persistent
Update Time : Mon Feb 28 02:25:34 2022
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 1
Spare Devices : 0
Consistency Policy : resync
Name : debian:1 (local to host debian)
UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8
Events : 41
Number Major Minor RaidDevice State
0 8 34 0 active sync /dev/sdd2
2 8 64 1 active sync /dev/sdf
1 8 48 - faulty /dev/sde
Anche qui, il kernel attiva automaticamente una fase di ricostruzione durante la quale il volume, sebbene ancora accessibile, è in modalità degradata. Una volta finita la ricostruzione, l'array RAID torna a uno stato normale. A questo punto si può dire al sistema che il disco sde
sta per essere rimosso dall'array, così da arrivare a un classico mirror RAID su due dischi:
#
mdadm /dev/md1 --remove /dev/sde
mdadm: hot removed /dev/sde from /dev/md1
#
mdadm --detail /dev/md1
/dev/md1:
[...]
Number Major Minor RaidDevice State
0 8 34 0 active sync /dev/sdd2
2 8 64 1 active sync /dev/sdf
Da questo punto il drive può essere rimosso fisicamente al prossimo spegnimento del server, o anche rimosso a caldo quando la configurazione hardware permette l'hot-swap. Tali configurazioni includono alcuni controller SCSI, la maggior parte dei dischi SATA e i dischi esterni che operano su USB o Firewire.
12.1.1.3. Fare il backup della configurazione
Most of the meta-data concerning RAID volumes are saved directly on the disks that make up these arrays, so that the kernel can detect the arrays and their components and assemble them automatically when the system starts up. However, backing up this configuration is encouraged, because this detection isn't fail-proof, and it is only expected that it will fail precisely in sensitive circumstances. In our example, if the sde
disk failure had been real (instead of simulated) and the system had been restarted without removing this sde
disk, this disk could start working again due to having been probed during the reboot. The kernel would then have three physical elements, each claiming to contain half of the same RAID volume. In reality this leads to the RAID starting from the individual disks alternately - distributing the data also alternately, depending on which disk started the RAID in degraded mode Another source of confusion can come when RAID volumes from two servers are consolidated onto one server only. If these arrays were running normally before the disks were moved, the kernel would be able to detect and reassemble the pairs properly; but if the moved disks had been aggregated into an md1
on the old server, and the new server already has an md1
, one of the mirrors would be renamed.
È quindi importante fare il backup della configurazione, se non altro per avere un riferimento. Il modo standard di farlo è modificare il file /etc/mdadm/mdadm.conf
, un esempio del quale è mostrato qui:
Esempio 12.1. File di configurazione di mdadm
# mdadm.conf
#
# !NB! Run update-initramfs -u after updating this file.
# !NB! This will ensure that initramfs has an uptodate copy.
#
# Please refer to mdadm.conf(5) for information about this file.
#
# by default (built-in), scan all partitions (/proc/partitions) and all
# containers for MD superblocks. alternatively, specify devices to scan, using
# wildcards if desired.
DEVICE /dev/sd*
# automatically tag new arrays as belonging to the local system
HOMEHOST <system>
# instruct the monitoring daemon where to send mail alerts
MAILADDR root
# definitions of existing MD arrays
ARRAY /dev/md/0 metadata=1.2 UUID=a75ac628:b384c441:157137ac:c04cd98c name=debian:0
ARRAY /dev/md/1 metadata=1.2 UUID=2dfb7fd5:e09e0527:0b5a905a:8334adb8 name=debian:1
# This configuration was auto-generated on Mon, 28 Feb 2022 01:53:48 +0100 by mkconf
Uno dei dettagli più utili è l'opzione DEVICE
, che elenca i dispositi in cui il sistema cercherà automaticamente le componenti dei volumi RAID all'avvio. Nell'esempio in questione, abbiamo sostituito il valore predefinito, partitions containers
, con una lista esplicita dei file di dispositi, poiché si è scelto di usare dei dischi interi e non solo delle partizioni, per alcuni volumi.
Le ultime due righe nell'esempio sono quelle che permettono al kernel di scegliere in sicurezza quale numero di volume assegnare a ciascun array. I metadati memorizzati sui dischi stessi sono sufficienti a riassemblare i volumi ma non a determinare i numeri di volume (e il corrispondente nome di device /dev/md*
).
Per fortuna, queste righe si possono generare automaticamente:
#
mdadm --misc --detail --brief /dev/md?
ARRAY /dev/md/0 metadata=1.2 UUID=a75ac628:b384c441:157137ac:c04cd98c name=debian:0
ARRAY /dev/md/1 metadata=1.2 UUID=2dfb7fd5:e09e0527:0b5a905a:8334adb8 name=debian:1
I contenuti di queste ultime due righe non dipendono dall'elenco dei dischi inclusi nel volume. Pertanto non è necessario rigenerare queste righe quando si sostituisce un disco guasto con uno nuovo. D'altro canto, bisogna avere cura di aggiornare il file quando si crea o si elimina un array RAID.
LVM, il Logical Volume Manager (Gestore Volume Logico) , è un altro approccio per astrarre volumi logici dai loro supporti fisici, che si concentra più sull'aumento della flessibilità che sull'aumento dell'affidabilità. LVM permette la modifica di un volume logico in modo trasparente dal punto di vista delle applicazioni; per esempio, è possibile aggiungere nuovi dischi, migrare i dati ad esso, e rimuovere i vecchi dischi, senza smontare il volume.
12.1.2.1. Concetti relativi a LVM
Questa flessibilità si raggiunge tramite un livello di astrazione che riguarda tre concetti.
Primo, il PV (Physical Volume, volume fisico) è l'entità più vicina all'hardware: i volumi fisici possono essere partizioni di un disco, o un disco completo, o anche qualunque altro dispositivo a blocchi (incluso, ad esempio, un array RAID). Notare che quando un elemento fisico viene configurato come PV per LVM, vi si deve accedere solo via LVM, altrimenti il sistema si confonderà.
A number of PVs can be clustered in a VG (Volume Group), which can be compared to disks both virtual and extensible. VGs are abstract, and don't appear in a device file in the /dev
hierarchy, so there is no risk of using them directly.
Il terzo tipo di oggetto è il LV (Logical Volume, volume logico), che è una parte di un VG; proseguendo con l'analogia fra VG e dischi, il LV è simile a una partizione. Il LV appare come un dispositivo a blocchi con una voce in /dev
, e può essere usato come ogni altra partizione fisica (più di frequente, per ospitare un filesystem o spazio di swap).
La cosa importante è che la divisione di un VG in LV è completamente indipendente dai suoi componenti fisici (i PV). Un VG con un solo componente fisico (per esempio un disco) può essere diviso in una dozzina di volumi logici; allo stesso modo, un VG può usare diversi dischi fisici e apparire come un unico grande volume logico. L'unico vincolo, ovviamente, è che la dimensione totale allocata ai LV non può superare la capacità totale dei PV nel gruppo di volume.
Spesso comunque ha un senso avere una certa omogeneità fra le componenti fisiche di un VG, e suddividere i VG in volumi logici che avranno modelli d'uso simili. Per esempio, se l'hardware disponibile include dischi rapidi e dischi più lenti, quelli rapidi possono essere raggruppati in un VG e quelli più lenti in un altro; blocchi del primo possono quindi essere assegnati ad applicazioni che richiedono un accesso rapido ai dati, mentre il secondo sarà tenuto per compiti meno impegnativi.
In ogni caso, è bene tenere a mente che un LV non è particolarmente legato a un singolo PV. È possibile indicare dove sono fisicamente memorizzati i dati di un LV, ma questa possibilità non è richiesta per un uso quotidiano. Al contrario: quando l'insieme dei componenti fisici di un VG evolve, il luogo fisico di stoccaggio che corrisponde a un particolare LV può essere migrato da un disco a un altro (ovviamente rimanendo all'interno dei PV assegnati ai VG).
12.1.2.2. Impostazione di un LVM
Si seguirà ora, passo per passo, il processo di impostazione di un LVM per un tipico caso d'uso: semplificare una situazione complessa di memorizzazione dati. Una tale situazione di solito si ha dopo una lunga e intricata storia fatta di misure temporanee accumulatesi nel tempo. A scopo illustrativo, si considererà un server in cui le necessità di memorizzazione sono cambiate nel tempo, arrivando ad avere alla fine un labirinto di partizioni disponibili sparse fra diversi dischi usati parzialmente. In termini più concreti, sono disponibili le seguenti partizioni:
sul disco sdb
, una partizione sdb2
, 4 GB;
sul disco sdc
, una partizione sdc3
, 3 GB;
il disco sdd
, 4 GB, è completamente disponibile;
sul disco sdf
, una partizione sdf1
, 4 GB e una partizione sdf2
, 5 GB.
Inoltre, si suppone che i dischi sdb
e sdf
siano più veloci degli altri due.
Lo scopo è di impostare tre volumi logici per tre diverse applicazioni: un file server che richiede 5 GB di spazio disco, un database (1 GB) e un po' di spazio per i backup (12 GB). I primi due hanno bisogno di buone prestazioni, ma i backup sono meno critici in termini di velocità di accesso. Tutti questi vincoli impediscono di usare le partizioni così come sono; l'uso di LVM permette di astrarre dalla dimensione fisica dei dispositivi, cosicché l'unico limite è lo spazio totale disponibile.
Gli strumenti richiesti sono nel pacchetto lvm2 e nelle sue dipendenze. Una volta installati, impostare un LVM richiede tre passi, che corrispondono ai tre livelli di concetti.
Prima di tutto si preparano i volumi fisici usando pvcreate
:
#
pvcreate /dev/sdb2
Physical volume "/dev/sdb2" successfully created.
#
pvdisplay
"/dev/sdb2" is a new physical volume of "4.00 GiB"
--- NEW Physical volume ---
PV Name /dev/sdb2
VG Name
PV Size 4.00 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID yK0K6K-clbc-wt6e-qk9o-aUh9-oQqC-k1T71B
#
for i in sdc3 sdd sdf1 sdf2 ; do pvcreate /dev/$i ; done
Physical volume "/dev/sdc3" successfully created.
Physical volume "/dev/sdd" successfully created.
Physical volume "/dev/sdf1" successfully created.
Physical volume "/dev/sdf2" successfully created.
#
pvdisplay -C
PV VG Fmt Attr PSize PFree
/dev/sdb2 lvm2 --- 4.00g 4.00g
/dev/sdc3 lvm2 --- 3.00g 3.00g
/dev/sdd lvm2 --- 4.00g 4.00g
/dev/sdf1 lvm2 --- 4.00g 4.00g
/dev/sdf2 lvm2 --- 5.00g 5.00g
Finora tutto bene: notare che un PV può essere impostato su tutto un disco così come su singole partizioni. Come mostrato sopra, il comando pvdisplay
elenca le PV esistenti, con due possibili formati di output.
Ora si assemblano questi elementi fisici in VG usando vgcreate
. Solo le PV dei dischi più veloci saranno riunite in un VG vg_critical
; l'altro VG, vg_normal
, includerà anche gli elementi più lenti.
#
vgcreate vg_critical /dev/sdb2 /dev/sdf1
Volume group "vg_critical" successfully created
#
vgdisplay
--- Volume group ---
VG Name vg_critical
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 2
Act PV 2
VG Size 7.99 GiB
PE Size 4.00 MiB
Total PE 2046
Alloc PE / Size 0 / 0
Free PE / Size 2046 / 7.99 GiB
VG UUID JgFWU3-emKg-9QA1-stPj-FkGX-mGFb-4kzy1G
#
vgcreate vg_normal /dev/sdc3 /dev/sdd /dev/sdf2
Volume group "vg_normal" successfully created
#
vgdisplay -C
VG #PV #LV #SN Attr VSize VFree
vg_critical 2 0 0 wz--n- 7.99g 7.99g
vg_normal 3 0 0 wz--n- <11.99g <11.99g
Anche qui, i comandi sono piuttosto semplici (e vgdisplay
propone due formati di output). Notare che è possibile usare due partizioni dello stesso disco fisico in due diversi VG. Notare inoltre che si è usato un prefisso vg_
per nominare i VG, ma non è altro che una convenzione.
We now have two “virtual disks”, sized about 8 GB and 12 GB respectively. Let's now carve them up into “virtual partitions” (LVs). This involves the lvcreate
command, and a slightly more complex syntax:
#
lvdisplay
#
lvcreate -n lv_files -L 5G vg_critical
Logical volume "lv_files" created.
#
lvdisplay
--- Logical volume ---
LV Path /dev/vg_critical/lv_files
LV Name lv_files
VG Name vg_critical
LV UUID Nr62xe-Zu7d-0u3z-Yyyp-7Cj1-Ej2t-gw04Xd
LV Write Access read/write
LV Creation host, time debian, 2022-03-01 00:17:46 +0100
LV Status available
# open 0
LV Size 5.00 GiB
Current LE 1280
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:0
#
lvcreate -n lv_base -L 1G vg_critical
Logical volume "lv_base" created.
#
lvcreate -n lv_backups -L 11.98G vg_normal
Rounding up size to full physical extent 11.98 GiB
Rounding up size to full physical extent 11.98 GiB
Logical volume "lv_backups" created.
#
lvdisplay -C
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv_base vg_critical -wi-a----- 1.00g
lv_files vg_critical -wi-a----- 5.00g
lv_backups vg_normal -wi-a----- 11.98g
La creazione di volumi logici richiede due parametri che devono essere passati come opzioni al comando lvcreate
. Il nome dei LV da creare viene specificato con l'opzione -n
e la sua dimensione viene generalmente data usando l'opzione -L
. Ovviamente bisogna anche dire al comando su quale VG operare, da cui l'ultimo parametro sulla riga di comando.
Una volta creati, i volumi logici si trovano come file di device a blocchi in /dev/mapper/
:
#
ls -l /dev/mapper
total 0
crw------- 1 root root 10, 236 Mar 1 00:17 control
lrwxrwxrwx 1 root root 7 Mar 1 00:19 vg_critical-lv_base -> ../dm-1
lrwxrwxrwx 1 root root 7 Mar 1 00:17 vg_critical-lv_files -> ../dm-0
lrwxrwxrwx 1 root root 7 Mar 1 00:19 vg_normal-lv_backups -> ../dm-2
#
ls -l /dev/dm-*
brw-rw---- 1 root disk 253, 0 Mar 1 00:17 /dev/dm-0
brw-rw---- 1 root disk 253, 1 Mar 1 00:19 /dev/dm-1
brw-rw---- 1 root disk 253, 2 Mar 1 00:19 /dev/dm-2
Per facilitare le cose, vengono inoltre creati dei comodi collegamenti simbolici in directory corrispondenti ai VG:
#
ls -l /dev/vg_critical
total 0
lrwxrwxrwx 1 root root 7 Mar 1 00:19 lv_base -> ../dm-1
lrwxrwxrwx 1 root root 7 Mar 1 00:17 lv_files -> ../dm-0
#
ls -l /dev/vg_normal
total 0
lrwxrwxrwx 1 root root 7 Mar 1 00:19 lv_backups -> ../dm-2
I LV possono quindi essere usati esattamente come normali partizioni:
#
mkfs.ext4 /dev/vg_normal/lv_backups
mke2fs 1.46.2 (28-Feb-2021)
Discarding device blocks: done
Creating filesystem with 3140608 4k blocks and 786432 inodes
Filesystem UUID: 7eaf0340-b740-421e-96b2-942cdbf29cb3
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
#
mkdir /srv/backups
#
mount /dev/vg_normal/lv_backups /srv/backups
#
df -h /srv/backups
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_normal-lv_backups 12G 24K 12G 1% /srv/backups
#
[...]
[...]
#
cat /etc/fstab
[...]
/dev/vg_critical/lv_base /srv/base ext4 defaults 0 2
/dev/vg_critical/lv_files /srv/files ext4 defaults 0 2
/dev/vg_normal/lv_backups /srv/backups ext4 defaults 0 2
Dal punto di vista delle applicazioni, la miriade di piccole partizioni è stata ora astratta in un grande volume di 12 GB con un nome più familiare.
Anche se la capacità di aggregare partizioni o dischi fisici è comoda, questo non è il vantaggio principale di LVM. La sua flessibilità si nota soprattutto col passare del tempo, quando le necessità evolvono. Nell'esempio, si supponga di dover memorizzare dei nuovi grandi file e che il LV dedicato al file server sia troppo piccolo per contenerli. Poiché non si è usato tutto lo spazio disponibile in vg_critical
, si può espandere lv_files
. A questo scopo, si usa il comando lvresize
, quindi resize2fs
per adattare il file system di conseguenza:
#
df -h /srv/files/
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_critical-lv_files 4.9G 4.2G 485M 90% /srv/files
#
lvdisplay -C vg_critical/lv_files
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv_files vg_critical -wi-ao---- 5.00g
#
vgdisplay -C vg_critical
VG #PV #LV #SN Attr VSize VFree
vg_critical 2 2 0 wz--n- 7.99g 1.99g
#
lvresize -L 6G vg_critical/lv_files
Size of logical volume vg_critical/lv_files changed from 5.00 GiB (1280 extents) to 6.00 GiB (1536 extents).
Logical volume vg_critical/lv_files successfully resized.
#
lvdisplay -C vg_critical/lv_files
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
lv_files vg_critical -wi-ao---- 6.00g
#
resize2fs /dev/vg_critical/lv_files
resize2fs 1.46.2 (28-Feb-2021)
Filesystem at /dev/vg_critical/lv_files is mounted on /srv/files; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/vg_critical/lv_files is now 1572864 (4k) blocks long.
#
df -h /srv/files/
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_critical-lv_files 5.9G 4.2G 1.5G 75% /srv/files
Si potrebbe procedere in modo simile per estendere il volume che ospita il database, ma è stato raggiunto il limite di spazio disponibile del VG:
#
df -h /srv/base/
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_critical-lv_base 974M 883M 25M 98% /srv/base
#
vgdisplay -C vg_critical
VG #PV #LV #SN Attr VSize VFree
vg_critical 2 2 0 wz--n- 7.99g 1016.00m
No matter, since LVM allows adding physical volumes to existing volume groups. For instance, maybe we've noticed that the sdb3
partition, which was so far used outside of LVM, only contained archives that could be moved to lv_backups
. We can now recycle it and integrate it to the volume group, and thereby reclaim some available space. This is the purpose of the vgextend
command. Of course, the partition must be prepared as a physical volume beforehand. Once the VG has been extended, we can use similar commands as previously to grow the logical volume then the filesystem:
#
pvcreate /dev/sdb3
Physical volume "/dev/sdb3" successfully created.
#
vgextend vg_critical /dev/sdb3
Volume group "vg_critical" successfully extended
#
vgdisplay -C vg_critical
VG #PV #LV #SN Attr VSize VFree
vg_critical 3 2 0 wz--n- <12.99g <5.99g
#
lvresize -L 2G vg_critical/lv_base
[...]
#
resize2fs /dev/vg_critical/lv_base
[...]
#
df -h /srv/base/
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_critical-lv_base 2.0G 886M 991M 48% /srv/base
RAID e LVM portano entrambi indiscutibili vantaggi quando si abbandona il caso semplice di un computer desktop con un solo disco fisso in cui il modello d'uso non cambia nel tempo. Tuttavia, RAID e LVM vanno in due direzioni differenti, con scopi distinti ed è giusto chiedersi quale dei due adottare. La risposta più appropriata ovviamente dipenderà dai requisiti attuali e da quelli prevedibili in futuro.
Ci sono alcuni casi semplici in cui il problema non si pone. Se il requisito è di salvaguardare i dati da guasti hardware, allora ovviamente si configurerà RAID su un array ridondante di dischi, in quanto LVM non risolve questo problema. Se, d'altro canto, c'è bisogno di uno schema flessibile per memorizzare dati dove i volumi siano indipendenti dalla disposizione fisica dei dischi, il RAID non è molto d'aiuto e LVM è la scelta naturale.
Il terzo importante caso d'uso è quando si vuole semplicemente aggregare due dischi in un unico volume, per motivi di prestazioni o per avere un unico file system più grande di qualunque disco disponibile. Questo caso può essere affrontato sia utilizzando un RAID-0 (o addirittura un linear-RAID) sia tramite un volume LVM. In questa situazione, senza considerare ulteriori vincoli (per esempio, mantenere la coerenza con altre macchine se queste usano solo RAID), la configurazione preferita di solito sarà LVM. L'impostazione iniziale è appena più complessa, ma questo leggero aumento di complessità è più che compensato dall'aumentata flessibilità di LVM nel caso i requisiti cambiassero o si dovessero aggiungere nuovi dischi.
Poi, ovviamente, c'è il caso d'uso veramente interessante, in cui il sistema di memorizzazione deve essere reso sia resistente ai guasti hardware sia flessibile in termini di allocazione di volumi. Né RAID né LVM possono di per sé soddisfare entrambi i requisiti; ciò non è un problema, perché qui si possono usare entrambi contemporaneamente, o piuttosto, uno sopra l'altro. Lo schema che è diventato lo standard da quando RAID e LVM hanno raggiunto la maturità è di assicurare prima di tutto la ridondanza dei dati raggruppando i dischi in un piccolo numero di array RAID e usare questi array RAID come volumi fisici LVM; a questo punto si creano i file system tramite partizioni logiche all'interno di questi LV. Il punto di forza di questa impostazione è che quando un disco si guasta si deve ricostruire solo un piccolo numero di array RAID, limitando così il tempo speso dall'amministratore per il ripristino.
Let's take a concrete example: the public relations department at Falcot Corp needs a workstation for video editing, but the department's budget doesn't allow investing in high-end hardware from the bottom up. A decision is made to favor the hardware that is specific to the graphic nature of the work (monitor and video card), and to stay with generic hardware for storage. However, as is widely known, digital video does have some particular requirements for its storage: the amount of data to store is large, and the throughput rate for reading and writing this data is important for the overall system performance (more than typical access time, for instance). These constraints need to be fulfilled with generic hardware, in this case two 300 GB SATA hard disk drives; the system data must also be made resistant to hardware failure, as well as some of the user data. Edited video clips must indeed be safe, but video rushes pending editing are less critical, since they're still on the videotapes.
RAID-1 e LVM vengono combinati per soddisfare questi vincoli. I dischi sono collegati a due controller SATA diversi per ottimizzare l'accesso in parallelo e ridurre i rischi di guasto simultaneo e quindi appaiono come sda
e sdc
. Vengono partizionati in modo identico secondo il seguente schema:
#
sfdisk -l /dev/sda
Disk /dev/sda: 894.25 GiB, 960197124096 bytes, 1875385008 sectors
Disk model: SAMSUNG MZ7LM960
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: BB14C130-9E9A-9A44-9462-6226349CA012
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 100667391 100663296 48G Linux RAID
/dev/sda3 100667392 134221823 33554432 16G Linux RAID
/dev/sda4 134221824 763367423 629145600 300G Linux RAID
/dev/sda5 763367424 1392513023 629145600 300G Linux RAID
/dev/sda6 1392513024 1875384974 482871951 230.3G Linux LVM
The first partitions of both disks are BIOS boot partitions.
The next two partitions sda2
and sdc2
(about 48 GB) are assembled into a RAID-1 volume, md0
. This mirror is directly used to store the root filesystem.
The sda3
and sdc3
partitions are assembled into a RAID-0 volume, md1
, and used as swap partition, providing a total 32 GB of swap space. Modern systems can provide plenty of RAM and our system won't need hibernation. So with this amount added, our system will unlikely run out of memory.
The sda4
and sdc4
partitions, as well as sda5
and sdc5
, are assembled into two new RAID-1 volumes of about 300 GB each, md2
and md3
. Both these mirrors are initialized as physical volumes for LVM, and assigned to the vg_raid
volume group. This VG thus contains about 600 GB of safe space.
The remaining partitions, sda6
and sdc6
, are directly used as physical volumes, and assigned to another VG called vg_bulk
, which therefore ends up with roughly 460 GB of space.
Una volta creati i VG, possono essere partizionati in modo molto flessibile. Bisogna ricordarsi che i LV creati in vg_raid
saranno preservati anche in caso di guasto di uno dei dischi, cosa che non succede per i LV creati in vg_bulk
; d'altro canto, quest'ultimo sarà allocato in parallelo su entrambi i dischi, il che consente velocità di lettura o scrittura maggiori per file grandi.
We will therefore create the lv_var
and lv_home
LVs on vg_raid
, to host the matching filesystems; another large LV, lv_movies
, will be used to host the definitive versions of movies after editing. The other VG will be split into a large lv_rushes
, for data straight out of the digital video cameras, and a lv_tmp
for temporary files. The location of the work area is a less straightforward choice to make: while good performance is needed for that volume, is it worth risking losing work if a disk fails during an editing session? Depending on the answer to that question, the relevant LV will be created on one VG or the other.
We now have both some redundancy for important data and much flexibility in how the available space is split across the applications.