Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Inledning

För en tid sedan fick jag i uppdrag att utveckla ett failover-kluster för PostgreSQL, som arbetar i flera datacenter anslutna med optisk fiber inom en stad och kan motstå ett fel (till exempel blackout) i ett datacenter. Som programvaran som ansvarar för feltolerans valde jag Pacemakereftersom detta är den officiella lösningen från RedHat för att skapa failover-kluster. Det är bra eftersom RedHat ger stöd för det, och eftersom denna lösning är universell (modulär). Med dess hjälp kommer det att vara möjligt att säkerställa feltolerans inte bara för PostgreSQL, utan även för andra tjänster, antingen genom att använda standardmoduler eller skapa dem för specifika behov.

Detta beslut väckte en rimlig fråga: hur feltolerant kommer ett failover-kluster att vara? För att undersöka detta utvecklade jag en testbänk som simulerar olika fel på klusternoderna, väntar på att tjänsten ska återställas, återställer den misslyckade noden och fortsätter testa i en loop. Detta projekt hette ursprungligen hapgsql, men med tiden blev jag uttråkad med namnet, som bara hade en vokal. Därför började jag ringa feltoleranta databaser (och flytande IP som pekar på dem) krogan (en karaktär från ett datorspel där alla viktiga organ dupliceras), och noder, kluster och själva projektet är tuchanka (planeten där krogans bor).

Nu har ledningen tillåtit öppna projektet för öppen källkod under MIT-licensen. README kommer snart att översättas till engelska (eftersom det förväntas att huvudkonsumenterna kommer att vara Pacemaker och PostgreSQL-utvecklare), och jag bestämde mig för att presentera den gamla ryska versionen av README (delvis) i form av denna artikel.

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Kluster distribueras på virtuella maskiner VirtualBox. Totalt kommer 12 virtuella maskiner (36GiB totalt) att distribueras, vilka bildar 4 feltoleranta kluster (olika alternativ). De två första klustren består av två PostgreSQL-servrar, som finns i olika datacenter, och en gemensam server Vittne c kvorumanordning (hostas på en billig virtuell maskin i ett tredje datacenter), vilket löser osäkerhet 50% / 50%, ger din röst till ett av partierna. Tredje klustret i tre datacenter: en master, två slavar, nr kvorumanordning. Det fjärde klustret består av fyra PostgreSQL-servrar, två per datacenter: en master, resten repliker och använder även Vittne c kvorumanordning. Den fjärde kan stå emot fel på två servrar eller ett datacenter. Denna lösning kan skalas till ett större antal repliker vid behov.

Exakt tidsservice ntpd även omkonfigurerad för feltolerans, men den använder själva metoden ntpd (föräldralöst läge). Delad server Vittne fungerar som en central NTP-server som distribuerar sin tid till alla kluster och synkroniserar därigenom alla servrar med varandra. Om Vittne misslyckas eller blir isolerad, kommer en av klusterservrarna (inom klustret) att börja fördela sin tid. Extra caching HTTP-proxy också upphöjd till Vittne, med dess hjälp har andra virtuella maskiner tillgång till Yum-förråd. I verkligheten kommer tjänster som exakt tid och proxyservrar med största sannolikhet att finnas på dedikerade servrar, men i montern finns de på Vittne bara för att spara antalet virtuella maskiner och utrymme.

versioner

v0. Fungerar med CentOS 7 och PostgreSQL 11 på VirtualBox 6.1.

Klusterstruktur

Alla kluster är designade för att vara placerade i flera datacenter, kombinerade till ett platt nätverk och måste motstå fel eller nätverksisolering av ett enda datacenter. Det är därför är omöjligt använda för skydd mot delad hjärna standard Pacemaker-teknik kallas STONITH (Skjut den andra noden i huvudet) eller stängsel. Dess väsen: om noderna i klustret börjar misstänka att något är fel med någon nod, den inte svarar eller beter sig felaktigt, stänger de av den med tvång via "externa" enheter, till exempel ett IPMI- eller UPS-kontrollkort . Men detta kommer bara att fungera i de fall där IPMI- eller UPS-servern fortsätter att fungera i händelse av ett enda fel. Här planerar vi att skydda mot ett mycket mer katastrofalt fel, när hela datacentret går sönder (till exempel tappar ström). Och med en sådan vägran, allt stonith-enheter (IPMI, UPS, etc.) kommer inte heller att fungera.

Istället bygger systemet på idén om kvorum. Alla noder har en röst, och bara de som kan se mer än hälften av alla noder kan fungera. Denna kvantitet "halv + 1" kallas kvorum. Om kvorum inte uppnås, så beslutar noden att den är i nätverksisolering och måste stänga av sina resurser, d.v.s. det här är vad det är skydd med delad hjärna. Om programvaran som är ansvarig för detta beteende inte fungerar måste en vakthund, till exempel baserad på IPMI, fungera.

Om antalet noder är jämnt (ett kluster i två datacenter) kan så kallad osäkerhet uppstå 50% / 50% (femtio femtio) när nätverksisolering delar klustret exakt på mitten. Därför lägger vi till för ett jämnt antal noder kvorumanordning är en krävande demon som kan lanseras på den billigaste virtuella maskinen i ett tredje datacenter. Han ger sin röst till ett av segmenten (som han ser), och löser därmed 50%/50% osäkerheten. Jag namngav servern där kvorumenheten kommer att startas Vittne (terminologi från repmgr, jag gillade det).

Resurser kan flyttas från plats till plats, till exempel från felaktiga servrar till friska, eller på kommando av systemadministratörer. Så att kunderna vet var de resurser de behöver finns (var ska de ansluta?), flytande IP (flytande IP). Det här är IP-adresser som Pacemaker kan flytta runt på noder (allt är på ett platt nätverk). Var och en av dem symboliserar en resurs (tjänst) och kommer att finnas där du behöver ansluta för att få tillgång till denna tjänst (i vårt fall en databas).

Tuchanka1 (krets med komprimering)

Struktur

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Tanken var att vi har många små databaser med låg belastning, för vilka det är olönsamt att upprätthålla en dedikerad slavserver i hot standby-läge för skrivskyddade transaktioner (det finns inget behov av ett sådant slöseri med resurser).

Varje datacenter har en server. Varje server har två PostgreSQL-instanser (i PostgreSQL-terminologi kallas de kluster, men för att undvika förvirring kommer jag att kalla dem instanser (i analogi med andra databaser), och jag kallar bara Pacemaker-kluster för kluster). En instans fungerar i masterläge, och endast den tillhandahåller tjänster (endast flytande IP leder till den). Den andra instansen fungerar som en slav för det andra datacentret och tillhandahåller tjänster endast om dess master misslyckas. Eftersom för det mesta bara en instans av två (mastern) kommer att tillhandahålla tjänster (utföra förfrågningar), är alla serverresurser optimerade för mastern (minne allokeras för shared_buffers-cachen, etc.), men så att den andra instansen har också tillräckligt med resurser (om än för suboptimal drift genom filsystemets cache) i händelse av fel på ett av datacentren. Slaven tillhandahåller inte tjänster (utför inte skrivskyddade förfrågningar) under normal drift av klustret, så att det inte finns något krig om resurser med mastern på samma maskin.

I fallet med två noder är feltolerans endast möjlig med asynkron replikering, eftersom med synkron replikering kommer ett fel hos en slav att leda till att mastern stannar.

Underlåtenhet att bevittna

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Underlåtenhet att bevittna (kvorumanordning) Jag kommer bara att överväga Tuchanka1-klustret, med alla andra kommer det att vara samma historia. Om vittnet misslyckas kommer ingenting att förändras i klusterstrukturen, allt kommer att fortsätta att fungera på samma sätt som det gjorde. Men kvorumet kommer att bli 2 av 3, och därför kommer varje efterföljande misslyckande att vara ödesdigert för klustret. Det kommer fortfarande att behöva fixas omgående.

Tuchanka1 vägran

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Fel i ett av datacenterna för Tuchanka1. I detta fall Vittne avger sin röst till en andra nod i ett andra datacenter. Där förvandlas den tidigare slaven till en master, som ett resultat av att båda masters arbetar på samma server och båda deras flytande IP-adresser pekar på dem.

Tuchanka2 (klassisk)

Struktur

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Klassiskt schema med två noder. Mastern arbetar på den ena, slaven på den andra. Båda kan exekvera förfrågningar (slaven är skrivskyddad), så båda pekas på float-IP: krogan2 är mastern, krogan2s1 är slaven. Både mastern och slaven kommer att ha feltolerans.

I fallet med två noder är feltolerans endast möjlig med asynkron replikering, eftersom med synkron replikering kommer fel hos slaven att leda till att mastern stannar.

Tuchanka2 vägran

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Om ett av datacenterna misslyckas Vittne röstar på den andra. På det enda fungerande datacentret kommer mastern att höjas, och båda flytande IP:erna kommer att peka på den: mastern och slaven. Naturligtvis måste instansen konfigureras på ett sådant sätt att den har tillräckligt med resurser (anslutningsgränser etc.) för att samtidigt acceptera alla anslutningar och förfrågningar från master och slav float IP. Det vill säga, under normal drift bör den ha ett tillräckligt utbud av gränser.

Tuchanka4 (många slavar)

Struktur

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Redan en annan ytterlighet. Det finns databaser som tar emot många skrivskyddade förfrågningar (ett typiskt fall av en webbplats med hög belastning). Tuchanka4 är en situation där det kan finnas tre eller fler slavar för att hantera sådana förfrågningar, men ändå inte för många. Med ett mycket stort antal slavar kommer det att vara nödvändigt att uppfinna ett hierarkiskt replikeringssystem. I minsta fall (på bilden) har vart och ett av de två datacentren två servrar, var och en med en PostgreSQL-instans.

En annan egenskap hos detta schema är att det redan är möjligt att organisera en synkron replikering. Den är konfigurerad att replikera, om möjligt, till ett annat datacenter, snarare än till en replika i samma datacenter som mastern. Mastern och varje slav pekas på av en flytande IP. Lyckligtvis, mellan slavar kommer det att vara nödvändigt att balansera förfrågningar på något sätt sql proxytill exempel på kundsidan. Olika typer av klienter kan kräva olika typer sql proxy, och bara klientutvecklare vet vem som behöver vilket. Denna funktionalitet kan implementeras antingen av en extern demon eller av ett klientbibliotek (anslutningspool), etc. Allt detta går utöver ämnet för ett failover-databaskluster (failover SQL proxy kan implementeras oberoende, tillsammans med klientens feltolerans).

Tuchanka4 vägran

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Om ett datacenter (dvs två servrar) misslyckas, röstar vittnen för det andra. Som ett resultat finns det två servrar som körs i det andra datacentret: en kör en master och master float IP pekar på den (för att ta emot läs- och skrivförfrågningar); och på den andra servern finns en slav som körs med synkron replikering, och en av slav-float-IP:erna pekar på den (för skrivskyddade förfrågningar).

Det första att notera är att inte alla slav-float-IP:er kommer att vara arbetare, utan bara en. Och för att arbeta med det korrekt kommer det att vara nödvändigt sql proxy omdirigerade alla förfrågningar till den enda kvarvarande flytande IP-adressen; och om sql proxy nej, då kan du lista alla flytande IP-slavar separerade med kommatecken i anslutnings-URL. I det här fallet med libpq anslutningen kommer att vara till den första fungerande IP-adressen, detta görs i det automatiska testsystemet. Kanske i andra bibliotek, till exempel JDBC, kommer detta inte att fungera och är nödvändigt sql proxy. Detta görs eftersom flytande IP-adresser för slavar är förbjudna att höjas samtidigt på en server, så att de är jämnt fördelade mellan slavservrar om det finns flera av dem igång.

För det andra: även i händelse av ett datacenterfel kommer synkron replikering att upprätthållas. Och även om ett sekundärt fel inträffar, det vill säga en av de två servrarna i det återstående datacentret misslyckas, kommer klustret, även om det kommer att sluta tillhandahålla tjänster, fortfarande behålla information om alla begångna transaktioner för vilka det har gett bekräftelse på bekräftelsen (det kommer ingen förlustinformation vid sekundärt fel).

Tuchanka3 (3 datacenter)

Struktur

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Detta är ett kluster för en situation där det finns tre fullt fungerande datacenter, som vart och ett har en fullt fungerande databasserver. I detta fall kvorumanordning behövs inte. Ett datacenter är bemannat av en master, de andra två är bemannade av slavar. Replikeringen är synkron, skriv ANY (slave1, slave2), det vill säga, klienten kommer att få en commit-bekräftelse när någon av slavarna är den första att svara att han har accepterat commit. Resurser indikeras med en flytande IP för mastern och två för slavar. Till skillnad från Tuchanka4 är alla tre flytande IP-adresser feltoleranta. För att balansera skrivskyddade SQL-frågor kan du använda sql proxy (med separat feltolerans), eller tilldela en slav-float-IP till hälften av klienterna och den andra hälften till den andra.

Tuchanka3 vägran

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Om ett av datacentren går sönder finns två kvar. I den ena höjs master- och float-IP från mastern, i den andra - slav- och båda slav-float-IP:erna (instansen måste ha en dubbel reserv av resurser för att acceptera alla anslutningar från båda slav-float-IP:erna). Synkron replikering mellan masters och slavar. Dessutom kommer klustret att spara information om begångna och bekräftade transaktioner (det kommer ingen förlust av information) i händelse av förstörelse av två datacenter (om de inte förstörs samtidigt).

Jag bestämde mig för att inte inkludera en detaljerad beskrivning av filstrukturen och distributionen. Alla som vill leka kan läsa allt i README. Jag ger bara en beskrivning av automatiserad testning.

Automatiskt testsystem

För att testa feltoleransen för kluster genom att simulera olika fel har ett automatiskt testsystem skapats. Lanserades av manus test/failure. Skriptet kan ta som parametrar antalet kluster som du vill testa. Till exempel detta kommando:

test/failure 2 3

kommer bara att testa det andra och tredje klustret. Om parametrar inte anges kommer alla kluster att testas. Alla kluster testas parallellt och resultatet visas i tmux-panelen. Tmux använder en dedikerad tmux-server, så skriptet kan köras från under standard tmux, vilket resulterar i en kapslad tmux. Jag rekommenderar att du använder terminalen i ett stort fönster och med ett litet typsnitt. Innan testet börjar rullas alla virtuella maskiner tillbaka till en ögonblicksbild när skriptet slutförs setup.

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Terminalen är indelad i kolumner enligt antalet kluster som testas; som standard (i skärmdumpen) finns det fyra. Jag kommer att beskriva innehållet i kolumnerna med exemplet Tuchanka2. Panelerna på skärmdumpen är numrerade:

  1. Teststatistik visas här. Kolumner:
    • misslyckande — namnet på testet (funktion i skriptet) som emulerar felet.
    • Reaktionen — aritmetisk medeltid i sekunder under vilken klustret återställde sin funktionalitet. Det mäts från början av skriptet som emulerar ett fel till det ögonblick då klustret återställer sin funktionalitet och kan fortsätta tillhandahålla tjänster. Om tiden är mycket kort, till exempel sex sekunder (detta händer i kluster med flera slavar (Tuchanka3 och Tuchanka4)), betyder det att felet var på den asynkrona slaven och inte påverkade prestandan på något sätt; det fanns inga klustertillståndsomkopplare.
    • avvikelse — visar spridningen (noggrannheten) för värdet Reaktionen med standardavvikelsemetoden.
    • räkna — hur många gånger detta test utfördes.
  2. En kort logg låter dig utvärdera vad klustret för närvarande gör. Iterationsnumret (testet), tidsstämpeln och namnet på operationen visas. Att köra för länge (> 5 minuter) indikerar ett problem.
  3. hjärta (hjärta) - aktuell tid. För visuell bedömning av prestanda mästare Den aktuella tiden skrivs hela tiden till sin tabell med hjälp av float IP-mastern. Om det lyckas visas resultatet i den här panelen.
  4. slå (puls) - "aktuell tid", som tidigare spelades in av manuset hjärta att bemästra, läs nu från slav via dess flytande IP. Låter dig visuellt bedöma prestanda för slaven och replikeringen. I Tuchanka1 finns det inga slavar med flytande IP (inga slavar som tillhandahåller tjänster), men det finns två instanser (DB), så det kommer inte att visas här slåOch hjärta andra instans.
  5. Övervaka klustrets hälsa med hjälp av verktyget pcs mon. Visar struktur, fördelning av resurser över noder och annan användbar information.
  6. Systemövervakning från varje virtuell maskin i klustret visas här. Det kan finnas fler sådana paneler beroende på hur många virtuella maskiner klustret har. Två grafer CPU-laddning (virtuella maskiner har två processorer), virtuell maskinnamn, Systembelastning (som kallas Load Average eftersom det är medelvärde över 5, 10 och 15 minuter), processdata och minnesallokering.
  7. Spår av skriptet som utför testning. I händelse av ett fel - ett plötsligt driftsavbrott eller en oändlig väntecykel - här kan du se orsaken till detta beteende.

Testning utförs i två steg. Först går skriptet igenom alla typer av tester och väljer slumpmässigt en virtuell maskin som det här testet ska tillämpas på. Sedan utförs en oändlig cykel av tester, de virtuella maskinerna och felet väljs ut slumpmässigt varje gång. Plötsligt avbrytande av testskriptet (nedre panelen) eller en oändlig slinga av väntan på något (> 5 minuters exekveringstid för en operation, detta kan ses i spåret) indikerar att några av testerna på detta kluster har misslyckats.

Varje test består av följande operationer:

  1. Starta en funktion som emulerar ett fel.
  2. Redo? — väntar på att klustret ska återställas (när alla tjänster tillhandahålls).
  3. Visar tidsgränsen för klusteråterställning (Reaktionen).
  4. Fast — klustret håller på att "repareras". Därefter bör den återgå till fullt funktionsdugligt tillstånd och vara redo för nästa fel.

Här är en lista över tester med en beskrivning av vad de gör:

  • ForkBomb: Skapar "Out of memory" med hjälp av en gaffelbomb.
  • OutOfSpace: Hårddisken är full. Men testet är ganska symboliskt, med den obetydliga belastningen som skapas under testning, så misslyckas PostgreSQL vanligtvis inte när hårddisken är full.
  • Postgres-KILL: dödar PostgreSQL med kommandot killall -KILL postgres.
  • Postgres-STOPP: hänger PostgreSQL-kommandot killall -STOP postgres.
  • Stäng av: "avaktiverar" den virtuella maskinen med kommandot VBoxManage controlvm "виртуалка" poweroff.
  • Återställa: överbelasta den virtuella maskinen med kommandot VBoxManage controlvm "виртуалка" reset.
  • SBD-STOPP: avbryter SBD-demonen med kommandot killall -STOP sbd.
  • Stänga av: skickar ett kommando till den virtuella maskinen via SSH systemctl poweroff, stängs systemet av graciöst.
  • Ta bort länk: nätverksisolering, kommando VBoxManage controlvm "виртуалка" setlinkstate1 off.

Slutför testning antingen med standard tmux-kommandot "kill-window" Ctrl-b &, eller kommandot "detach-client". Ctrl-b d: vid denna tidpunkt slutar testningen, tmux stängs, virtuella maskiner stängs av.

Problem identifierade under testning

  • I detta ögonblick vakthund demon sbd fungerar på att stoppa observerade demoner, men inte frysa dem. Och, som ett resultat, endast fel som leder till frysning Corosync и Pacemaker, men inte hängande sbd. För kontroll Corosync har redan PR#83 (på GitHub kl sbd), accepterad till tråden Master. De lovade (i PR#83) att det skulle finnas något liknande för Pacemaker, jag hoppas att genom Redhat 8 ska göra. Men sådana "fel" är spekulativa och kan enkelt simuleras på konstgjord väg med hjälp av t.ex. killall -STOP corosync, men aldrig träffas i verkligheten.

  • У Pacemaker i versionen för 7 CentOS felaktigt inställd sync_timeout у kvorumanordning, som ett resultat om en nod misslyckades, med viss sannolikhet startade även den andra noden om, dit befälhavaren skulle flytta. Botad genom utvidgningen sync_timeout у kvorumanordning under driftsättning (i script setup/setup1). Detta tillägg accepterades inte av utvecklarna Pacemaker, istället lovade de att designa om infrastrukturen på ett sådant sätt (vid någon ospecificerad framtid) att denna timeout skulle beräknas automatiskt.

  • Om databaskonfigurationen anger det LC_MESSAGES (sms) Unicode kan användas, t.ex. ru_RU.UTF-8, sedan vid start postgres i en miljö där lokalen inte är UTF-8, säg i en tom miljö (här pacemaker+pgsqlms(paf) springer postgres), Den där loggen kommer att innehålla frågetecken istället för UTF-8-bokstäver. PostgreSQL-utvecklarna har inte kommit överens om vad de ska göra i det här fallet. Det kostar, du måste installera LC_MESSAGES=en_US.UTF-8 när du konfigurerar (skapar) en databasinstans.

  • Om wal_receiver_timeout är inställd (som standard är det 60s), så under PostgreSQL-STOP-testet på mastern i tuchanka3- och tuchanka4-klustren replikering återansluter inte till den nya mastern. Replikering där är synkron, så inte bara slaven stannar utan även den nya mastern. Löser sig genom att ställa in wal_receiver_timeout=0 när du konfigurerar PostgreSQL.

  • Ibland såg jag att replikeringen fryser i PostgreSQL i ForkBomb-testet (minnesspill). Efter ForkBomb kanske slavar inte återansluter till den nya mastern. Jag har bara stött på detta i tuchanka3- och tuchanka4-klustren, där mastern frös på grund av synkron replikering. Problemet gick över av sig självt efter en lång tid (cirka två timmar). Mer forskning behövs för att rätta till detta. Symtomen liknar den tidigare buggen, som orsakas av en annan orsak, men med samma konsekvenser.

Krogan bild tagen från avvikande Art med tillstånd av författaren:

Modellera failover-kluster baserade på PostgreSQL och Pacemaker

Källa: will.com

Lägg en kommentar