ZFS dRAID Grundlagen und Einrichtung

Aus Thomas-Krenn-Wiki
Zur Navigation springen Zur Suche springen

dRAID steht für distributed Spare RAID und ist eine Implementation für ZFS. Ein dRAID vdev ist zusammengesetzt aus RAIDZ Array Gruppen und wird in Proxmox VE ab der Version 7.3 unterstützt. Die Besonderheit von dRAID sind die inbegriffenen verteilten Hot Spares.

Dieser Artikel gibt einen Überblick über die Funktionsweise von dRAID und zeigt die Einrichtung eines vdev auf Basis von dRAID unter Proxmox 7.3.

Funktionsweise

dRAID hat das Ziel, sowohl parity als auch spare auf alle Datenträger im Verbund zu verteilen. Die besonderen Merkmale eines solchen Verbunds sollen im Folgenden erläutert werden.

Hauptmerkmale

Einfache Darstellung eines slices. Die groups sind RAIDZ-1,2 oder 3 Verbünde mit statischer Stripe-Länge.

Ein dRAID-Verbund besteht aus

  1. RAIDZ Gruppen
  2. (distributed) spare

Diese werden in sogenannten slices angeordnet (s.u.). Die RAIDZ Gruppen werden dabei in der Definition des dRAID festgelegt - ein dRAID1 nutzt RAIDZ-1 Gruppen, ein dRAID3 verwendet RAIDZ-3 Gruppen.

Bei der Definition eines dRAID müssen also immer die Parameter data, parity und spare festgelegt werden. Optional kann auch die Gesamtzahl der eingebundenen Datenträger (im dRAID children genannt) angegeben werden.

Möglich sind - analog den RAIDZ Leveln - 1, 2 oder 3 parity. Die Anzahl der spares kann frei bestimmt werden, wobei der Standardwert 0 ist. Die Datenanteile sind frei wählbar bis zu einem Maximum. Dieses wird bestimmt durch die Gesamtzahl der children abzüglich der gewünschten parities und spares im Verbund.

Hier einige Beispiele möglicher Definitionen:

Datenträger (children) Definition parity data spares
4 dRAID:2d:1s:4c 1 2 1
11 dRAID2:7d:2s:11c 2 7 2
26 dRAID3:8d:2s:26c 3 8 2
50 dRAID2:7d:3s:50c 2 7 3

Im Gegensatz zu einem herkömmlichen RAIDZ ist die Stripe-Länge bei einem dRAID festgelegt. Die Stripe-Width ergibt sich aus der Disk Sector Size multipliziert mit den data-Anteilen.

Beispiel: Eine Disk Sector Size von 4k und ein Daten-Anteil von 7 (siehe Beispiel 2 oben) ergäbe eine Stripe-Width von 7 * 4k = 28k.

Aufbau

Ein dRAID Verbund ist ein Zusammenspiel verschiedener Teile[1]:

child Bezeichnet einen Datenträger innerhalb eines dRAID Verbunds.
row Ein 16 MB großer Chunk, der auf allen Datenträger denselben Offset hat.
group Bezeichnet die RAIDZ-Gruppen innerhalb des dRAID. Sie beinhalten Daten und Parität. Falls notwendig, können groups row-übergreifend verteilt werden.
slice Ein slice bildet den Rahmen für groups und rows innerhalb eines dRAID Verbunds. Er ist abgeschlossen, sobald die groups einer row vollständig beschrieben sind.
device map Die device map bestimmt die Verteilung von data, parity und spare auf die children im Verbund. Sie ist in Reihen bzw. columns eingeteilt.

Die device map wird für jeden slice neu festgelegt wird. Daher ist es sinnvoll sich den Aufbau eines slices zu verdeutlichen:

Raid sets-dRAID Slice komplex.png

Jede Reihe innerhalb der device map steht für ein child im dRAID. In jedem slice wird sie zufällig permutiert, also neu angeordnet. Das sorgt dafür, dass data, parity und spares zufällig auf alle children verteilt werden. Dadurch werden Hot-Spots innerhalb des RAID Sets vermieden. Die spare-Anteile sind innerhalb eines slices statisch. Sie werden über die einzelnen slices verteilt.

Betrachtet man zusätzlich auch groups und rows, ergibt sich ein vollständiges Bild eines dRAID.

Betrachten wir das Beispiel eines dRAID2:4d:2s:11c. Diese Definition bedeutet, der Verbund wird gebildet aus 11 children. Jede group beinhaltet 4 data und 2 parity, was einem RAIDZ-2 entspricht. Zustätzlich sollen 2 spares gebildet werden. Da 11 children zur Verfügung stehen, aber mit data, parity und spares nur 9 children genutzt werden, müssen in diesem dRAID-Verbund groups auf mehrere rows verteilt werden. Am besten verdeutlicht man sich dies anhand eines Diagramms:

Raid sets-dRAID Detail.png

Solange also die Summe der data, parity und spares unter der Anzahl der children liegt, kann man immer ein dRAID bilden.

Die Anzahl der groups innerhalb eines slice hängt dabei davon ab, wann eine row vollständig und ohne Rest abgeschlossen wird. Die notwendigen groups innerhalb eines Verbunds können mithilfe einer kurzen Berechnung ermittelt werden.

groups pro slice berechnen

Die columns einer group bestimmen sich aus der Summe aus data und parity. Aus der Differenz von children und spares ergibt sich, wieviele columns insgesamt von groups gefüllt werden müssen. Das kleinste gemeinsame Vielfache dieser beiden Werte zeigt dann, wie viele groups benötigt werden, bis eine row vollständig und ohne Rest befüllt werden kann:

n := groups pro slice, d :=data, p := parity, c := children, s := spare
n * d+p = KgV(d+p,c-s)

In unserem Beispiel ergibt das:

n * d+p = KgV(d+p,c-s)
n *  6  = KgV(6,9)
n *  6  = 18
n       =  3

Es werden also 3 groups benötigt.

Vergleich

In der folgenden Tabelle wird dRAID verglichen mit anderen RAID-Arten. Dabei ist zu beachten, dass die diagrammatische Darstellung des dRAID stark vereinfacht ist und die device map nicht berücksichtigt wird.

Bezeichnung Dateisystem Datenträger Minimum Stripe Länge (data + parity) Parität Allokation (Parität) Allokation

(Hot Spare)

Funktionsdiagramm
RAID-5 - 3 Statisch 1 Verteilt Statisch (Single Device) Raid sets-RAID-5 mit Hot-Spare.png
RAIDZ-1 [2,3] OpenZFS 3 Dynamisch 1 [2,3] Verteilt Statisch (Single Device) Raid sets-RAIDZ-1 mit Hot-Spare.png
dRAID-1 [2,3] OpenZFS (ab 2.1.0) 3 Statisch 1 [2,3] Verteilt Verteilt Raid sets-dRAID Simpel.png

Einrichtung

Dieser Abschnitt befasst sich mit der Einrichtung eines dRAID. Sie funktioniert für alle Distributionen, die mindestens OpenZFS 2.1.0 bereitstellen.

Es ist sinnvoll ein dRAID über die SCSI-IDs anzulegen, was einen späteren Austausch von Datenträgern erleichtert. Eine Einrichtung mit SCSI-IDs ist per GUI einfacher, über das Terminal ist sie aber ebenfalls möglich.

Terminal

Die Einrichtung über das Terminal ist sehr einfach und benötigt nur einen Befehl.

Die Einrichtung gelingt mit[2]

# zpool create <options> <pool> draid[<parity>][:<data>d][:<children>c][:<spares>s] <vdevs...>

Zur Erläuterung:

Befehl Beschreibung
zpool Paket zur Erstellung eines ZFS Storage Pools.
create Befehl zur Erstellung eines zpool.
<options> Hier können die regulären Optionen für einen zpool gesetzt werden.
<pool> Feld für den Namen des zu erstellenden zpool.
draid[<parity>] Befehl zur Definition des dRAID. Mögliche Paritäten sind 1 (Default), 2 und 3.
[:<data>d] Anzahl der Daten-Devices pro Gruppe. Ein niedrigerer Wert erhöht IOPS, Kompressionsrate und verbessert die Resilvering-Dauer. Verringert gleichzeitig auch die nutzbare Datenkapazität (Default 8).
[:<children>c] Gesamtzahl der zu verwendenden Datenträger.
[:<spares>s] Anzahl der Spare-Devices (Default 0).
<vdevs...> Eingabe der im dRAID zu verwendenden vdevs.

Hinweis: [:d][:c][:s] können in beliebiger Reihenfolge verwendet werden.

Hier eine Beispielhafte Konfiguration:

GUI

Ein dRAID ist ein regulärer zpool und wird wie gewohnt eingerichtet:

Pool Vergleich

Der Unterschied bei der (einfachen) Einrichtung per Terminal bzw. GUI ist hier zu sehen:

Ausfall von Datenträgern

Dieser Abschnitt beschreibt das Resilvering und das Rebalancing eines dRAID im Falle eines Defekts innerhalb des Verbunds.

Resilvering

Durch die im Verbund enthaltenen Spare-Anteile funktioniert das Resilvering im dRAID automatisch sobald der ZFS Event Daemon (ZED)[4] den Ausfall bemerkt. Die folgende Bildreihe verdeutlicht den Vorgang innerhalb der Proxmox-Umgebung:

Resilvering Typen

dRAID unterstützt sowohl sequential resilver[5] als auch traditionelles healing resilver.

Der Vorteil von sequential resilver bei dristibuted Hot-Spares ist, dass die Rebuild-Zeit mit dem Quotienten aus disks und Stripe-Länge skaliert[6].

Standardmäßig ist sequential resilver aktiviert. Dies kann mit dem Befehl

# zpool get feature@device_rebuild

abgefragt werden[7]. In unserem Fall erhalten wir folgende Ausgabe:

# zpool get feature@device_rebuild
NAME   PROPERTY                VALUE                   SOURCE
rpool  feature@device_rebuild  enabled                 local
tank   feature@device_rebuild  enabled                 local

Dieser Wert muss bei der Erstellung des Verbunds gesetzt werden. Eine nachträgliche Änderung ist nicht möglich:

# zpool set feature@device_rebuild=disabled tank
cannot set property for 'tank': property 'feature@device_rebuild' can only be set to 'disabled' at creation time

Der richtige Befehl zur Erstellung eines dRAID ohne sequential resilver ist:

# zpool create -o feature@device_rebuild=disabled <pool> ...

Beispiel:

root@pve73-test:~# zpool create -o feature@device_rebuild=disabled tank draid:2d:2s:5c /dev/sd[d-h]
root@pve73-test:~# zpool get feature@device_rebuild
NAME   PROPERTY                VALUE                   SOURCE
rpool  feature@device_rebuild  enabled                 local
tank   feature@device_rebuild  disabled                local
root@pve73-test:~# 

Rebalancing

Dieser Vorgang beschreibt den Ausgleich eines RAID-Verbundes durch ersetzen eines ausgefallenen Datenträgers. Wird ein Hard-Drive mit derselben SCSI-ID in das System eingebunden, so findet ein Rebalance automatisch statt. Soll ein Datenträger mit einer anderen SCSI-ID eingebunden werden, so ist dies in der aktuellen Proxmox Version 7.3-3 nicht per GUI, sondern ausschließlich über das Terminal möglich.

Der Befehl für das Einbinden eines neuen Laufwerks in den Verbund ist:

# zpool replace <pool> <device-old> <device-new>

In der folgenden Bilderreihe wird der Vorgang verdeutlicht:

Weitere Informationen

Einzelnachweise


Foto Stefan Bohn.jpg

Autor: Stefan Bohn

Stefan Bohn ist seit 2020 bei der Thomas-Krenn.AG beschäftigt. Ursprünglich als Berater für IT-Lösungen im PreSales beheimatet, wechselte er 2022 zum Product Management. Dort widmet er sich dem Wissenstransfer und treibt dabei auch das Thomas-Krenn Wiki voran.

Icon-LinkedIn.png

Das könnte Sie auch interessieren

Maintenance Mode Proxmox VE aktivieren
Wake On LAN Proxmox - Konfiguration inkl. BIOS
X12DPi-NT6 Proxmox VE 8 poweroff statt reboot