Hoge beschikbaarheid is een van de hoofdzaken in serieuze zakelijke toepassingen
en hoog beschikbare opslag is een sleutelonderdeel in zulke omgevingen. Hoog
beschikbare opslag, of HAST, werd ontwikkeld door Pawel Jakub
Dawidek <pjd@FreeBSD.org>
als een raamwerk dat
transparante opslag van dezelfde gegevens toestaat over fysiek gescheiden machines
die verbonden zijn door een TCP/IP-netwerk. HAST kan gezien worden als een netwerkgebaseerde RAID1 (spiegel)
en is vergelijkbaar met het DRBD® opslagsysteem bekend van het GNU/Linux® platform. In combinatie met andere eigenschappen
voor hoge beschikbaarheid van FreeBSD zoals CARP maakt HAST het
mogelijk om een opslagcluster met hoge beschikbaarheid te bouwen dat resistent is
tegen falende hardware.
Na het lezen van deze sectie weet u:
Wat HAST is, hoe het werkt en welke mogelijkheden het biedt.
Hoe HAST op FreeBSD te op te zetten en te gebruiken.
Hoe CARP en devd(8) te integreren om een robuust opslagsysteem te bouwen.
Voor het lezen van deze sectie dient u:
De beginselen van UNIX® en FreeBSD te begrijpen (Hoofdstuk 4).
Te weten hoe de netwerkinterfaces en andere kerndeelsystemen van FreeBSD in te stellen (Hoofdstuk 12).
Netwerken op FreeBSD goed te begrijpen (Deel IV in FreeBSD handboek).
FreeBSD 8.1-RELEASE of nieuwer te gebruiken.
Het HAST-project werd gesponsord door The FreeBSD Foundation met ondersteuning van OMCnet Internet Service GmbH en TransIP BV.
De belangrijkste eigenschappen van HAST zijn:
Het kan gebruikt worden om I/O-fouten op lokale harde schijven te maskeren.
Agnostisch qua bestandssysteem, dus het werkt met elk bestandssysteem dat door FreeBSD wordt ondersteund.
Efficiënte en snelle hersynchronisatie, alleen de blokken die zijn veranderd toen een knooppunt uitstond worden gesynchroniseerd.
Het kan gebruikt worden in reeds uitgerolde omgevingen om aanvullende redundantie toe te voegen.
Samen met CARP, Heartbeat of andere gereedschappen kan het worden gebruikt om een robuust en duurzaam opslagsysteem te bouwen.
Omdat HAST synchrone replicatie op blokniveau van elk opslagmedium naar verscheidene machines biedt, heeft het tenminste twee knooppunten (fysieke machines) nodig — het primaire (ook bekend als meester) knooppunt en het secundaire (slaaf) knooppunt. Tezamen worden deze twee machines een cluster genoemd.
Opmerking: HAST is momenteel beperkt tot een totaal van twee clusterknooppunten.
Aangezien HAST in een primaire-secundaire configuratie werkt, kan er op elk moment slechts één van de clusterknooppunten actief zijn. Het primaire knooppunt, ookwel actief, is degene die alle I/O-verzoeken aan apparaten die door HAST worden beheerd afhandelt. Het secundaire knooppunt wordt dan automatisch gesynchroniseerd vanuit het primaire knooppunt.
De fysieke componenten van het HAST-systeem zijn:
lokale schijf (op primair knooppunt)
schijf op verre machine (secundair knooppunt)
HAST werkt synchroon op blokniveau, wat het transparant maakt voor bestandssystemen en toepassingen. HAST biedt reguliere GEOM-aanbieders aan in /dev/hast/ voor zowel andere gereedschappen als toepassingen, er is dus geen verschil tussen het gebruik van apparaten die door HAST worden geleverd en rauwe schijven, partities, etc.
Elke bewerking met betrekking tot schrijven, verwijderen of spoelen wordt naar de plaatselijke schijf en over TCP/IP naar de verre schijf gestuurd. Elke leesbewerking wordt gedaan door de plaatselijke schijf, tenzij de plaatselijke schijf niet actueel is of er een I/O-fout optreed. In zulke gevallen wordt de leesbewerking naar het secundaire knooppunt gestuurd.
HAST probeert om een snel herstel van fouten te leveren. Om deze reden is het heel belangrijk om de synchronisatietijd te verkorten nadat een knooppunt is hersteld van een uitval. Om een snelle synchronisatie te leveren, beheert HAST op de schijf een bitmap van gebruikte extents en synchroniseert het die alleen tijdens een reguliere synchronisatie (met uitzondering van de initiëe synchronisatie).
Er zijn vele manieren om synchronisatie af te handelen. HAST implementeert meerdere replicatiemodi om verschillende synchronisatiemethodes af te handelen:
memsync: rapporteer een schrijfbewerking als voltooid wanneer de plaatselijke schrijfbewerking klaar is en wanneer het verre knooppunt de gegevensaankomst bevestigt, maar voordat het de gegevens daadwerkelijk heeft opgeslagen. De gegevens op het verre knooppunt zullen meteen na het versturen van de bevestiging worden opgeslagen. Deze modus is bedoeld om latency te verminderen en nog steeds een zeer goede betrouwbaarheid te bieden. De replicatiemodus memsync is momenteel niet geïmplementeerd.
fullsync: rapporteer een schrijfbewerking als voltooid wanneer zowel de plaatselijke en de verre schrijfbewerking voltooid zijn. Dit is de veiligste en traagste replicatiemodus. Dit is de standaardmodus.
async: rapporteer de schrijfbewerking als voltooid wanneer de plaatselijke schrijfbewerking klaar is. Dit is de snelste en gevaarlijkste replicatiemodus. Het dient gebruikt te worden wanneer er naar een ver knooppunt wordt gerepliceerd en de latency te hoog is voor andere modi. De replicatiemodus async is momenteel niet geïmplementeerd.
WaarschuwingMomenteel wordt alleen de replicatiemodus fullsync ondersteund.
HAST heeft ondersteuning voor GEOM_GATE nodig om te kunnen functioneren. De kernel GENERIC bevat standaard geen GEOM_GATE, de laadbare module geom_gate.ko is echter beschikbaar in de standaardinstallatie van FreeBSD. Zorg ervoor dat deze module beschikbaar is voor afgeslankte systemen. Het is ook mogelijk om ondersteuning voor GEOM_GATE statisch in de kernel te bouwen, door deze regel aan het kernelconfiguratiebestand toe te voegen:
options GEOM_GATE
Het HAST-raamwerk bestaat vanuit het besturingssysteem gezien uit verschillende delen:
het daemon hastd(8) dat verantwoordelijk is voor de gegevenssynchronisatie,
het beheerprogramma hastctl(8) voor de gebruikers,
het configuratiebestand hast.conf(5).
Het volgende voorbeeld beschrijft hoe twee knooppunten in een meester-slaaf / primaire-secundaire opstelling te configureren door HAST te gebruiken om de gegevens tussen de twee te repliceren. De knooppunten worden hasta met IP-adres 172.16.0.1 en hastb met IP-adres 172.16.0.2 genoemd. Beide knooppunten hebben een toegewijde harde schijf /dev/ad6 van dezelfde grootte om met HAST te werken. De HAST-pool (soms ook een hulpbron genoemd, i.e., de GEOM-aanbieder in /dev/hast/) wordt test genoemd.
Het bestand /etc/hast.conf regelt de configuratie van HAST. Dit bestand dient hetzelfde te zijn op beide knooppunten. Het volgende is de eenvoudigste configuratie die mogelijk is:
resource test { on hasta { local /dev/ad6 remote 172.16.0.2 } on hastb { local /dev/ad6 remote 172.16.0.1 } }
Raadpleeg voor geavanceerdere configuraties de handleidingpagina hast.conf(5).
Tip: Het is ook mogelijk om hostnamen in de regels met remote te gebruiken. Zorg er in dat geval voor dat deze hosts vindbaar zijn, bijvoorbeeld doordat ze zijn gedefinieerd in het bestand /etc/hosts of anders in het plaatselijke DNS.
Nu de configuratie op beide knooppunten aanwezig is, kan de HAST-pool aangemaakt worden . Voer deze commando's op beide knooppunten uit om de initiële metagegevens op de plaatselijke schijf te plaatsen en het hastd(8)-daemon te starten:
# hastctl create test # /etc/rc.d/hastd onestart
Opmerking: Het is niet mogelijk om GEOM-aanbieders met een bestaand bestandssysteem te gebruiken (i.e., een bestaande opslag omzetten naar een door HAST beheerde pool), omdat deze procedure wat metagegevens op de aanbieder moet opslaan en er daarvoor niet genoeg beschikbare ruimte is.
De rol van een HAST-knooppunt (primair of secundair) wordt uitgekozen door een beheerder of software zoals Heartbeat dat het gereedschap hastctl(8) gebruikt. Voer het volgende commando uit op het primaire knooppunt ( hasta):
# hastctl role primary test
Voer dit soortgelijke commando uit op het secundaire knooppunt ( hastb):
# hastctl role secondary test
Let opDe situatie dat de knooppunten niet met elkaar kunnen communiceren en beide geconfigureerd zijn als primaire knooppunten; wordt split-brain genoemd. Volg de stappen zoals beschreven in Paragraaf 19.18.5.2 om deze situatie op te lossen.
Verifieer met het gereedschap hastctl(8) het resultaat op elk knooppunt:
# hastctl status test
De belangrijke tekst is de regel met status dat voor alle knooppunten complete dient te bevatten. Als het degraded bevat, is er iets verkeerd gegaan. Op dat moment is de synchronisatie tussen de knooppunten al begonnen. De synchronisatie is compleet wanneer hastctl status 0 bytes aan dirty extents rapporteert.
De volgende stap is het aanmaken van een bestandssysteem op de GEOM-aanbieder /dev/hast/test en het aan te koppelen. Dit moet op het primaire knooppunt gebeuren, aangezien /dev/hast/test alleen op het primaire knooppunt verschijnt. Het aanmaken van het bestandssysteem kan afhankelijk van de grootte van de harde schijf enkele minuten duren:
# newfs -U /dev/hast/test # mkdir /hast/test # mount /dev/hast/test /hast/test
Wanneer het HAST-raamwerk correct is geconfigureerd, betreft de laatste stap het ervoor zorgen dat HAST automatisch tijdens het opstarten wordt gestart. Voeg deze regel toe aan het bestand /etc/rc.conf:
hastd_enable="YES"
Het doel van dit voorbeeld is om een robuust opslagsysteem te bouwen dat resistent is tegen het falen van alle knooppunten. Het scenario is dat een primair knooppunt van het cluster faalt. Als dit gebeurt, dan neemt het secundaire knooppunt het feilloos over, controleert het het bestandssysteem en koppelt het het bestandssysteem aan, en gaat het verder zonder dat er een bit aan gegevens ontbreekt.
Om dit voor elkaar te krijgen, is er een andere eigenschap die beschikbaar is op FreeBSD dat voorziet in automatische failover van de IP-laag — CARP. CARP (Common Address Redundancy Protocol) maakt het mogelijk dat meerdere hosts in hetzelfde netwerksegment een IP-adres delen. Stel CARP in op beide knooppunten van het cluster volgens de documentatie die beschikbaar is in Paragraaf 32.14. Nadat de opzet voltooid is, heeft elk knooppunt een eigen interface carp0 met een gedeeld IP-adres 172.16.0.254. Het primaire HAST-knooppunt van het cluster moet het meester-CARP-knooppunt zijn.
De HAST-pool die in de vorige sectie is gemaakt is nu klaar om geëxporteerd te worden naar de andere hosts op het netwerk. Dit kan gedaan worden door het te exporteren over NFS, Samba, etc., door gebruik te maken van het gedeelde IP-adres 172.16.0.254. Het enige overgebleven probleem is een automatische failover in het geval dat het primaire knooppunt het begeeft.
Als een CARP-interface aan- of uitgaat, genereert FreeBSD een devd(8)-gebeurtenis, wat het mogelijk maakt om toestandsveranderingen op de CARP-interfaces in de gaten te houden. Een toestandsverandering op het CARP-interface geeft aan dat een van de knooppunten het begaf of weer online kwam. Deze toestandsveranderingen maken het mogelijk om een script te draaien dat automatisch de HAST-failover afhandelt.
Voeg, om toestandsverandering op de CARP-interfaces af te vangen, het volgende toe aan het bestand /etc/devd.conf op elk knooppunt:
notify 30 { match "system" "IFNET"; match "subsystem" "carp0"; match "type" "LINK_UP"; action "/usr/local/sbin/carp-hast-switch master"; }; notify 30 { match "system" "IFNET"; match "subsystem" "carp0"; match "type" "LINK_DOWN"; action "/usr/local/sbin/carp-hast-switch slave"; };
Herstart devd(8) op beide knooppunten om de nieuwe configuratie te laten gelden:
# /etc/rc.d/devd restart
Als het interface carp0 aan of uit gaat (i.e., de toestand van het interface verandert), genereert het systeem een notificatie wat het subsysteem devd(8) in staat stelt om een willekeurig script te draaien, in dit geval /usr/local/sbin/carp-hast-switch. Dit is het script dat de automatische failover afhandelt. Raadpleeg de handleidingpagina devd.conf(5) voor verdere uitleg over de bovenstaande configuratie van devd(8).
Dit zou een voorbeeld van zo'n script kunnen zijn:
#!/bin/sh # Origineel script door Freddie Cash <fjwcash@gmail.com> # Gewijzigd door Michael W. Lucas <mwlucas@BlackHelicopters.org> # en Viktor Petersson <vpetersson@wireload.net> # De namen van de HAST-hulpbronnen, zoals vermeld in /etc/hast.conf resources="test" # vertraging voor het aankoppelen van de HAST-hulpbron na het worden van meester # doe een gok delay=3 # logging log="local0.debug" name="carp-hast" # einde van gebruiker-instelbare dingen case "$1" in master) logger -p $log -t $name "Omschakelen naar primaire aanbieder voor ${resources}." sleep ${delay} # Wacht totdat de "hastd secondary" processen zijn gestopt for disk in ${resources}; do while $( pgrep -lf "hastd: ${disk} \(secondary\)" > /dev/null 2>&1 ); do sleep 1 done # Verwissel de rol voor elke schijf hastctl role primary ${disk} if [ $? -ne 0 ]; then logger -p $log -t $name "Omschakelen van rol naar primair voor hulpbron ${disk} mislukt." exit 1 fi done # Wacht totdat de apparaten /dev/hast/* verschijnen for disk in ${resources}; do for I in $( jot 60 ); do [ -c "/dev/hast/${disk}" ] && break sleep 0.5 done if [ ! -c "/dev/hast/${disk}" ]; then logger -p $log -t $name "GEOM-aanbieder /dev/hast/${disk} is niet verschenen." exit 1 fi done logger -p $log -t $name "Rollen van HAST-hulpbronnen ${resources} omgeschakeld naar primair." logger -p $log -t $name "Schijven aankoppelen." for disk in ${resources}; do mkdir -p /hast/${disk} fsck -p -y -t ufs /dev/hast/${disk} mount /dev/hast/${disk} /hast/${disk} done ;; slave) logger -p $log -t $name "Omschakelen naar secundaire aanbieder voor ${resources}." # Schakel de rollen van de HAST-hulpbronnen om for disk in ${resources}; do if ! mount | grep -q "^/dev/hast/${disk} on " then else umount -f /hast/${disk} fi sleep $delay hastctl role secondary ${disk} 2>&1 if [ $? -ne 0 ]; then logger -p $log -t $name "Omschakelen van rol naar secundair voor hulpbron ${disk} mislukt." exit 1 fi logger -p $log -t $name "Rol van hulpbron ${disk} omgeschakeld naar secundair." done ;; esac
In een notendop neemt het script deze acties wanneer een knooppunt meester / primair wordt:
De HAST-pools opwaarderen naar primair op een gegeven knooppunt.
Het bestandssysteem onder de HAST-pool controleren.
De pools op een juiste plaats aankoppelen.
Wanneer een knooppunt back-up / secundair wordt:
De HAST-pools afkoppelen.
De HAST-pools degraderen naar secundair.
Let opHoud in gedachte dat dit slechts een voorbeeldscript is om aan te tonen dat alles werkt. Het behandeld niet alle mogelijke situaties en kan op elke manier worden uitgebreid of veranderd, het kan bijvoorbeeld benodigde diensten starten en stoppen.
Tip: Voor dit voorbeeld hebben we een standaard UFS-bestandssysteem gebruikt. Om de tijd die nodig is voor herstel te verkorten, kan een bestandssysteem met UFS-journalling of ZFS worden gebruikt.
Meer gedetailleerde informatie met aanvullende voorbeelden kunnen gevonden worden op de HAST Wiki-pagina.
HAST zou over het algemeen zonder problemen moeten werken. Net als met elk ander software-product zijn er momenten waarop het anders werkt dan het zou moeten. De oorzaken van de problemen kunnen verschillen, maar de vuistregel is om ervoor te zorgen dat de klokken zijn gesynchroniseerd op alle knooppunten in het cluster.
Wanneer problemen met HAST worden verholpen, dient het debug-niveau van hastd(8) verhoogd te worden door het daemon hastd(8) met het argument -d op te starten. Merk op dat dit argument meerdere malen kan worden opgegeven om het debug-niveau nog verder op te hogen. Op deze manier kan veel nuttige informatie worden vergaard. Overweeg ook om het argument -F te gebruiken, dat het daemon hastd(8) in de voorgrond zal starten.
Split-brain treedt op waneer de knooppunten van het cluster niet met elkaar kunnen communiceren, en beide als primair zijn geconfigureerd. Dit is een gevaarlijke situatie omdat het beide knooppunten in staat stelt om incompatibele veranderingen aan de gegevens te maken. Dit probleem dient handmatig door de systeembeheerder te worden gecorrigeerd.
De beheerder moet besluiten welk knooppunt de belangrijkere veranderingen bevat (of ze handmatig samenvoegen) en HAST een volledige synchronisatie op het knooppunt dat de kapotte gegevens heeft laten uitvoeren. Voer hiervoor deze commando's uit op het knooppunt dat opnieuw gesynchroniseerd moet worden:
# hastctl role init <resource> # hastctl create <resource> # hastctl role secondary <resource>