Skip to content

Opdracht 11 - ZFS

Doel

In deze opdracht zet je de eerste stappen met het Zettabyte File System (ZFS). Het staat bekend als een van de meest robuuste bestandssystemen met de hoogste bescherming voor opgeslagen data. Dit wordt gedemonstreerd door twee harde schijven aan te maken en in een ZFS "mirror" te plaatsen. Hierdoor hebben deze schijven op elk moment identieke inhoud. Ze zijn dus "gespiegeld" maar gedragen zich nog steeds als één geheel. Vervolgens laten we een van de schijven fouten genereren en vervangen we deze. Het mooie aan ZFS is dat het deze fouten detecteert en ervoor zorgt dat andere gebruikers en programma's niet doorhebben dat er iets mis is. Na het vervangen van de schijf zal alles weer hersteld zijn.

Opdracht

❗️ Let op: bij deze opdracht bestaat de kans dat je de VM beschadigt, waardoor je helemaal opnieuw zou moeten beginnen. Bespaar jezelf veel werk en gebruik snapshots in VirtualBox!

Studenten die UTM op Apple Silicon Macs gebruiken, hebben helaas niet de mogelijkheid om snapshots te maken. Mogelijk kan je wel deze suggestie gebruiken: https://github.com/utmapp/UTM/discussions/5234.

Als je de foutmelding Medium '...' is attached to a virtual machine with UUID {...}. No differencing media based on it may be created until it is detached. krijgt, verwijder dan de opgegeven aangesloten harde schijf en probeer het opnieuw.

Installatie ZFS

Deze sectie is gebaseerd op de tutorial op https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/index.html#installation mits enkele aanpassingen voor Ubuntu 24.04.

Het is een goed idee om de commando's als root gebruiker uit te voeren. Voer het commando sudo su uit om root te worden.

Allereerst moeten we controleren of de universe suite van de officiële Ubuntu package repository is ingeschakeld. Hiervoor open je het bestand /etc/apt/sources.list.d/ubuntu.sources in een teksteditor (bv. gedit of nano) en controleer je of de volgende regels aanwezig zijn. Als je deze regels niet ziet, voeg je deze toe aan het bestand.

Text Only
1
2
3
4
5
Types: deb
URIs: http://archive.ubuntu.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Na Suites zie je de codenaam van de Ubuntu-versie. Op Ubuntu 24.04 is dit noble (van Noble Numbat). Als je een andere versie van Ubuntu gebruikt, zal daar een andere codenaam staan. Je kan de codenaam vinden door lsb_release -c uit te voeren.

Vervolgens installeren we ZFS:

Bash
apt update
apt install zfsutils-linux

Na de installatie herstart je de VM en controleer je of ZFS correct is geïnstalleerd. Je zou een gelijkaardige uitvoer moeten krijgen:

Bash
1
2
3
4
5
6
$ zfs version
zfs-2.1.5-1ubuntu6~22.04.1
zfs-kmod-2.1.5-1ubuntu6

$ zpool status
no pools available

Aanmaken van een ZFS datapool

⚠️ Gebruikers van UTM op een Apple Silicon mac moeten op een andere manier de harde schrijven aanmaken, zie de documenatie van UTM: https://docs.getutm.app/settings-qemu/drive/drive/#creation. Nadien kan je de stappen hieronder volgen vanaf lsblk.

In de volgende stap gaan we een ZFS-datapool aanmaken. Dit is een verzameling harde schijven die als één geheel worden gezien. In ons voorbeeld maken we twee harde schijven aan en plaatsen deze in een datapool. Dit is een soort "mirror" van de twee schijven. Als er iets misgaat met één van de schijven, zal de andere schijf de data overnemen. Dit is een van de voordelen van ZFS: het is zeer robuust en zorgt ervoor dat de data altijd beschikbaar is.

Sluit de VM af en maak in VirtualBox twee harde schijven aan met een grootte van 512 MB. Dit is het eenvoudigst in VirtualBox via het menu Bestand > Tools > Virtual Media Manager omdat je daar een schijf eenmaal kan maken en vervolgens kan kopiëren. Deze schijven mogen gerust dynamisch gealloceerd zijn.

VirtualBox - Virtual Media Manager

Koppel deze schijven aan de SATA-controller van jouw Ubuntu VM.

VirtualBox - Virtual Media Manager - Koppelen schijven

Start de VM en controleer of de schijven zijn gekoppeld aan het systeem met lsblk. Beantwoord de volgende vragen:

Vind je de nieuwe harde schijven terug in de output (sdb en sdc in het voorbeeld)? Hoe weet je dat dit de nieuwe schijven zijn?

We zien dat er twee nieuwe harde schijven zijn van 512 MB groot. Deze zijn nog niet geformatteerd en hebben geen partities. Dit zijn dus de nieuwe harde schijven.

Bash
$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0  500G  0 disk
├─sda1   8:1    0  236G  0 part /
├─sda2   8:2    0   10G  0 part [SWAP]
└─sda3   8:3    0  254G  0 part /home
sdb      8:16   0  512M  0 disk
sdc      8:32   0  512M  0 disk
sr0     11:0    1 1024M  0 rom
zram0  252:0    0  3.8G  0 disk [SWAP]

/dev/sdb en /dev/sdc zijn namen (sd<letter>) die willekeurig worden toegekend door de Linux-kernel. Als je een harde schijf aan een andere SATA-poort op het moederbord koppelt, zal de letter waarschijnlijk veranderen. Hierop kan je dus moeilijk vertrouwen als je schijven verwisselt of verplaatst.

Laten we de disk-id's opzoeken: deze zijn immers aan een specifieke harde schijf verbonden en zullen dus telkens hetzelfde zijn voor een bepaalde harde schijf, ongeacht hoe of waar deze is aangesloten.

Op Linux is alles een bestand, zo ook de harde schijven. Als je de bestanden in de map /dev/disk/by-id bekijkt, zie je een lijst van alle harde schijven die op het systeem zijn aangesloten.

Het is eenvoudig om de inhoud van deze map te bekijken met ls -l /dev/disk/by-id/. Je ziet in onderstaand voorbeeld dat /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 een link is naar /dev/sdb (door de ../../ gaan we twee mappen terug in de structuur):

Bash
1
2
3
4
5
6
7
8
9
$ ls -l /dev/disk/by-id/
total 0
lrwxrwxrwx. 1 root root  9 May  2 11:41 ata-VBOX_CD-ROM_VB2-1a2b3c4d -> ../../sr0
lrwxrwxrwx. 1 root root  9 May  2 11:41 ata-VBOX_HARDDISK_VB84639317-15163edd -> ../../sdc
lrwxrwxrwx. 1 root root  9 May  2 11:41 ata-VBOX_HARDDISK_VBc637223c-984634e8 -> ../../sdb
lrwxrwxrwx. 1 root root  9 May  2 11:41 ata-VBOX_HARDDISK_VBda1b77f7-48bded97 -> ../../sda
lrwxrwxrwx. 1 root root 10 May  2 11:41 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part1 -> ../../sda1
lrwxrwxrwx. 1 root root 10 May  2 11:41 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part2 -> ../../sda2
lrwxrwxrwx. 1 root root 10 May  2 11:41 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part3 -> ../../sda3

De disk-id's in het voorbeeld zijn als volgt:

Naam Disk-id
/dev/sdb /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8
/dev/sdc /dev/disk/by-id/ata-VBOX_HARDDISK_VB84639317-15163edd

📝 Stel voor jouw VM een vergelijkbare tabel op. Je hebt deze in de volgende stappen nodig, waarbij je de disk-id's telkens moet vervangen door de (unieke) disk-id's van jouw systeem.

Maak een mirror met de naam somezfsdatapool aan:

Bash
sudo zpool create somezfsdatapool mirror /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 /dev/disk/by-id/ata-VBOX_HARDDISK_VB84639317-15163edd

Controleer of de status van de pool ONLINE is:

Bash
$ zpool status
    pool: somezfsdatapool
    state: ONLINE
config:

    NAME                                       STATE     READ WRITE CKSUM
    somezfsdatapool                            ONLINE       0     0     0
    mirror-0                                   ONLINE       0     0     0
        ata-VBOX_HARDDISK_VBc637223c-984634e8  ONLINE       0     0     0
        ata-VBOX_HARDDISK_VB84639317-15163edd  ONLINE       0     0     0

errors: No known data errors

Met het commando zpool list kunnen we zien waar deze pool is gemount op het bestandssysteem:

Bash
1
2
3
$ zpool list
NAME              SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
somezfsdatapool   480M   563K   479M        -         -     4%     0%  1.00x    ONLINE  -

Om bestanden op de datapool te plaatsen, kan je deze gewoon in /somezfsdatapool zetten alsof het een normale map is. Probeer dit eens uit door een bestand met wat willekeurige tekst in deze map te maken. Deze map is eigendom van de root gebruiker, dus je zal hiervoor sudo moeten gebruiken.

Herstellen van fouten

Om het herstellen van fouten te demonstreren, hebben we eerst data nodig in onze ZFS pool. Je kan hiervoor bijvoorbeeld een bestand in /somezfsdatapool plaatsen.

Wij kiezen ervoor om de man pages naar de datapool te kopiëren:

Bash
sudo cp -r -v /usr/share/man /somezfsdatapool

Het kan zijn dat de data nog in de write cache zit en nog niet op de schijf is geschreven. Met sync zorgen we ervoor dat de data op de schijf wordt geschreven.

Bash
sudo sync

Wanneer we nu alle pools opvragen, zien we dat de vrije ruimte van de datapool is afgenomen:

Bash
1
2
3
$ zpool list
NAME              SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
somezfsdatapool   480M  41.7M   438M        -         -     0%     8%  1.00x    ONLINE  -

Het volgende commando beschadigt een deel van de bestanden op een enkele schijf van de datapool. In dit voorbeeld is dat de harde schijf /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8. Vervang dit door een van de disk-id's van jouw systeem.

Bash
1
2
3
4
$ sudo dd if=/dev/zero of=/dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 bs=1024k count=100 conv=notrunc
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.114396 s, 917 MB/s
Wat doet dit commando?

Het commando dd staat voor "data duplicator". Het is een commando dat data kan kopiëren van een bron naar een doel. In dit geval wordt er van /dev/zero naar /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 gekopieerd.

/dev/zero is een speciaal bestand dat enkel nullen bevat. Je kan hier oneindig veel nullen van kopiëren.

De optie bs=1024k zorgt ervoor dat er 1024 kilobytes (1 megabyte) per keer wordt gekopieerd.

De optie count=100 zorgt ervoor dat er 100 keer 1 megabyte wordt gekopieerd.

De optie conv=notrunc zorgt ervoor dat het bestand niet wordt afgekapt. Dit is nodig omdat we anders de bestanden die we willen beschadigen zouden overschrijven.

Hier schrijven we dus 100 megabytes aan nullen naar de schijf. Dit is genoeg om een deel van de bestanden op de schijf te beschadigen.

Laat ZFS nu de datapool controleren op fouten. Dit wordt ook wel "scrubben" genoemd. Als je daarna de status opvraagt, zal ZFS melden dat er fouten in de bestanden zijn geslopen:

Bash
$ sudo zpool scrub somezfsdatapool

$ zpool status
    pool: somezfsdatapool
    state: DEGRADED
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
    see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
    scan: scrub repaired 22.2M in 00:00:03 with 0 errors on Mon May  2 11:58:10 2022
config:

    NAME                                       STATE     READ WRITE CKSUM
    somezfsdatapool                            DEGRADED     0     0     0
    mirror-0                                   DEGRADED     0     0     0
        ata-VBOX_HARDDISK_VBc637223c-984634e8  DEGRADED     0     0 13.3K  too many errors
        ata-VBOX_HARDDISK_VB84639317-15163edd  ONLINE       0     0     0

errors: No known data errors

Ondanks dat een harde schijf corrupt of beschadigd is geraakt, heeft ZFS dankzij de mirror-opstelling genoeg informatie om de oorspronkelijke bestanden te herstellen en correct terug te geven wanneer je deze opvraagt (bijvoorbeeld met cat). Gebruikers of programma's merken dus niet dat er iets fout is. ZFS meldt daarom dat de datapool nog steeds online is en dat het alle bestanden correct kan teruggeven (No known data errors). Wel meldt ZFS ook dat een harde schijf foutieve data bevat en dat deze hersteld of vervangen moet worden.

Wat gebeurt er als de andere schijf nu ook zou falen?

Als de andere schijf ook zou falen, dan zou ZFS de datapool niet meer kunnen herstellen. De datapool zou dan in een OFFLINE status komen te staan. In dat geval zou je de datapool moeten verwijderen en opnieuw moeten aanmaken. De data die je op de datapool had staan, zou dan verloren zijn.

We zullen de defecte harde schijf moeten vervangen door een nieuwe blanco harde schijf. Sluit de VM af en ontkoppel de defecte harde schijf (dit is zfs.vdi in de screenshots). Je zal zelf moeten achterhalen welke harde schrijf defect is in jouw geval.

Hoe kan je snel zien welke harde schijf defect is?

Met het dd-commando hebben we nullen weggeschreven naar een van beide schijven. Wanneer je in de Virtual Media Manager de ware grootte van de schijven bekijkt, zal je zien dat een van beide schijven kleiner is dan de andere. Dit is de schijf die we beschadigd hebben.

Virtuele machine - Onkoppelen schijf

Ga nu terug naar de Virtual Media Manager en voer de volgende stappen uit:

  • Verwijder de defecte harde schijf.
  • Maak een nieuwe blanco harde schijf aan van 512 MB. Gebruik geen Copy, maar maak een nieuwe blanco harde schijf aan via Create.

Virtuele machine - Aanmaken nieuwe schijf

Koppel de nieuwe blanco harde schijf aan de VM.

Virtuele machine - Koppelen schijf

Start de VM en controleer de aangesloten schijven en disk-id's:

Bash
$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0  500G  0 disk
├─sda1   8:1    0  236G  0 part /
├─sda2   8:2    0   10G  0 part [SWAP]
└─sda3   8:3    0  254G  0 part /home
sdb      8:16   0  512M  0 disk
sdc      8:32   0  512M  0 disk
├─sdc1   8:33   0  502M  0 part
└─sdc9   8:41   0    8M  0 part
sr0     11:0    1 1024M  0 rom
zram0  252:0    0  3.8G  0 disk [SWAP]

$ ls -l /dev/disk/by-id/
total 0
lrwxrwxrwx. 1 root root  9 May  3 19:29 ata-VBOX_CD-ROM_VB2-1a2b3c4d -> ../../sr0
lrwxrwxrwx. 1 root root  9 May  3 19:29 ata-VBOX_HARDDISK_VB71c64cb1-d6cc2bcb -> ../../sdb
lrwxrwxrwx. 1 root root  9 May  3 19:29 ata-VBOX_HARDDISK_VB84639317-15163edd -> ../../sdc
lrwxrwxrwx. 1 root root 10 May  3 19:29 ata-VBOX_HARDDISK_VB84639317-15163edd-part1 -> ../../sdc1
lrwxrwxrwx. 1 root root 10 May  3 19:29 ata-VBOX_HARDDISK_VB84639317-15163edd-part9 -> ../../sdc9
lrwxrwxrwx. 1 root root  9 May  3 19:29 ata-VBOX_HARDDISK_VBda1b77f7-48bded97 -> ../../sda
lrwxrwxrwx. 1 root root 10 May  3 19:29 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part1 -> ../../sda1
lrwxrwxrwx. 1 root root 10 May  3 19:29 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part2 -> ../../sda2
lrwxrwxrwx. 1 root root 10 May  3 19:29 ata-VBOX_HARDDISK_VBda1b77f7-48bded97-part3 -> ../../sda3

Controleer de status van de datapool. Je zal zien dat ZFS aangeeft dat er fouten in de bestanden zijn opgetreden.

Bash
$ zpool status
  pool: somezfsdatapool
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
 invalid.  Sufficient replicas exist for the pool to continue
 functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-4J
  scan: scrub repaired 22.2M in 00:00:06 with 0 errors on Tue May  3 19:19:30 2022
config:

 NAME                                       STATE     READ WRITE CKSUM
 somezfsdatapool                            DEGRADED     0     0     0
   mirror-0                                 DEGRADED     0     0     0
     8509535142708180278                    UNAVAIL      0     0     0  was /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8-part1
     ata-VBOX_HARDDISK_VB84639317-15163edd  ONLINE       0     0     0

errors: No known data errors

Je ziet dat de disk-id van /dev/sdb is veranderd; we hebben immers de harde schijf vervangen door een nieuwe blanco harde schijf:

Naam Oude disk-id Nieuwe disk-id
/dev/sdb /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 /dev/disk/by-id/ata-VBOX_HARDDISK_VB71c64cb1-d6cc2bcb

📝 Stel voor jouw VM een vergelijkbare tabel op. Je hebt deze in de volgende stappen nodig, waarbij je de disk-id's telkens moet vervangen door de (unieke) disk-id's van jouw systeem.

Nu moeten we ervoor zorgen dat de nieuwe blanco harde schijf de rol van de oude defecte harde schijf overneemt. Dit proces wordt "resilveren" genoemd:

Bash
sudo zpool replace somezfsdatapool /dev/disk/by-id/ata-VBOX_HARDDISK_VBc637223c-984634e8 /dev/disk/by-id/ata-VBOX_HARDDISK_VB71c64cb1-d6cc2bcb

Wanneer we nu de status van de datapool bekijken, zien we dat deze weer online is:

Bash
$ zpool status
  pool: somezfsdatapool
 state: ONLINE
  scan: resilvered 47.6M in 00:00:04 with 0 errors on Tue May  3 19:39:00 2022
config:

 NAME                                       STATE     READ WRITE CKSUM
 somezfsdatapool                            ONLINE       0     0     0
   mirror-0                                 ONLINE       0     0     0
     ata-VBOX_HARDDISK_VB71c64cb1-d6cc2bcb  ONLINE       0     0     0
     ata-VBOX_HARDDISK_VB84639317-15163edd  ONLINE       0     0     0

errors: No known data errors

Alles is gerepareerd. Ondertussen hebben andere gebruikers en programma's niets gemerkt van de problemen met de datapool! Omdat we werken met VirtualBox, moesten we de VM even kort afsluiten om de defecte harde schijf te vervangen. Servers ondersteunen vaak hot swapping, waardoor harde schijven kunnen worden vervangen terwijl de server blijft draaien. In dat geval zullen andere gebruikers en programma's zeker niets merken!


Bronnen