Hulpartikel overzicht

Hulpartikel

split-brain-situaties bij MariaDB MaxScale

In dit artikel gaan wij in op split-brain-situaties, met als doel je bewust te maken van wat het is, wat de gevolgen zijn en wat je er al dan niet aan kunt doen. Bij het opzetten van een SQL-cluster heb je vaak diverse configuratie-opties en het is belangrijk op de hoogte te zijn van de implicaties van split-brain, om een weloverwogen keuze te kunnen maken voor je configuratie.

Split-brain-problemen zijn de meest vervelende database problemen die je kunt ervaren in een SQL-cluster, maar wat is een split-brain-situatie?

Een split-brain-situatie is een situatie waarbij twee of meerdere servers in een SQL-cluster elkaar niet meer kunnen zien, maar wel bereikbaar zijn voor clients. Die clients schrijven vervolgens nog steeds data naar een van de servers, maar niet langer naar alle servers.

Het gevolg van dit probleem is dat in je database cluster minimaal één server een andere inhoud krijgt dan de andere server(s). Dit is bijzonder ingewikkeld om op te lossen en het voorkomen (waar mogelijk) is dan ook belangrijker dan het genezen.


Hoe ontstaat een split-brain-situatie?

Split-brain treed bijvoorbeeld op wanneer aan de volgende voorwaarden wordt voldaan:

  • de verbinding tussen de SQL-servers onderling valt weg (i.e. de SQL-servers zien elkaar niet meer).
  • de SQL-diensten op de SQL-servers werken nog wel 
  • de SQL-servers zijn nog bereikbaar voor clients (i.e. clients die write-acties initiëren).

Dit kan bijvoorbeeld gebeuren bij een configuratie-fout op een VPS, of onderbreking van het private network om welke reden dan ook.

Is er geen netwerkverbinding met de buitenwereld, of voer je überhaupt geen write-queries uit naar je SQL-servers (met uitzondering van wanneer je je website update), dan treedt er geen split-brain op. De voorwaarde voor het eerste voorbeeld is wel dat de onderlinge verbinding van je SQL-cluster zich herstelt voor er nieuwe write-acties worden uitgevoerd.


Bij welke split-brain-situatie kun je de gevolgen niet voorkomen?

Het ontstaan van een split-brain-situatie is lastig te voorkomen. Simpel gezegt kun je de gevolgen niet voorkomen wanneer je een automatische failover-setup, of multi-master-setup gebruikt, één master voor de andere VPS'en onbereikbaar wordt, en de andere VPS'en geen manier hebben om vast te stellen dat die master nog wel publiekelijk bereikbaar is.

Wanneer kan een dergelijke situatie bijvoorbeeld ontstaan?

Er zijn voornamelijk twee scenario's denkbaar waarin een dergelijke situatie kan ontstaan:

  • Zijn je databaseservers gescheiden van je webservers en heb je de publieke WAN uitgezet, dan zal wanneer de verbinding tussen de databaseservers wegvalt, maar niet tussen de webservers en databaseservers een split-brain situatie ontstaan.
     
  • Gebruik je twee databaseservers en ontstaat er een probleem met de routing table bij een van de routers die het verkeer tussen twee availability zones verwerkt, dan ontstaat er mogelijk een split-brain situatie. Een routing probleem kan namelijk het publieke WAN en private LAN tussen beide locaties tegelijk onbereikbaar worden, terwijl de verbinding naar de buitenwereld intact blijft. Het gevolg is dat beide VPS'en als master opereren, zonder dit van elkaar te weten.

    De reden dat een dergelijke routing probleem een split-brain-situatie kan veroorzaken, is dat de VPS'en proberen de snelste route naar elkaar te vinden, oftewel via de directe lijn tussen beide availability zones. Een externe gebruiker van je diensten zal nog prima bij je VPS'en kunnen komen, omdat die niet via de directe lijn tussen beide availability zones met je VPS'en verbindt. Dit is een zeldzame situatie en het kan heel goed zijn dat je jezelf nooit met dit specifieke scenario geconfronteerd zult zien.

Indien een van deze situaties zich zou voordoen, zou je nadat het netwerk herstelt is van de verschillende servers in je SQL-cluster handmatig moeten mergen.

Een manier om dit te voorkomen is drie availability zones gebruiken met een VPS in iedere zone. Zo zullen bij een routing probleem bij één availability zone de andere twee availability zones elkaar nog wel zien en het SQL-cluster samen intact houden. Bij een routingprobleem bij twee availability zones, zou je echter nog steeds dit probleem hebben. De kans dat dat gebeurt is gelukkig bijzonder klein.


Split-brain gevolgen voorkomen bij onbereikbaarheid van het private network

Dit onderdeel is niet van toepassing op een Galera-cluster, of andere setups waarbij een quorum vote wordt uitgevoerd. 

De beste manier om split-brain zo veel mogelijk te voorkomen is door drie databaseservers te gebruiken in drie verschillende availability zones. Wordt één server onbereikbaar, dan kunnen de andere nog steeds vaststellen dat zij samen de meerderheid vormen en het cluster intact houden (vijf availability zones met een totaal van vijf databaseservers zou nog mooier zijn).

Er zijn ook twee scenario's denkbaar waarbij je slechts twee databaseservers gebruikt en de gevolgen van split-brain (maar niet de oorzaak) voorkomen kunnen worden:

  • Je gebruikt twee VPS'en met een controlepaneel zoals Plesk of DirectAdmin met een master-slave setup en alleen het private network is onbereikbaar, maar niet de publieke WAN. Let wel dat de makers van de controlepanelen (en dus ook wijzelf) een clusteroplossing bij hun producten niet officieel ondersteunen.
     
  • Wanneer je twee servers in een colocatie gebruikt en twee aparte netwerkadapters tot je beschikking hebt en alleen het private network is onbereikbaar, maar niet de publieke WAN.

Bij VPS'en met een controlepaneel staat de webserver en databaseserver altijd op dezelfde VPS en zijn deze ook bereikbaar via het publieke IP. Stel dat je daar een master-slave setup voor gebruikt, dan kun je in situaties waar enkel het private network onbereikbaar is en er geen routing probleem is, het publieke network gebruiken om een heartbeat check uit te voeren. In het geval van een colocatie is dit ook mogelijk, door een extra fysieke netwerkadapter te gebruiken.

MaxScale heeft de bijzonder handige eigenschap dat je een script in werking kunt laten treden wanneer een specifiek event zich voordoet. Deze eigenschap kun je gebruiken om de gevolgen van een split-brain-situatie in bovenstaande scenario's te voorkomen. Dit doe je door een serie aan controles uit te voeren bij een master down-event. Stelt het script vast dat het publieke IP beschikbaar is, maar niet het private IP, dan zet je MariaDB automatisch uit op de slave-VPS.

Voer onderstaande stappen uit als root-user en enkel op je slave-VPS tenzij anders aangegeven.

 

Stap 1

Maak eerst het script, een logbestand, en de benodigde directories aan (je bent vrij andere directories / bestandsnamen te gebruiken):

mkdir /var/log/failover/
mkdir /etc/failover/
touch /var/log/failover/failover.log
touch /etc/failover/failover.sh

 

Stap 2

De rechten staan standaard ingesteld voor de root-user. MaxScale heeft echter volledige rechten nodig tot deze bestanden. Pas daarom nu eerst de rechten aan (-R staat voor recursive en zorgt dat alle bestanden en subdirectories meegenomen worden):

chown -R maxscale:maxscale /var/log/failover
chown -R maxscale:maxscale /etc/failover/
chmod -R 744 /var/log/failover/
chmod -R 744 /etc/failover/

 

Stap 3

Open je MaxScale-configuratie:

nano /etc/maxscale.cnf

 

Stap 4

Voeg de volgende twee regels toe aan het [MariaDB-Monitor] deel:

events=master_down
script=/etc/failover/failover.sh initiator=$INITIATOR event=$EVENT
  • events: Geeft aan bij welke events het script wordt uitgevoerd. In dit geval laten wij het script triggeren bij een master_down event. Alle andere events die je kunt gebruiken vind je op deze pagina onder Script events.
  • scripts: Verwijst naar je script directory
    • initiator: Geeft je informatie over de VPS die down gaat. De output van $INITIATOR ziet er uit als: initiator=[192.168.1.1]:3306
    • event: Geeft aan of er een master_down event heeft plaatsgevonden

Het eindresultaat ziet er dan ongeveer als volgt uit:

[MariaDB-Monitor]
type=monitor
module=mariadbmon
servers=server1, server2
user=slave
passwd=D8FB67994030F6D8FFEAB1D69E384B84
monitor_interval=2000
events=master_down
script=/etc/failover/failover.sh initiator=$INITIATOR event=$EVENT
auto_failover=true
auto_rejoin=true

Sla de wijzigingen op en sluit nano af (ctrl + x > y > enter).


 

Stap 5

Maxscale heeft geen rechten om MariaDB stop te zetten (dit richt je in stap 8 in). Daarom geven we maxscale toestemming om met root-rechten MariaDB te stoppen (om veiligheidsredenen niet meer dan dat). Open het sudoers-bestand als volgt:

visudo

 

Stap 6

Voeg de volgende inhoud toe op een lege plek. Om het overzicht te bewaren raden wij aan dit onder de andere Cmnd_Alias commando's toe te voegen.

Visudo opent standaard in vi. Mocht je zelf nano gebruiken en niet bekend met vi zijn, druk dan eerst op i. Je ziet dan dat onderaan --insert staat. Dit betekent dat je tekst kunt toevoegen.

## Allows maxscale to shut down MariaDB.
Cmnd_Alias SPLITBRAIN = /usr/bin/systemctl stop mariadb.service
Defaults!SPLITBRAIN !requiretty
maxscale ALL=(root) NOPASSWD: SPLITBRAIN

Druk om de wijzigingen op te slaan achtereenvolgens op de toestsen Esc > :wq! > enter.


 

Stap 7

Installeer netcat (als het nog niet op je VPS'en staat):

yum -y install nc

 

Stap 8

Open het script failover.sh:

nano /etc/failover/failover.sh

 

Stap 9

Voeg onderstaande inhoud toe aan het bestand en sla de wijzigingen op (ctl + x > y > enter). Onder de code volgt een toelichting van de volledige inhoud en waarom specifiek deze aanpak gebruikt wordt.

#!/bin/bash

TIMEOUT_SECONDS=2
HOST=192.168.1.1
HOST1=136.144.204.28
HOST2=8.8.8.8
PORT=80
PORT1=3306
PORT2=443
LOG=/var/log/failover/failover.log

#Checks if the predefined port is reachable on the private LAN of the master. 
#This first test is strictly for error reporting purposes (0=yes, 1=no)
nc -w $TIMEOUT_SECONDS $HOST $PORT </dev/null;
NC=$?

#checks if the SQL port is reachable on the public WAN (0=yes, 1=no)
nc -w $TIMEOUT_SECONDS $HOST1 $PORT1 </dev/null;
NC1=$?

#checks if Google can be reached (0=yes, 1=no)
nc -w $TIMEOUT_SECONDS $HOST2 $PORT2 </dev/null;
NC2=$?

if [ $NC -eq 1 ]
then
  PLAN="Private network status: UNAVAILABLE! Current master at $initiator cannot be reached over port $PORT. Netcat returned $NC"
else
  PLAN="Private network status: ONLINE! Master down event most likely caused by human error."
fi

if [ $NC2 -eq 1 ]
then
  WAN="Slave WAN is down. Netcat Google test returned $NC2" 
  echo "$WAN" >> $LOG
else
  WAN="Slave WAN is up. Netcat Google test returned $NC2"
  echo "$WAN" >> $LOG
fi

if [ $NC1 -eq 0 ]
then
  sudo /usr/bin/systemctl stop mariadb.service
  echo "** $(date): *** $event event from current master at $initiator ***" >> $LOG 
  echo "$PLAN" >> $LOG
  echo "SQL status: ONLINE! Public SQL port $PORT1 on current master at $HOST1 available. Netcat returned $NC1" >> $LOG
  echo "MARIADB HAS BEEN SHUT DOWN TO PREVENT SPLIT-BRAIN!" >> $LOG
  echo "**********************************************************************" >> $LOG
fi
Toelichting code

De code:

  • TIMEOUT: Aantal seconden waarna netcat stopt met proberen te verbinden.
  • HOST: Het private network IP-adres van je master-VPS.
  • HOST1: Het publieke WAN IP-adres van je master-VPS.
  • HOST2: Google's publieke IP-adres
  • PORT: Een willekeurige port die bereikbaar is op het private network van de VPS. Je kunt er een kiezen uit het lijstje dat je ziet met het commando netstat -tulpen | less.
  • PORT1: De SQL-poort, in dit geval 3306
  • PORT2: De Webserver-poort 443
  • LOG: De locatie van de logfile waar je de bevindingen en acties van dit script bijhoudt.
  • nc -w $TIMEOUT_SECONDS $HOST $PORT </dev/null; De syntax houdt punt voor punt het volgende in:
    • nc Start van het netcat-commando
    • -w Laat een timeout optreden als netcat geen response krijgt
    • $TIMEOUT_SECONDS Het aantal seconden waarna een timeout optreed. Normaliter verbindt netcat in minder dan 0.1 seconden. Met twee seconden geef je het dan ook meer dan genoeg tijd.
    • $HOST Het IP-adres dat getest wordt
    • $PORT De poort die getest wordt op het $HOST IP-adres
    • </dev/null Normaal gesproken houdt netcat een succesvolle verbinding open tot je hem afbreekt. Door deze toevoeging schrijf je het resultaat weg naar het </dev/null device  zorgt ervoor dat netcat de verbinding niet actief houdt. Die verdwijnt
    • ; sluit het commando af
  • NC=$? : Geeft een 0 terug als netcat kan verbinden op het opgegeven IP-adres en poortnummer, of een 1 als dat niet lukt.
  • if [ $NC -eq 1 ] .... fi: De slave-VPs test of het private network van de master bereikbaar is en schrijft het resultaat weg in de variabele $PLAN, zie toelichting onder 'Waarom deze aanpak?'
  • if [ $NC2 -eq 1 ] .... fi: De slave-VPS test of Google bereikbaar is en schrijt het resultaat weg in de log, zie toelichting onder "Waarom deze aanpak?"
  • if [ $NC1 -eq 0 ] .... fi: De slave-VPS test of de SQL-poort van de master VPS bereikbaar is, zo ja, dan stopt de slave-VPS zijn eigen MariaDB-service en schrijft in het logbestand ($LOG) de datum, de resultaten van de eerste test, de melding dat de master bereikbaar is, en dat MariaDB zichzelf heeft uigezet op de slave-VPS

Waarom deze aanpak?

Wanneer de master-VPS down gaat wordt een aantal controles uitgevoert die de verbinding test en het troubleshooten eenvoudig maakt.

  • Je test een willekeurige (niet SQL) poort op het private network IP-adres van de master, om vast te stellen of het private network bereikbaar is of niet.
  • Het maakt voor het wel of niet uitschakelen van je server niet uit of de ingestelde port op het private network aan of uit staat. Er is namelijk een master_down event dus een failover wordt hoe dan ook gestart. De bereikbaarheid van het private network wordt enkel getest voor logging / troubleshooting doeleinden.
  • De Google-test dient om vast te stellen of je public WAN van je slave nog bereikbaar is. Dit is ook voor troubleshooting en kun je eventueel weglaten.
  • Is de publieke WAN bereikbaar, dan wordt MariaDB uitgezet op de slave. Het is dan duidelijk dat de master nog steeds queries kan accepteren. Zet dit script wel tijdelijk uit (door het uit te commenten en MaxScale te herstarten) wanneer je voor onderhoud je SQL-master tijdelijk offline haalt.

 

Daarmee zijn we aan het eind van dit artikel gekomen. Je bent nu bekend met wat split-brain inhoud en dat je in zeer specifieke gevallen scripts kunt inzetten om VPS'en bijvoorbeeld automatisch offline te halen.

Mocht je aan de hand van dit artikel nog vragen hebben, aarzel dan niet om onze supportafdeling te benaderen. Je kunt hen bereiken via de knop 'Neem contact op' onderaan deze pagina.

Wil je dit artikel met andere gebruikers bespreken, laat dan vooral een bericht achter onder 'Reacties'.

Heb je een goed idee?

Stuur jouw idee in! Met genoeg stemmen komt jouw idee op onze wishlist!

Heeft dit artikel je geholpen?

Maak een account aan of log in om een beoordeling achter te laten.

Reacties

Maak een account aan of log in om een reactie te plaatsen.

Kom je er niet uit?

Ontvang persoonlijke hulp van onze supporters

Neem contact op