19.18. Highly Available Storage (HAST)

Bijgedragen door Daniel Gerzo. Met informatie van Freddie Cash, Pawel Jakub Dawidek, Michael W. Lucas, en Viktor Petersson.

19.18.1. Overzicht

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 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:

Voor het lezen van deze sectie dient u:

Het HAST-project werd gesponsord door The FreeBSD Foundation met ondersteuning van OMCnet Internet Service GmbH en TransIP BV.

19.18.2. Eigenschappen van HAST

De belangrijkste eigenschappen van HAST zijn:

19.18.3. Werking van HAST

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:

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.

19.18.3.1. Synchronisatie- en replicatiemodi

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.

19.18.4. HAST-configuratie

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 de volgende regel aan het kernelconfiguratiebestand toe te voegen:

options    GEOM_GATE

Het HAST-raamwerk bestaat vanuit het besturingssysteem gezien uit verschillende delen:

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 simpelst mogelijke configuratie:

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, is het mogelijk om de HAST-pool aan te maken. Voer de volgende 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.

HAST is niet verantwoordelijk voor het kiezen van de rol van een knooppunt (primair of secundair). De rol van een knooppunt dient door een beheerder of andere software zoals Heartbeat gebruikmakend van hastctl(8) te worden geconfigureerd. Voer het volgende commando uit op het primaire knooppunt ( hasta):

# hastctl role primary test

Voer het volgende, soortgelijke, commando uit op het secundaire knooppunt (hastb):

# hastctl role secondary test

Let opHet kan gebeuren dat beide knooppunten niet met elkaar kunnen communiceren en beiden geconfigureerd zijn als primaire knooppunten; het gevolg van deze situatie wordt split-brain genoemd. Volg de stappen zoals beschreven in Paragraaf 19.18.5.2 om deze situatie op te lossen.

Het is mogelijk om met het gereedschap hastctl(8) het resultaat op elk knooppunt te verifiëren:

# hastctl status test

Het belangrijke gedeelte van de uitvoer 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 het commando hastctl status 0 bytes aan dirty extents rapporteert.

De laatste 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), en het enkele minuten kan duren afhankelijk van de grootte van de harde schijf:

# 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. De volgende regel dient aan het bestand /etc/rc.conf te worden toegevoegd:

hastd_enable="YES"

19.18.4.1. Failover-configuratie

Het doel van dit voorbeeld is om een robuust opslagsysteem te bouwen dat resistent is tegen het falen van alle knooppunten. De hoofdtaak is het oplossen van een scenario waarin een primair knooppunt van het cluster faalt. Mocht dit gebeuren, dan neemt het secundaire knooppunt het feilloos over, controleert en koppelt het het bestandssysteem aan, en gaat het verder zonder dat er een bit aan gegevens ontbreekt.

Om deze taak voor elkaar te krijgen, is het nodig om een andere eigenschap te gebruiken die beschikbaar is op FreeBSD en dat voorziet in automatische failover van de IP-laag -- CARP. CARP staat voor Common Address Redundancy Protocol en 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 deze taak voltooid is, zou elk knooppunt een eigen interface carp0 met een gedeeld IP-adres 172.16.0.254 moeten hebben. 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. In zulke gevallen is het mogelijk om een script te draaien dat automatisch de failover afhandelt.

Om de toestandsverandering op de CARP-interfaces af te vangen, dient de volgende configuratie te worden toegevoegd 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";
};

Draai het volgende commando 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).

Het volgende 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 doet het script het volgende 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 de juiste plaats aankoppelen.

Wanneer een knooppunt backup / secundair wordt:

  • De HAST-pools afkoppelen.

  • De HAST-pools degraderen naar secundair.

Let opHoud in gedachte dat dit slechts een voorbeeldscript is dat dienst doet 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 het doel van 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.

19.18.5. Problemen oplossen

19.18.5.1. Algemene tips om problemen op te lossen

HAST zou over het algemeen zonder problemen moeten werken, maar 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.

Het debug-niveau van hastd(8) dient verhoogd te worden wanneer problemen met HAST worden verholpen. Dit kan gedaan 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. Het is ook de moeite te overwegen om het argument -F te gebruiken, dat het daemon hastd(8) in de voorgrond zal starten.

19.18.5.2. Herstellen van de Split-brain-conditie

Het gevolg van de situatie waarin beide knooppunten van het cluster niet met elkaar kunnen communiceren en beide als primaire knooppunten zijn ingesteld wordt split-brain genoemd. Dit is een gevaarlijke situatie omdat het beide knooppunten in staat stelt om incompatibele veranderingen aan de gegevens te maken. Deze situatie dient handmatig door de systeembeheerder te worden afgehandeld.

Om deze situatie op te lossen moet de beheerder besluiten welk knooppunt de belangrijkere veranderingen bevat (of ze handmatig samenvoegen) en HAST de volledige synchronisatie op het knooppunt dat de kapotte gegevens heeft laten uitvoeren. Voer hiervoor de volgende commando's uit op het knooppunt dat opnieuw gesynchroniseerd moet worden:

# hastctl role init <resource>
# hastctl create <resource>
# hastctl role secondary <resource>