Homer – ja, Homer – mein Hauptserver zu Hause, hatte auf einer Festplatte immer mal wieder Lesefehler. Das war eine ganze Zeit weg und ich dachte, das Thema wäre gegessen, jetzt tauchten sie aber wieder auf. Also: Neue Festplatte muss rein, bevor die alte stirbt.
Ich schreibe hier einmal die Konstellation und wie ich vorgegangen bin, da das Setup etwas „eigenwillig“ ist.
Homer ist ein HP Microserver der achten Generation, hat 8GB RAM, vier Festplattenplätze, die bei mir komplett mit 2TB-HDDs belegt sind. Installiert ist aktuell FreeBSD 13.1-RELEASE. Ich wollte ein RAID5 haben, aber meine Daten verschlüsselt vom Betriebssystem trennen, ohne eine Festplatte dazu abzustellen oder irgendeine andere Lösung zu nutzen. Auch wollte ich keinen Hardware-RAID-Controller haben. Zum Einen, weil die teuer sind, aber viel wichtiger: weil ich die Vorteile von ZFS wollte.
Also: Betriebssystem unverschlüsselt (kann man drüber streiten, normalerweise solltet ihr aber alles verschlüsseln, auch OS und Logging usw.!), Daten verschlüsselt, alles RAID5 soweit möglich, in meinem Fall also RAID-Z1. Da ich noch einen SWAP-Bereich habe, sollte der auch redundant ausgelegt sein. Dafür nahm ich gmirror (GEOM mirror).
Die Partitionierung aller vier Platten ist identisch:
=> 40 3907029088 adaX GPT (1.8T)
40 944 1 (null) (472K)
984 33554432 2 swapX (16G)
33555416 125829120 3 zrootX (60G)
159384536 3732930560 4 serverX (1.7T)
3892315096 14714032 - free - (7.0G)
Das X steht hier für eine Zahl zwischen 0 und inklusive 3. Alle vier HDDs haben einen Bootsektor und Bootcode für ZFS drauf, so dass tatsächlich jede Platte ausfallen, aber dennoch gebootet werden kann.
Ich hatte hier noch eine Festplatte auf Halde, gleiche Größe, anderes Modell. Aus dem Grund sieht man, dass ich in der Partitionierung noch 7GB freigelassen habe. Freilich ist das ein wenig viel, um Hardwareunterschiede auszugleich, es reicht merklich weniger, aber ich weiß nicht mehr, warum ich diese Entscheidung vor einigen Jahren so traf. Letztlich ist es so, dass die eine 2TB-Platte von Hersteller X doch ein paar weniger oder mehr Bytes als die von Hersteller Y oder von einem anderen Modell haben kann. Ist die Platte kleiner, kann das RAID nicht mehr resilvern, da ja die Kapazität nicht ausreicht. Deshalb lässt man einfach ein paar MB (und nicht wie ich GB) frei, falls das Problem einmal eintreten sollte.
Gut, Platte lag herum, was als nächstes? Natürlich direkt eine neue Platte bestellen, denn sobald ich die auf Halde liegende Platte verbaue, habe ich keinen Ersatz mehr hier für einen meiner Server.
Danach war mein Vorgehen recht einfach. Als erstes sicherte ich mir das Layout der Platte (ada2 war defekt):
gpart backup ada2 > /root/ada2.gpart
Auch, wenn HP angibt, dass ohne RAID-Controller das System nicht „Hotplugable“ sei, ist das doch in den Spezifikationen für SATA drin und ich hätte die Platte auch so ziehen können. Da ich den Rechner aber auch aussagen wollte (und der hatte es nötig!), fuhr ich ihn herunter, saugte aus, tauschte die Platte und fuhr den Rechner wieder hoch (bitte, liebe Hersteller: macht den Tausch von Festplatten doch caddy- und schraubenfrei!).
Natürlich waren die RAIDs jetzt „degraded“. Hier beginnt die kritische Phase. Als erstes sah ich, ob die neue Platte erkannt wurde:
root@homer:~ # camcontrol devlist
<ST2000VX003-1HH164 CV12> at scbus0 target 0 lun 0 (pass0,ada0)
<ST2000VX003-1HH164 CV12> at scbus1 target 0 lun 0 (pass1,ada1)
<ST2000DM008-2FR102 0001> at scbus2 target 0 lun 0 (pass2,ada2)
<ST2000VX003-1HH164 CV12> at scbus3 target 0 lun 0 (pass3,ada3)
<AHCI SGPIO Enclosure 2.00 0001> at scbus6 target 0 lun 0 (ses0,pass4)
<asmedia ASM1153E 0> at scbus7 target 0 lun 0 (da0,pass5)
Und da war sie. Man sieht, dass es ein anderes Modell ist. Mit
root@homer:~ # diskinfo -v ada2
ada2
512 # sectorsize
2000398934016 # mediasize in bytes (1.8T)
3907029168 # mediasize in sectors
4096 # stripesize
0 # stripeoffset
3876021 # Cylinders according to firmware.
16 # Heads according to firmware.
63 # Sectors according to firmware.
ST2000DM008-2FR102 # Disk descr.
ZFL5QMHW # Disk ident.
ahcich2 # Attachment
id1,enc@n3061686369656d30/type@0/slot@3/elmdesc@Slot_02 # Physical path
Yes # TRIM/UNMAP support
7200 # Rotation rate in RPM
Not_Zoned # Zone Mode
sah ich mir dann noch die Spezifikationen an und alles war soweit ok. Jetzt spielte ich das Paritionsschema wieder ein, was ich vorher sicherte:
gpart restore ada2 < /root/ada2.gpart
Da ja alle Platten das selbe Partitionsschema haben, hätte ich auch folgendes machen können:
gpart backup ada1 | gpart restore ada2
Dabei werden aber die Labels nicht mitgesichert, so dass ich diese noch setzen musste:
gpart modify -i 2 -l swap2 ada2
gpart modify -i 3 -l zroot2 ada2
gpart modify -i 4 -l server2 ada2
Als nächstes wollte ich mit dem kleinsten Problem beginnen, dem Swap-Mirror, der den Namen „swap“ trägt. Also:
gmirror forget swap
gmirror insert swap /dev/gpt/swap2
Das Resilvering ging dann sehr schnell, weil Swap nicht sonderlich groß war, und schon bald sah es so aus:
root@homer:~ # gmirror status
Name Status Components
mirror/swap COMPLETE ada0p2 (ACTIVE)
ada1p2 (ACTIVE)
ada3p2 (ACTIVE)
ada2p2 (ACTIVE)
Dann ging es an den zroot, also den Bereich, auf dem das Betriebssystem liegt. Das war sehr einfach, da nicht verschlüsselt, und somit reichte:
zpool replace zroot gpt/zroot2 gpt/zroot2
Schon begann das Resilvering, was auch nicht lange brauchte. In der Zeit kümmerte ich mich um den „server“-Bereich. Dieser ist mit GELI (GEOM eli) verschlüsselt, also musste ich das zuerst vorbereiten:
geli init -s 4096 -e aes -l 256 /dev/gpt/server2
Dann einhängen:
geli attach /dev/gpt/server2
Hat das funktioniert, dann noch das Device im ZFS-Pool tauschen:
zpool replace server /dev/gpt/server2.eli /dev/gpt/server2.eli
Jetzt noch den Bootcode schreiben, damit man von der Platte auch booten kann:
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada2
Solange das Resilvering läuft, ist natürlich „kritische Phase“:
root@homer:~ # zpool status
pool: server
state: DEGRADED
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
scan: resilver in progress since Tue Sep 13 06:32:15 2022
4.10T scanned at 47.7M/s, 3.34T issued at 38.8M/s, 5.37T total
856G resilvered, 62.11% done, 15:15:49 to go
config:
NAME STATE READ WRITE CKSUM
server DEGRADED 0 0 0
raidz1-0 DEGRADED 0 0 0
gpt/server0.eli ONLINE 0 0 0
gpt/server1.eli ONLINE 0 0 0
replacing-2 DEGRADED 0 0 0
4177616201411802674 UNAVAIL 0 0 0 was /dev/gpt/server2.eli/old
gpt/server2.eli ONLINE 0 0 0 (resilvering)
gpt/server3.eli ONLINE 0 0 0
errors: No known data errors
pool: zroot
state: ONLINE
scan: resilvered 9.88G in 00:06:38 with 0 errors on Tue Sep 13 06:36:11 2022
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/zroot0 ONLINE 0 0 0
gpt/zroot1 ONLINE 0 0 0
gpt/zroot2 ONLINE 0 0 0
gpt/zroot3 ONLINE 0 0 0
errors: No known data errors
Man sieht, dass der Aufwand natürlich durchaus höher ist, als bei einem Hardware-RAID, wo man im Optimalfall nur „Platte raus, Platte rein“ machen muss. Aber sonderlich schwierig und kompliziert ist es auch nicht.
Update
Das Resilvering ist durch, das RAID ist wieder in einem konsistenten Zustand. Es hat fast 43 Stunden gedauert, bis alles durch war.
root@homer:~ # zpool status
pool: server
state: ONLINE
scan: resilvered 1.34T in 1 days 18:41:45 with 0 errors on Thu Sep 15 01:14:00 2022
config:
NAME STATE READ WRITE CKSUM
server ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/server0.eli ONLINE 0 0 0
gpt/server1.eli ONLINE 0 0 0
gpt/server2.eli ONLINE 0 0 0
gpt/server3.eli ONLINE 0 0 0
errors: No known data errors
pool: zroot
state: ONLINE
scan: resilvered 9.88G in 00:06:38 with 0 errors on Tue Sep 13 06:36:11 2022
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
gpt/zroot0 ONLINE 0 0 0
gpt/zroot1 ONLINE 0 0 0
gpt/zroot2 ONLINE 0 0 0
gpt/zroot3 ONLINE 0 0 0
errors: No known data errors