Redundant EFI System Partitions voor een Linux Raid Systeem

Hoewel software raid goede bescherming biedt bij uitval van een disk, is er één aspect dat daarbij mis kan gaan: booten. Vroeger lukte dat met een RAID1 (mirrored) boot disk nog wel, tegenwoordig niet meer. Hoe het dan wel moet, dat lees je hier. We baseren ons op Ubuntu Linux, maar andere distributies werken vergelijkbaar.

Het probleem

Je hebt een server met een RAID-setup: meerdere disks, die gezamenlijk een tegen uitval beveiligde opslag bieden. Dan wil je niet alleen dat je data veilig is bij uitval van een van de disks, maar je wilt ook dat je systeem een herstart overleeft.

Linux-distributies zijn inmmiddels allemaal over naar EFI voor het booten, maar stuk voor stuk wordt de boot-partitie (in EFI termen: de EFI System Partition, ESP), op een enkele disk gezet.

Daar sta je, met je RAID6-redundante systeem, een enkele bootpartitie op een disk die defect is geraakt.

Vroeger: MBR, RAID1, superblock 0.9

Voordat EFI gemeengoed werd, kon je als volgt meerdere bootable disks maken. Je maakte van de bootdisk een RAID1 device (eventueel met spares). Vervolgens installeerde je grub (of LiLo) op alle bij dit RAID-device horende disks. Deze truc werkte, omdat het raidblock bij het destijds gangbare Linux RAID 0.9 aan het eind van de partitie stond. De Master Boot Record, gevolgd door het filesystem, stond aan het begin. Voor het bios leek het dus alsof er gewoon twee bootable partities waren, maar was de kernel eenmaal geboot, dan werden de twee partities tot een MD raid device samengevoegd en alleen als MD device aangesproken. Met een beetje geluk (zowel LiLo als Grub kenden hun eigenaardigheden) wilde het systeem daardoor nog steeds booten, ook na uitval van 1 disk.

Nu: EFI, RAID superblock ≥ 1.0

Tegenwoordig lukt deze truc niet meer, want het raidblock staat aan het begin van de partitie. Er is daardoor geen plek voor een bootsector voor het BIOS. Bovendien zijn de disks tegenwoordig meestal voorzien van GPT, en wordt gebruik gemaakt van een EFI System Partion (ESP) voor het booten.

Bij installatie van een systeem met software-raid wordt doorgaans echter maar één zo’n ESP aangemaakt: op de eerste disk. Als deze uitvalt, draait het systeem door – maar een reboot gaat niet meer lukken als de kapotte disk ontbreekt.

Om te kunnen blijven booten, ook na disk-uitval, is het nodig om meer dan één EFI partitie te hebben waarvan gestart kan worden. Die moet je met de hand aanmaken, omdat geen enkele Linux-distributie dat geautomatiseerd doet. Gelukkig is het niet moeilijk, als je weet wat je moet doen.

Eerst nog even opfrissen hoe EFI-booten met een enkele disk werkt.

EFI met één disk

Onder Ubuntu werkt het booten als volgt:

  1. Tijdens de installatie wordt een kleine partitie, 100Mb, aangemaakt met een FAT32-filesystem.
  2. Op die partitie staat een map EFI met daarin weer een map ubuntu. En omdat EFI de DOS-methode voor het onderscheiden van mappen aanhoudt, is het, vanuit EFI gezien althans, niet EFI/ubuntu/ maar EFI\ubuntu\ (met backslashes dus).
  3. In de map ubuntu staat ofwel een enkel bestand grubx64.efi (als er geen secure boot gebruikt wordt); ofwel, in geval van secure boot, een paar bestanden, namelijk shim64.efi, grubx64.efi, grub.cfg en misschien nog mmx64.efi. Hierover zo meteen meer.
  4. Met behulp van de Linux utility efibootmgr is ofwel grubx64.efi, ofwel shim64.efi als boot manager geregistreerd in het NVRAM.

Tijdens het booten wordt uit NVRAM gelezen welke disk, welke partitie en welk bestand geopend en gestart moet worden – en dat wordt gestart.

Als er een enkele “grubx64.efi” op de schijf staat, dan is dat een samengesteld programma, dat – met behulp van grub-mkimage zowel grub zelf, als de bijpassende modules, als de grub.cfg aan boord heeft. Bij een systeem met shim64.efi wordt een eenvoudige grub-configuratie los bijgevoegd als grub.cfg. Van daaruit wordt de rest van grub, inclusief de volledige configuratie, geladen.

Opzet multiple EFI Partitions

Na installatie van Ubuntu is er een ESP van een van de disks gemount op /boot/efi. Hier vind je EFI/ubuntu/ en daarin de boot-bestanden. In het NVRAM staat deze bootloader geregistreerd – onder de naam ubuntu.

We gaan uit van de situatie waarbij je drie disks hebt, genaamd /dev/sda, /dev/sdb en /dev/sdc. Op deze disks staat een eenvoudige partitie-indeling, in GPT-stijl: op alle disks is de eerste partitie de EFI-boot-partitie, de tweede partitie is een Linux RAID-partitie. Dat ziet er zo uit:

~# parted /dev/sda print
Model: ATA SAMSUNG MZ7WD480 (scsi)
Schijf /dev/sda: 480GB
Sectorgrootte (logisch/fysiek): 512B/512B
Partitietabel: gpt

Nummer Begin   Einde Grootte Bestandssysteem Naam        Vlaggen
 1     1049kB  106MB 105MB   fat32           EFI         System opstart
 2     106MB   480GB 480GB                   Linux RAID  raid

We maken nu op de root-partitie extra EFI mountpoints aan voor disks sdb en sdc:

mkdir /boot/efi-sdb1 /boot/efi-sdc1

Zorg dat /dev/sdb1 en /dev/sdc1 efi partities zijn, bijvoorbeeld met parted of gdisk. Maak een vfat aan op deze partities. De EFI-standaard schrijft voor dat dit een FAT32-partitie moet zijn (er bestaat ook nog zoiets als FAT12 en FAT16, maar dat mag dus niet):

mkfs.vfat -F 32 /dev/sdb1
mkfs.vfat -F 32 /dev/sdc1
mount /dev/sdb1 /boot/efi-sdb1
mount /dev/sdc1 /boot/efi-sdc1

Kopieer nu de boot-bestanden naar de beide disks:

cp -r /boot/efi/* /boot/efi-sdb1
cp -r /boot/efi/* /boot/efi-sdc1

Bekijk met efibootmgr -v hoe ubuntu geladen wordt. Daar komt bijvoorbeeld uit:

~# efibootmgr -v
BootCurrent: 0019
Timeout: 0 seconds
BootOrder: 0019
Boot0000  Setup
Boot0001  Boot Menu
Boot0002  Diagnostic Splash Screen
Boot0003  Startup Interrupt Menu
Boot0004  ME Configuration Menu
Boot0005  Rescue and Recovery
Boot0006* USB CD
Boot0019* ubuntu	HD(3,GPT,7b3cd7a2-e175-4432-805b-398a7ebeeb8c,0xdcb4800,0x32000)/File(\EFI\ubuntu\shimx64.efi)

Dat betekent: ubuntu boot harddisk, van de partitie met GUID 7b3cd7a2-e175-4432-805b-398a7ebeeb8c en bestand EFI/ubuntu/shim64.efi. De GUID van de partitie kun je terugvinden met het commando blkid. Nodig is dat niet, want efibootmgr (en grub-install) zoeken dat in de achtergrond zelf uit. Maar je kunt wel controleren of de juiste partitie gekozen is:

~# blkid -p -o value -s PART_ENTRY_UUID /dev/sda1
7b3cd7a2-e175-4432-805b-398a7ebeeb8c

We voegen nu voor de andere partities ook boot-opties toe aan de EFI bootmanager. De optie “-c” staat voor create, “-d” is de disk die we bootable willen maken en “-p” de partitie. Met “-l” geef je het boot-bestand op en “-L” is de naam. LET OP: gebruik NIET het woord “ubuntu” (of UbuntU, uBunTU) in de naam, want dan haalt grub-install je boot-entry de volgende keer weg, zie bug #1568050.

efibootmgr -v -c -d /dev/sdb -p 1 -l '\EFI\ubuntu\shimx64.efi' -L sdb1-shimx64
efibootmgr -v -c -d /dev/sdc -p 1 -l '\EFI\ubuntu\shimx64.efi' -L sdc1-shimx64

Het resultaat: De EFI bootmanager kan booten van 3 EFI partities. Let op: de bootvolgorde is nu ook gewijzigd: de laatst toegevoegde entry (in het voorbeeld: /dev/sdc1) wordt de eerste die geprobeerd wordt door het systeem.

Wat kan er nog mis gaan

Alles. We behandelen een paar zaken die we zelf tegenkwamen.

Een eventueel nieuwe versie van grub-install (bijvoorbeeld vanwege een security issue of een bug fix) overschrijft de grubx64.efi in /boot/efi/EFI/ubuntu/. De kopieën die je maakte in /boot/efi-sdb/ en /boot/efi-sdc/ worden niet bijgewerkt. Daarnaast is problematisch dat de EFI boot-entries waar het woord ubuntu in voorkomt, worden weggehaald door grub-install.

Wanneer je een verkeerde partitie opgeeft, zal efibootmgr “gewoon” de opties in NVRAM zetten – maar je houdt er een non-bootable partitie aan over. Soms kun je dat zien aan de foutieve GPT-entry:

Boot0003* boot via /dev/sdc HD(99,GPT,00000000-0000-0000-0000-000000000000,0x0,0x1)/File(\EFI\ubuntu\grubx64.efi)

… maar soms lijkt er eigenlijk niks mis:

Boot0002* boot via /dev/sdc HD(4,GPT,84931182-be00-46e0-86a2-3cde8f0768cb,0x123188000,0x37d26800)/File(\EFI\ubuntu\grubx64.efi)

Dat ziet er prima uit; alleen is bovenstaande partitie helemaal niet FAT32-geformatteerd, is hij niet van het type “boot, esp” (0xef00) en staat er ook nergens een bestand EFI/ubuntu/grubx64.efi op. Maar dat kun je allemaal niet zien aan deze entry.

Het hangt van de implementatie van EFI af wat er gebeurt bij zo’n verkeerde boot-regel. Sommige PC’s rollen gewoon door naar de volgende entry, zonder foutmelding. Dat is niet alleen vervelend, maar het kan zelfs leiden tot een niet-bootable systeem als je per ongeluk twee niet-bootable schijven hebt opgegeven in je handmatige EFI-entries.

De ultieme test is dus, helaas, om tijdelijk /dev/sda fysiek los te koppelen, dan te kijken of het systeem wil booten en pas als je dat gedaan hebt, /dev/sda weer aan te koppelen. En dan ook nog eens op tijd: want laat je de disk losgekoppeld, dan constateert de RAID-driver dat er een disk ontbreekt en gooit /dev/sda uit het array…

Oppassen dus. Niet alleen na het toevoegen van de extra boot-entries, maar juist ook tijdens het testen ervan.