Introduktion
För en tid sedan fick jag i uppdrag att utveckla en hög tillgÀnglighetskluster för , som fungerar i flera datacentra, kopplade med fiber inom samma stad, och som kan klara av att ett datacenter gÄr nere (till exempel strömavbrott). Som programvara för hög tillgÀnglighet valde jag , eftersom detta Àr den officiella lösningen frÄn RedHat för att skapa hög tillgÀngliga kluster. Det Àr bra eftersom RedHat ger stöd för det, och det Àr en universell (modulÀr) lösning. Med hjÀlp av detta kan hög tillgÀnglighet sÀkerstÀllas för inte bara PostgreSQL, utan ocksÄ andra tjÀnster, antingen genom att anvÀnda standardmoduler eller genom att skapa dem för specifika behov.
Det uppstod en rimlig frĂ„ga om detta lösning: hur hög tillgĂ€nglighet kommer det hög tillgĂ€nglighetsklustret att ha? För att undersöka detta utvecklade jag en testmiljö som imiterar olika fel pĂ„ klusternoderna, vĂ€ntar pĂ„ Ă„terstĂ€llande av funktionaliteten, Ă„terstĂ€ller den misslyckade noden och fortsĂ€tter testningen i cykler. Ursprungligen kallades detta projekt hapgsql, men med tiden blev jag trött pĂ„ namnet som bara hade en vokal. DĂ€rför började jag kalla hög tillgĂ€ngliga databaser (och den flytande IP som pekar pĂ„ dem) krogan (en karaktĂ€r frĂ„n ett datorspel vars alla viktiga organ Ă€r duplicerade), och noder, kluster och sjĂ€lva projektet â tuchanka (planeten dĂ€r krogans bor).
Nu har ledningen beslutat att . README kommer snart att översÀttas till engelska (eftersom det förvÀntas att huvudkonsumenterna kommer att vara utvecklare av Pacemaker och PostgreSQL), och den gamla ryska varianten av README har jag beslutat att utforma (delvis) i form av denna artikel.

Klustren sÀtts upp pÄ virtuella maskiner . Totalt kommer 12 virtuella maskiner att sÀttas upp (totalt 36 GiB), som bildar 4 hög tillgÀnglighetskluster (olika varianter). De första tvÄ klustren bestÄr av tvÄ PostgreSQL-servrar, som Àr placerade i olika datacentra, och en gemensam server witness c quorum device (placerad pÄ en billig virtuell maskin i det tredje datacentret), som löser osÀkerheten 50%/50%, genom att ge sin röst till en av parterna. Det tredje klustret bestÄr av tre datacenter: en master och tvÄ slavservrar, utan quorum device. Den fjÀrde klustret bestÄr av fyra PostgreSQL-servrar, tvÄ per datacenter: en master och resten repliker, och anvÀnder ocksÄ witness c quorum device. FjÀrde klustret klarar av att förlora tvÄ servrar eller ett datacenter. Denna lösning kan, vid behov, skalas upp till fler repliker.
TjÀnst för exakt tid har ocksÄ konfigurerats för hög tillgÀnglighet, men dÀr anvÀnds metoden för ntpd (orphan mode). Den gemensamma servern witness har en central roll som NTP-server, som delar sin tid med alla kluster och pÄ sÄ sÀtt synkroniserar alla servrar med varandra. Om witness den gÄr sönder eller blir isolerad, dÄ börjar en av klusterservrarna (inom klustret) dela sin tid. En hjÀlpkassande HTTP-proxy Àr ocksÄ upprÀttad, witnessmed hjÀlp av denna har de andra virtuella maskinerna tillgÄng till Yum-repositorier. I verkligheten kommer sÄdana tjÀnster som exakt tid och proxy förmodligen att hostas pÄ dedikerade servrar, men i detta stand har de placerats pÄ witness endast för att spara pÄ antalet virtuella maskiner och utrymme.
Versioner
v0. Fungerar med CentOS 7 och PostgreSQL 11 pÄ VirtualBox 6.1.
Konstruktur för kluster
Alla kluster Àr avsedda för distribution i flera datacenter, sammanlÀnkade i ett enda platt nÀtverk och ska klara av ett fel eller nÀtverksisolering av ett datacenter. DÀrför Àr omöjligt anvÀnds för skydd mot split-brain standardteknologin Pacemaker, som kallas STONITH (Shoot The Other Node In The Head) eller fencing. Dess kÀrna: om noderna i klustret börjar misstÀnka att nÄgot Àr fel med en nod, den svarar inte eller beter sig felaktigt, sÄ stÀnger de av den tvÄngsmÀssigt via "externa" enheter, till exempel en IPMI-kontrollkort eller UPS. Men detta fungerar bara i fall dÀr vid enstaka serverfel fortsÀtter IPMI eller UPS att fungera. HÀr planeras skydd mot betydligt mer katastrofalt fel, nÀr hela datacentret gÄr ner (till exempel strömavbrott). Vid sÄdan avbrott kommer alla stonith-enheter (IPMI, UPS osv.) heller inte fungera.
IstÀllet bygger systemet pÄ idén om majoritet. Alla noder har en röst, och endast de som ser mer Àn hÀlften av alla noder kan arbeta. Detta antal "hÀlften+1" kallas kvorum. Om majoriteten inte uppnÄs anser noden att den Àr i nÀtverksisolering och att den mÄste stÀnga av sina resurser, dvs. det Àr sÄ hÀr skydd mot split-brain. Om mjukvaran som ansvarar för detta beteende inte fungerar, bör en watchdog aktiveras, till exempel baserat pÄ IPMI.
Om antalet noder Ă€r jĂ€mnt (klustret finns i tvĂ„ datacenter) kan det uppstĂ„ sĂ„ kallad osĂ€kerhet 50%/50% (fifty-fifty), nĂ€r nĂ€tverksisoleringen delar klustret i exakt tvĂ„ halvor. DĂ€rför lĂ€ggs det till ett jĂ€mnt antal noder quorum device â en resurskrĂ€vande demon som kan köras pĂ„ den billigaste virtuella maskinen i det tredje datacentret. Den ger sin röst till en av segmenten (som den ser) och dĂ€rmed löser 50%/50% osĂ€kerheten. Servern dĂ€r quorum-enheten kommer att köras har jag kallat witness (terminologi frĂ„n repmgr, jag gillade den).
Resurser kan flyttas runt, till exempel frÄn trasiga servrar till fungerande, eller pÄ begÀran av systemadministratörer. För att kunder ska veta var deras nödvÀndiga resurser finns (var de ska ansluta?), anvÀnds flytande IP (float IP). Det Àr IP-adresser som Pacemaker kan flytta mellan noder (allt finns i ett platt nÀtverk). Varje av dem symboliserar en resurs (tjÀnst) och kommer att befinna sig dÀr man behöver ansluta för att fÄ tillgÄng till denna tjÀnst (i vÄrt fall DB).
Tuchanka1 (schema med komprimering)
Struktur

Idén var att vi har mÄnga smÄ databaser med lÄg belastning, för vilka det inte Àr lönsamt att ha en dedikerad slavserver i hot standby-lÀge för read only-transaktioner (ingen anledning till sÄdan resursÄtergÄng).
I varje datacenter finns en server. PÄ varje server finns det tvÄ instanser av PostgreSQL (i PostgreSQL-termer kallas de kluster, men för att undvika förvirring kommer jag att kalla dem instanser (i analogi med andra databaser), och kluster kommer jag bara att kalla kluster för Pacemaker). En instans fungerar i masterlÀge, och endast den tillhandahÄller tjÀnster (det Àr bara den som har float IP). Den andra instansen fungerar som en slav för det andra datacentret och kommer endast att erbjuda tjÀnster om dess master gÄr ner. Eftersom det under större delen av tiden bara Àr en instans av de tvÄ (master) som tillhandahÄller tjÀnster (bearbetar förfrÄgningar) optimeras alla serverresurser för master (minne avsÀtts för cache av shared_buffers etc.), men sÄ att det ocksÄ finns tillrÀckligt med resurser för den andra instansen (om Àn för en suboptimal drift via filsystemets cache) i hÀndelse av att ett av datacentren slutar fungera. Slaven tillhandahÄller inga tjÀnster (gör inga read-only-förfrÄgningar) under normal drift av klustret för att undvika resurskonflikter med mastern pÄ samma maskin.
I fallet med tvÄ noder Àr felresiliens endast möjlig vid asynkron replikering, eftersom en synkroniserad fel pÄ slaven skulle leda till att mastern stannar.
Fel witness

Fel witness (quorum device) jag kommer endast att övervÀga för klustret Tuchanka1, alla andra kommer att ha samma historia. Vid ett fel pÄ witness i klustrets struktur förÀndras ingenting, allt kommer att fungera som tidigare. Men avgörande röster blir 2 av 3, och dÀrför kommer varje följande fel att vara fatalt för klustret. Det mÄste fortfarande ÄtgÀrdas omedelbart.
Fel Tuchanka1

Fel pÄ ett av datacentren för Tuchanka1. I detta fall witness ger sin röst till den andra noden i det andra datacentret. DÀr förvandlas den tidigare slaven till master, vilket resulterar i att bÄda mastern arbetar pÄ en server och bÄda deras float IP pekar pÄ dem.
Tuchanka2 (klassisk)
Struktur

Klassiskt mönster med tvÄ noder. PÄ en arbetar master, pÄ den andra slav. BÄda kan behandla förfrÄgningar (slaven bara read-only), sÄ bÄda pekar pÄ float IP: krogan2 - för mastern, krogan2s1 - för slaven. Felresiliens kommer att finnas bÄde hos mastern och slaven.
I fallet med tvÄ noder Àr felresiliens endast möjlig vid asynkron replikering, eftersom en synkroniserad fel pÄ slaven skulle leda till att mastern stannar.
Fel Tuchanka2

Vid ett fel pĂ„ ett av datacentren witness röstar pĂ„ den andra. PĂ„ det enda fungerande datacentret kommer en master att sĂ€ttas upp, och bĂ„da float IP:erna â master och slav â kommer att peka pĂ„ den. SjĂ€lvklart mĂ„ste instansen konfigureras sĂ„ att den har tillrĂ€ckligt med resurser (grĂ€nser för anslutningar etc.) för att samtidigt ta emot alla anslutningar och förfrĂ„gningar frĂ„n bĂ„de master- och slavens float IP. Det vill sĂ€ga, under normal drift bör den ha ett tillrĂ€ckligt överskott av kapacitet.
Tuchanka4 (mÄnga slavar)
Struktur

Det Àr redan en annan extrem. Det finns databaser som har mycket höga read-only förfrÄgningar (ett typiskt fall för en högbelastad webbplats). 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. Vid ett mycket stort antal slavar behöver man uppfinna ett hierarkiskt replikationssystem. I det minimiella fallet (pÄ bilden) finns det tvÄ servrar i varje datacenter, med en instans av PostgreSQL pÄ varje server.
En annan funktion hos detta system Àr att man redan kan organisera en synkron replikation. Den Àr konfigurerad för att replikera, nÀr det Àr möjligt, till ett annat datacenter, snarare Àn till en replika i samma datacenter som master. BÄde master och varje slav pekar pÄ float IP. För att optimera detta bör man balansera förfrÄgningarna mellan slavar med hjÀlp av nÄgot. sql proxy, till exempel frÄn klientens sida. Olika typer av klienter kan behöva olika typer sql proxy, och endast klientutvecklarna vet vem som behöver vad. Denna funktionalitet kan implementeras antingen som en extern demon eller som en klientbibliotek (connection pool), etc. Allt detta faller utanför Àmnet för ett fel- och drift-sÀkert databaskluster (drift-sÀkerhet SQL proxy kan realiseras oberoende, tillsammans med klientens drift-sÀkerhet).
Fel i Tuchanka4

Vid fel i ett datacenter (dvs tvÄ servrar) röstar witness för den andra. Som en följd av detta fungerar tvÄ servrar i det andra datacentret: en server hanterar master och pekar pÄ master float IP (för att ta emot read-write förfrÄgningar); och pÄ den andra servern verkar en slav med synkron replikation, och pÄ den pekar ett av slavarnas float IP (för read-only förfrÄgningar).
Det första att notera Àr att arbetsfloat IP för slavar inte kommer att vara alla, bara en. Och för att kunna arbeta korrekt med det krÀvs det att sql proxy alla begÀrningar omdirigerades till den enda kvarvarande float IP; om inte sql proxy kan man lista alla float IP för slavarna med kommatecken i URL:en för anslutning. I sÄ fall kommer anslutningen att ske till den första fungerande IP:n, som implementerats i automatiseringstestningssystemet. Det kan hÀnda att det fungerar annorlunda i andra bibliotek, som JDBC, och dÄ krÀvs libpq att anslutningen kommer att ske till den första fungerande IP:n, vilket implementerats i automatiserat testningssystem. I andra bibliotek, som JDBC, kan det hÀnda att detta inte fungerar och att det krÀvs sql proxy. Detta Àr för att float IP:n för slavarna har en restriktion för att samtidigt kunna köra pÄ en server, sÄ att de fördelas jÀmnt över slavservrarna om flera Àr igÄng.
För det andra: Àven om datacentret skulle falla kommer den synkrona replikeringen att bevaras. Om en sekundÀr felaktighet uppstÄr, det vill sÀga om en av tvÄ servrar i det kvarstÄende datacentret gÄr ner, sÄ kommer klustret, Àven om det slutar erbjuda tjÀnster, fortfarande att bevara information om alla kommitterade transaktioner som det har bekrÀftat med en commit (ingen förlust av information vid sekundÀr felaktighet).
Tuchanka3 (3 datacenter)
Struktur

Detta Ă€r ett kluster för situationen nĂ€r det finns tre fullt fungerande datacenter, dĂ€r var och en har en fullt fungerande databasserver. I detta fall quorum device Ă€r inte nödvĂ€ndig. I ett datacenter finns det en master, och i de tvĂ„ andra â slavar. Replikeringen Ă€r synkron, i stil med ANY (slave1, slave2), vilket innebĂ€r att klienten fĂ„r en bekrĂ€ftelse pĂ„ commit nĂ€r nĂ„gon av slavarna först svarar att den har tagit emot commiten. Resurserna pekar pĂ„ en float IP för master och tvĂ„ för slavarna. Till skillnad frĂ„n Tuchanka4 Ă€r alla tre float IP:er Ă€r redundanta. För lastbalansering av read-only SQL-förfrĂ„gningar kan man anvĂ€nda sql proxy (med separat redundans), eller tilldela hĂ€lften av klienterna en slav float IP och den andra hĂ€lften den andra.
Fel pÄ Tuchanka3

Vid ett fel i ett av datacentren finns det fortfarande tvÄ kvar. I ett finns master och float IP frÄn master, medan det andra har en slav och bÄda slavarnas float IP (instansen bör ha dubbelt sÄ mycket resurser för att ta emot alla anslutningar frÄn bÄda slavarnas float IP). Mellan master och slav finns det synkron replikering. Klustret kommer ocksÄ att bevara information om kommitterade och bekrÀftade transaktioner (ingen förlust av information) i hÀndelse av att tvÄ datacenter förstörs (om de inte förstörs samtidigt).
Jag har valt att inte inkludera en detaljerad beskrivning av filstrukturen och distributionen. De som vill experimentera kan lÀsa allt detta i README. Jag ger bara en beskrivning av automatisk testning.
Automatisk testningssystem
För att kontrollera klusterens felbestÀndighet har ett system för automatisk testning skapats. Det körs med ett skript. test/failure. Skriptet kan ta som parametrar de nummer av kluster som du vill testa. Till exempel, det hÀr kommandot:
test/failure 2 3kommer bara att testa det andra och tredje klustret. Om inga parametrar 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 default tmux, vilket ger en inbÀddad tmux. Jag rekommenderar att anvÀnda en terminal i ett stort fönster med liten teckenstorlek. Innan testningen inleds ÄterstÀlls alla virtuella maskiner till en snapshot vid tidpunkten dÄ skriptet avslutades. setup.

Terminals Àr uppdelad i kolumner enligt antal testade kluster, som standard (i skÀrmdumpen) fyra. InnehÄllet i kolumnerna kommer jag att beskriva med exemplet Tuchanka2. Panelerna pÄ skÀrmdumpen Àr numrerade:
- HÀr visas statistiken för testerna. Kolumner:
- failure â namnet pĂ„ testet (funktionen i skriptet) som emulerar ett fel.
- reaction â det aritmetiska medelvĂ€rdet i sekunder, som klustret tog för att Ă„terfĂ„ sin funktionalitet. MĂ€ts frĂ„n början av skriptets körning, som emulerar felet, fram till det ögonblick dĂ„ klustret Ă„terfĂ„r sin funktionalitet och kan fortsĂ€tta leverera tjĂ€nster. Om tiden Ă€r mycket kort, till exempel sex sekunder (som ibland gĂ€ller kluster med flera arbetare (Tuchanka3 och Tuchanka4)), innebĂ€r det att felet intrĂ€ffade pĂ„ en asynkron arbetare och dĂ€rför inte hade nĂ„gon pĂ„verkan pĂ„ funktionaliteten, inga tillstĂ„ndsbyten i klustret skedde.
- deviation â visar spridningen (noggrannheten) av vĂ€rdet reaction med metoden "standardavvikelse".
- count â hur mĂ„nga gĂ„nger detta test har utförts.
- En kort logg ger möjlighet att bedöma vad klustret gör för nÀrvarande. Iterationsnummer (test), tidsstÀmpel och operationens namn visas. Om utförandet tar för lÄng tid (> 5 minuter) tyder det pÄ ett problem.
- heart (hjĂ€rtat) â aktuell tid. För visuell bedömning av funktionalitet mĂ€stare i hans tabell skrivs den aktuella tiden kontinuerligt med hjĂ€lp av mĂ€starens float IP. Vid framgĂ„ng visas resultatet i denna panel.
- slag (puls) â "aktuell tid", som tidigare registrerades av skriptet heart i mĂ€staren, lĂ€ses nu frĂ„n slaven genom hans float IP. Ger möjligheten att visuellt bedöma slaven och replikationens funktionalitet. I Tuchanka1 finns det inga slavar med float IP (inga slavar som erbjuder tjĂ€nster), men dĂ€r finns tvĂ„ instanser (databaser), sĂ„ hĂ€r kommer det att visas inte slag, och heart den andra instansen.
- Ăvervakning av klustrets tillstĂ„nd med hjĂ€lp av verktyg
pcs mon. Visar strukturen, resursfördelningen pĂ„ noderna och annan nyttig information. - HĂ€r visas systemövervakning frĂ„n varje virtuell maskin i klustret. Det kan finnas flera sĂ„dana paneler â sĂ„ mĂ„nga virtuella maskiner klustret har. TvĂ„ diagram CPU-belastning (med tvĂ„ processorer i varje virtuell maskin), namn pĂ„ den virtuella maskinen, Systembelastning (benĂ€mns Load Average, eftersom den Ă€r genomsnittlig över 5, 10 och 15 minuter), data om processer och minnesfördelning.
- Skriptslagning som utför tester. Vid fel â plötslig avbrott av arbetet eller oĂ€ndlig vĂ€nteloop â kan orsaken till ett sĂ„dant beteende ses hĂ€r.
Testningen genomförs i tvÄ steg. Först gÄr skriptet igenom alla typer av tester, slumpmÀssigt vÀljer en virtuell maskin till vilken detta test ska tillÀmpas. Sedan utförs en oÀndlig testcykel, dÀr virtuella maskiner och fel vÀljs slumpmÀssigt varje gÄng. Plötslig avslutning av testningsskriptet (nedre panel) eller oÀndlig vÀnteloop för nÄgot (> 5 minuter exekveringstid för en operation, vilket syns i spÄrningen) indikerar att nÄgot av testen i detta kluster har misslyckats.
Varje test bestÄr av följande operationer:
- Kör en funktion som emulerar ett fel.
- Redo? â vĂ€ntar pĂ„ att klustret ska Ă„terstĂ€llas (nĂ€r alla tjĂ€nster Ă€r tillgĂ€ngliga).
- Visar tiden för att ÄterstÀlla klustret (reaction).
- Fix â klustret "repareras". Efter det ska det Ă„tergĂ„ till ett helt fungerande 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 fork-bomb.
- OutOfSpace: fyller disken. Men testet Àr snarare symboliskt, med den begrÀnsade belastning som skapas vid testning, för vid diskfullhet uppstÄr vanligtvis inget avbrott i PostgreSQL.
- Postgres-KILL: dödar PostgreSQL med kommandot
killall -KILL postgres. - Postgres-STOP: hÀnger PostgreSQL med kommandot
killall -STOP postgres. - PowerOff: "stÀnger av" virtuella maskinen med kommandot
VBoxManage controlvm "virtuell maskin" poweroff. - Ă
terstÀllning: omstartar den virtuella maskinen med kommandot
VBoxManage controlvm "virtuell maskin" reset. - SBD-STOP: hÀnger SBD-demonen med kommandot
killall -STOP sbd. - ShutDown: skickar kommandot till den virtuella maskinen via SSH
systemctl poweroff, systemet avslutar arbetet korrekt. - UnLink: nÀtverksisolering, kommando
VBoxManage controlvm "virtuell maskin" setlinkstate1 off.
Avslutande av testet antingen med standardkommandot tmux "kill-window" Ctrl-b &, eller med kommandot "detach-client" Ctrl-b d: dÀrmed avslutas testet, tmux stÀngs av, de virtuella maskinerna stÀngs ner.
Identifierade problem vid testning
För tillfÀllet watchdog-demonen sbd hanterar stopp av observerade demoner, men inte deras hÀngande. Och som en följd av detta, hanteras felaktigheter felaktigt, vilket leder till hÀngningar bara Corosync och Pacemaker, men som inte hÀnger sbd. För att kontrollera Corosync sÄ med hjÀlp av denna samling certifikat kan en kedja byggas och webbplatsen autentiseras. , accepterad i grenen master. Lovade (i PR#83) att det kommer att finnas nÄgot liknande för Pacemaker, jag hoppas att det kommer till RedHat 8 . Men sÄdana "fel" Àr hypotetiska, lÀtt duplicerbara artificiellt med exempelvis
killall -STOP corosync, men förekommer aldrig i verkliga livet.Hos Pacemaker i versionen för CentOS 7 Àr sync_timeout felaktigt stÀllt , vilket resulterar i för quorum deviceatt vid ett node-fel startade Àven den andra noden med viss sannolikhet omstart vid distribution (i skriptet , vilket resulterar i för quorum device setup/setup1
). Denna Àndring accepterades inte av utvecklarna, istÀllet lovade de att omarbeta infrastrukturen pÄ sÄ sÀtt (i nÄgon obestÀmd framtid), att denna timeout skulle berÀknas automatiskt. PacemakerOm det under konfigurationen av databasen anges attLC_MESSAGES
(textmeddelanden) kan anvÀnda Unicode, till exempelru_RU.UTF-8, sÄ vid starti en miljö dÀr locale inte Àr UTF-8, lÄt sÀga i en tom miljö (hÀr postgres pacemaker pgsqlms+(paf) startari loggen istÀllet för tecken i UTF-8 kommer det att finnas frÄgetecken postgres), sÄ LC_MESSAGES=en_US.UTF-8LC_MESSAGES=en_US.UTF-8vid konfiguration (skapande) av en databasinstans.Om wal_receiver_timeout Àr instÀllt (standard Àr 60s), dÄ vid test av PostgreSQL-STOP pÄ master i klustren tuchanka3 och tuchanka4 . Replikeringen Àr synkron, sÄ bÄde arbetaren och den nya mastern stannar. Detta kan kringgÄs genom att sÀtta wal_receiver_timeout=0 nÀr du konfigurerar PostgreSQL.
Jag har sÀllan sett att replikeringen hÀnger sig i PostgreSQL under ForkBomb-testet (minnesöverflöd). . Jag har bara sett detta i klustren tuchanka3 och tuchanka4, dÀr master hÀngde sig pÄ grund av att replikeringen var synkron. Problemet löste sig sjÀlv efter en lÀngre tid (ungefÀr tvÄ timmar). Ytterligare forskning krÀvs för att ÄtgÀrda detta. Symptomen liknar en tidigare bugg som orsakas av en annan anledning, men med samma konsekvenser.
Krogan-bilden Àr hÀmtad frÄn med författarens tillstÄnd:

KĂ€lla: habr.com
