Introducere
Cu ceva timp în urmă mi s-a dat sarcina de a dezvolta un cluster de failover pentru , care operează în mai multe centre de date conectate prin fibră optică într-un oraș și care poate rezista la o defecțiune (de exemplu, întreruperea curentului) a unui centru de date. Ca software care este responsabil pentru toleranța la erori, am ales deoarece aceasta este soluția oficială de la RedHat pentru crearea clusterelor de failover. Este bine pentru că RedHat oferă suport pentru el și pentru că această soluție este universală (modulară). Cu ajutorul acestuia, se va putea asigura toleranța la erori nu numai a PostgreSQL, ci și a altor servicii, fie folosind module standard, fie creându-le pentru nevoi specifice.
Această decizie a ridicat o întrebare rezonabilă: cât de tolerant la erori va fi un cluster de failover? Pentru a investiga acest lucru, am dezvoltat un banc de testare care simulează diverse defecțiuni pe nodurile clusterului, așteaptă ca serviciul să fie restaurat, recuperează nodul eșuat și continuă testarea într-o buclă. Acest proiect se numea inițial hapgsql, dar cu timpul m-am plictisit de nume, care avea doar o vocală. Prin urmare, am început să apelez baze de date tolerante la erori (și IP-ul flotant care indică spre ele) krogan (un personaj dintr-un joc de calculator în care toate organele importante sunt duplicate), iar nodurile, clusterele și proiectul în sine sunt tuchanka (planeta unde locuiesc kroganii).
Acum conducerea a permis . README va fi tradus în curând în engleză (pentru că se așteaptă ca principalii consumatori să fie dezvoltatorii Pacemaker și PostgreSQL) și am decis să prezint vechea versiune rusă a README (parțial) sub forma acestui articol.

Clusterele sunt implementate pe mașini virtuale . Vor fi implementate un total de 12 mașini virtuale (36GiB în total), care formează 4 clustere tolerante la erori (opțiuni diferite). Primele două clustere constau din două servere PostgreSQL, care sunt situate în centre de date diferite și un server comun martor c dispozitiv de cvorum (găzduit pe o mașină virtuală ieftină într-un al treilea centru de date), care rezolvă incertitudinea 50% / 50%, oferindu-vă votul uneia dintre partide. Al treilea cluster în trei centre de date: un master, doi slave, nr dispozitiv de cvorum. Al patrulea cluster este format din patru servere PostgreSQL, două pentru fiecare centru de date: un master, restul replici și, de asemenea, utilizează martor c dispozitiv de cvorum. Al patrulea poate rezista la defectarea a două servere sau a unui centru de date. Această soluție poate fi scalată la un număr mai mare de replici, dacă este necesar.
Serviciu de timp precis de asemenea, reconfigurat pentru toleranță la erori, dar folosește metoda în sine ntpd (modul orfan). Server partajat martor acționează ca un server NTP central, distribuindu-și timpul către toate clusterele, sincronizând astfel toate serverele între ele. Dacă martor eșuează sau devine izolat, atunci unul dintre serverele clusterului (din cadrul clusterului) va începe să-și distribuie timpul. Cache auxiliar Http proxy de asemenea ridicat la martor, cu ajutorul lui, alte mașini virtuale au acces la depozitele Yum. În realitate, servicii precum ora exactă și proxy-urile vor fi cel mai probabil găzduite pe servere dedicate, dar în cabină sunt găzduite pe martor doar pentru a salva numărul de mașini virtuale și spațiu.
versiuni
v0. Funcționează cu CentOS 7 și PostgreSQL 11 pe VirtualBox 6.1.
Structura clusterului
Toate clusterele sunt proiectate pentru a fi amplasate în mai multe centre de date, combinate într-o singură rețea plată și trebuie să reziste la defecțiunile sau izolarea rețelei a unui singur centru de date. De aceea este imposibil utilizați pentru protecție împotriva creier impartit tehnologie standard Pacemaker numită STONITH (împușcă celălalt nod în cap) sau scrimă. Esența sa: dacă nodurile din cluster încep să suspecteze că ceva nu este în regulă cu un nod, acesta nu răspunde sau se comportă incorect, atunci îl opresc forțat prin intermediul dispozitivelor „externe”, de exemplu, o placă de control IPMI sau UPS . Dar acest lucru va funcționa numai în cazurile în care, în cazul unei singure defecțiuni, serverul IPMI sau UPS continuă să funcționeze. Aici intenționăm să ne protejăm împotriva unei defecțiuni mult mai catastrofale, atunci când întregul centru de date defectează (de exemplu, pierde energie). Și cu un asemenea refuz, totul stonith-dispozitivele (IPMI, UPS etc.) nu vor funcționa.
În schimb, sistemul se bazează pe ideea de cvorum. Toate nodurile au o voce și numai cele care pot vedea mai mult de jumătate din toate nodurile pot funcționa. Această cantitate de „jumătate + 1” se numește cvorum. Dacă cvorumul nu este atins, atunci nodul decide că se află în izolarea rețelei și trebuie să-și dezactiveze resursele, de exemplu. asta este protecția creierului divizat. Dacă software-ul care este responsabil pentru acest comportament nu funcționează, atunci un watchdog, de exemplu, bazat pe IPMI, va trebui să funcționeze.
Dacă numărul de noduri este par (un cluster în două centre de date), atunci poate apărea așa-numita incertitudine 50% / 50% (jumi Juma) când izolarea rețelei împarte cluster-ul exact în jumătate. Prin urmare, pentru un număr par de noduri, adăugăm dispozitiv de cvorum este un demon nepretențios care poate fi lansat pe cea mai ieftină mașină virtuală dintr-un al treilea centru de date. Își dă votul unuia dintre segmente (pe care îl vede) și rezolvă astfel incertitudinea de 50%/50%. Am numit serverul pe care va fi lansat dispozitivul de cvorum martor (terminologie de la repmgr, mi-a plăcut).
Resursele pot fi mutate dintr-un loc în altul, de exemplu, de la servere defecte la cele sănătoase, sau la comanda administratorilor de sistem. Pentru ca clienții să știe unde se află resursele de care au nevoie (unde să se conecteze?), IP flotant (float IP). Acestea sunt IP-uri pe care Pacemaker le poate muta în jurul nodurilor (totul este într-o rețea plată). Fiecare dintre ele simbolizează o resursă (serviciu) și va fi amplasat acolo unde trebuie să vă conectați pentru a obține acces la acest serviciu (în cazul nostru, o bază de date).
Tuchanka1 (circuit cu compactare)
Structura

Ideea a fost că avem multe baze de date mici, cu încărcare redusă, pentru care nu este rentabilă să menținem un server slave dedicat în modul de așteptare la cald pentru tranzacții doar în citire (nu este nevoie de o astfel de risipă de resurse).
Fiecare centru de date are un server. Fiecare server are două instanțe PostgreSQL (în terminologia PostgreSQL se numesc clustere, dar pentru a evita confuziile le voi numi instanțe (prin analogie cu alte baze de date) și voi numi doar clustere Pacemaker clusters). O instanță funcționează în modul master și numai aceasta oferă servicii (doar IP-ul float duce la aceasta). A doua instanță funcționează ca slave pentru cel de-al doilea centru de date și va oferi servicii numai dacă masterul său eșuează. Deoarece de cele mai multe ori doar o instanță din două (masterul) va oferi servicii (efectuează cereri), toate resursele serverului sunt optimizate pentru master (memoria este alocată pentru cache-ul shared_buffers etc.), dar astfel încât a doua instanță are, de asemenea, suficiente resurse (deși pentru o funcționare suboptimă prin cache-ul sistemului de fișiere) în cazul defecțiunii unuia dintre centrele de date. Sclavul nu furnizează servicii (nu efectuează cereri doar de citire) în timpul funcționării normale a cluster-ului, astfel încât să nu existe război pentru resurse cu masterul de pe aceeași mașină.
În cazul a două noduri, toleranța la erori este posibilă numai cu replicarea asincronă, deoarece cu replicarea sincronă, defecțiunea unui slave va duce la oprirea masterului.
Eșecul de a depune martori

Eșecul de a asista (dispozitiv de cvorum) Voi lua în considerare doar pentru clusterul Tuchanka1, cu toate celelalte va fi aceeași poveste. Dacă martorul eșuează, nimic nu se va schimba în structura clusterului, totul va continua să funcționeze la fel. Dar cvorumul va deveni 2 din 3 și, prin urmare, orice defecțiune ulterioară va fi fatală pentru cluster. Va trebui totusi reparat urgent.
Tuchanka1 refuz

Eșecul unuia dintre centrele de date pentru Tuchanka1. În acest caz martor își votează un al doilea nod dintr-un al doilea centru de date. Acolo, fostul sclav se transformă într-un master, ca urmare, ambii master lucrează pe același server și ambele lor IP-uri float indică către ei.
Tuchanka2 (clasic)
Structura

Schema clasică a două noduri. Stăpânul lucrează la unul, sclavul la al doilea. Ambele pot executa cereri (sclavul este doar pentru citire), deci ambele sunt indicate prin IP-ul float: krogan2 este masterul, krogan2s1 este slave. Atât masterul cât și slave vor avea toleranță la erori.
În cazul a două noduri, toleranța la erori este posibilă doar cu replicarea asincronă, deoarece cu replicarea sincronă, defecțiunea slave va duce la oprirea masterului.
Tuchanka2 refuz

Dacă unul dintre centrele de date eșuează martor voturi pentru al doilea. Pe singurul centru de date care funcționează, masterul va fi ridicat și ambele IP-uri float vor indica către el: masterul și slave. Desigur, instanța trebuie configurată în așa fel încât să aibă suficiente resurse (limite de conectare etc.) pentru a accepta simultan toate conexiunile și solicitările de la IP-ul float master și slave. Adică, în timpul funcționării normale ar trebui să aibă o rezervă suficientă de limite.
Tuchanka4 (mulți sclavi)
Structura

Deja o altă extremă. Există baze de date care primesc o mulțime de solicitări doar în citire (un caz tipic al unui site cu încărcare mare). Tuchanka4 este o situație în care pot exista trei sau mai mulți sclavi care să gestioneze astfel de solicitări, dar totuși nu prea mulți. Cu un număr foarte mare de sclavi, va fi necesar să se inventeze un sistem de replicare ierarhică. În cazul minim (în imagine), fiecare dintre cele două centre de date are două servere, fiecare cu o instanță PostgreSQL.
O altă caracteristică a acestei scheme este că este deja posibilă organizarea unei replicări sincrone. Este configurat pentru a se replica, dacă este posibil, la un alt centru de date, mai degrabă decât la o replică din același centru de date ca și masterul. Master și fiecare slave sunt indicați de către un IP float. Din fericire, între sclavi va fi necesar să echilibrăm cumva cererile proxy sql, de exemplu, pe partea clientului. Diferite tipuri de clienți pot necesita tipuri diferite proxy sql, și numai dezvoltatorii clienți știu cine are nevoie de care. Această funcționalitate poate fi implementată fie de un demon extern, fie de o bibliotecă client (pool de conexiuni), etc. Toate acestea depășesc subiectul unui cluster de baze de date de failover (failover proxy SQL poate fi implementat independent, împreună cu toleranța la erori ale clientului).
Tuchanka4 refuz

Dacă un centru de date (adică două servere) eșuează, martorii votează pentru al doilea. Ca rezultat, există două servere care rulează în al doilea centru de date: unul rulează un master, iar IP-ul float principal indică către acesta (pentru primirea solicitărilor de citire-scriere); iar pe al doilea server există un slave care rulează cu replicare sincronă, iar unul dintre IP-urile slave float indică către acesta (pentru solicitări doar în citire).
Primul lucru de remarcat este că nu toate IP-urile slave float vor fi lucrători, ci doar unul. Și pentru a lucra cu el corect va fi necesar ca proxy sql a redirecționat toate cererile către singurul IP float rămas; si daca proxy sql nu, atunci puteți enumera toți slavii IP float separati prin virgule în URL-ul conexiunii. În acest caz, cu libpq conexiunea va fi la primul IP de lucru, acest lucru se face în sistemul automat de testare. Poate că în alte biblioteci, de exemplu, JDBC, acest lucru nu va funcționa și este necesar proxy sql. Acest lucru se face deoarece IP-urile float pentru sclavi sunt interzise să fie ridicate simultan pe un server, astfel încât acestea să fie distribuite uniform între serverele slave dacă există mai multe dintre ele care rulează.
În al doilea rând: chiar și în cazul unei eșecuri a centrului de date, replicarea sincronă va fi menținută. Și chiar dacă apare o defecțiune secundară, adică unul dintre cele două servere din centrul de date rămas eșuează, clusterul, deși nu va mai furniza servicii, va păstra în continuare informații despre toate tranzacțiile comise pentru care a dat confirmarea commitării. (nu vor exista informații despre pierderi în caz de defecțiune secundară).
Tuchanka3 (3 centre de date)
Structura

Acesta este un cluster pentru o situație în care există trei centre de date complet funcționale, fiecare dintre ele având un server de baze de date complet funcțional. În acest caz dispozitiv de cvorum nu e necesar. Un centru de date este ocupat de un maestru, celelalte două sunt ocupate de sclavi. Replicarea este sincronă, tastați ANY (slave1, slave2), adică clientul va primi o confirmare de comitere atunci când oricare dintre sclavi este primul care răspunde că a acceptat commit-ul. Resursele sunt indicate de un IP float pentru master și două pentru slave. Spre deosebire de Tuchanka4, toate cele trei IP-uri float sunt tolerante la erori. Pentru a echilibra interogările SQL numai în citire, puteți utiliza proxy sql (cu toleranță separată la erori) sau atribuiți un IP float slave la jumătate dintre clienți, iar cealaltă jumătate celui de-al doilea.
Tuchanka3 refuz

Dacă unul dintre centrele de date eșuează, rămân două. Într-una, IP-ul master și float de la master sunt ridicate, în al doilea - IP-urile float slave și ambele IP-uri slave (instanța trebuie să aibă o rezervă dublă de resurse pentru a accepta toate conexiunile de la ambele IP-uri float slave). Replicare sincronă între master și sclavi. De asemenea, clusterul va salva informații despre tranzacțiile comise și confirmate (nu va exista pierdere de informații) în cazul distrugerii a două centre de date (dacă acestea nu sunt distruse simultan).
Am decis să nu includ o descriere detaliată a structurii și implementării fișierelor. Oricine vrea să se joace poate citi totul în README. Ofer doar o descriere a testării automate.
Sistem automat de testare
Pentru a testa toleranța la erori a clusterelor prin simularea diferitelor defecte, a fost creat un sistem automat de testare. Lansat prin script test/failure. Scriptul poate lua ca parametri numărul de clustere pe care doriți să le testați. De exemplu, această comandă:
test/failure 2 3va testa doar al doilea și al treilea cluster. Dacă nu sunt specificați parametrii, atunci toate clusterele vor fi testate. Toate clusterele sunt testate în paralel, iar rezultatul este afișat în panoul tmux. Tmux folosește un server tmux dedicat, astfel încât scriptul poate fi rulat din tmux implicit, rezultând un tmux imbricat. Recomand să folosiți terminalul într-o fereastră mare și cu un font mic. Înainte de începerea testării, toate mașinile virtuale sunt derulate înapoi la un instantaneu la momentul finalizării scriptului setup.

Terminalul este împărțit în coloane în funcție de numărul de clustere testate în mod implicit (în captură de ecran) sunt patru. Voi descrie conținutul coloanelor folosind exemplul lui Tuchanka2. Panourile din captura de ecran sunt numerotate:
- Statisticile testelor sunt afișate aici. Coloane:
- eşec — numele testului (funcția din script) care emulează eroarea.
- reacţie — timpul mediu aritmetic în secunde în care clusterul și-a recuperat funcționalitatea. Se măsoară de la începutul script-ului emulând o eroare până în momentul în care cluster-ul își restabilește funcționalitatea și este capabil să continue să furnizeze servicii. Dacă timpul este foarte scurt, de exemplu, șase secunde (acest lucru se întâmplă în clustere cu mai mulți sclavi (Tuchanka3 și Tuchanka4)), aceasta înseamnă că defecțiunea a fost pe slave asincron și nu a afectat în niciun fel performanța; comutatoare de stare cluster.
- deviere — arată răspândirea (acuratețea) valorii reacţie folosind metoda abaterii standard.
- conta — de câte ori a fost efectuat acest test.
- Un jurnal scurt vă permite să evaluați ceea ce face clusterul în prezent. Sunt afișate numărul iterației (testului), marca temporală și numele operației. A alerga prea mult (> 5 minute) indică o problemă.
- inimă (inima) - ora curentă. Pentru evaluarea vizuală a performanței maestru Ora curentă este scrisă constant în tabelul său folosind masterul IP float. Dacă are succes, rezultatul este afișat în acest panou.
- bate (puls) - „ora curentă”, care a fost înregistrată anterior de scenariu inimă a stăpâni, acum citește din sclav prin IP-ul său float. Vă permite să evaluați vizual performanța slave și replicarea. În Tuchanka1 nu există sclavi cu IP float (nu există sclavi care furnizează servicii), dar există două instanțe (DB), așa că nu va fi afișat aici bateȘi inimă a doua instanță.
- Monitorizarea stării clusterului folosind utilitarul
pcs mon. Afișează structura, distribuția resurselor între noduri și alte informații utile. - Monitorizarea sistemului de la fiecare mașină virtuală din cluster este afișată aici. Pot exista mai multe astfel de panouri, în funcție de câte mașini virtuale are clusterul. Două grafice Încărcare CPU (mașinile virtuale au două procesoare), numele mașinii virtuale, Încărcare sistem (numită Load Average deoarece este mediată pe 5, 10 și 15 minute), procesează datele și alocarea memoriei.
- Urmărirea scriptului care efectuează testarea. În cazul unei defecțiuni - o întrerupere bruscă a funcționării sau un ciclu nesfârșit de așteptare - aici puteți vedea motivul acestui comportament.
Testarea se realizează în două etape. Mai întâi, scriptul trece prin toate tipurile de teste, selectând aleatoriu o mașină virtuală la care să se aplice acest test. Apoi se efectuează un ciclu nesfârșit de testare, mașinile virtuale și eroarea sunt selectate aleatoriu de fiecare dată. Încetarea bruscă a scriptului de testare (panoul de jos) sau o buclă nesfârșită de așteptare pentru ceva (> 5 minute timp de execuție pentru o operație, acest lucru poate fi văzut în urmărire) indică faptul că unele dintre testele de pe acest cluster au eșuat.
Fiecare test constă din următoarele operații:
- Lansați o funcție care emulează o eroare.
- Gata? — așteptarea restaurării clusterului (când sunt furnizate toate serviciile).
- Afișează expirarea timpului de recuperare a clusterului (reacţie).
- Repara — clusterul este „reparat”. După care ar trebui să revină la o stare complet operațională și să fie pregătit pentru următoarea defecțiune.
Iată o listă de teste cu o descriere a ceea ce fac:
- ForkBomb: creează „În memorie” folosind o bombă cu furcă.
- Fara spatiu: Hard disk-ul este plin. Dar testul este mai degrabă simbolic, cu sarcina nesemnificativă care este creată în timpul testării, PostgreSQL de obicei nu eșuează când hard disk-ul este plin.
- Postgres-KILL: omoara PostgreSQL cu comanda
killall -KILL postgres. - Postgres-STOP: blochează comanda PostgreSQL
killall -STOP postgres. - Oprire: „dezenergizează” mașina virtuală cu comanda
VBoxManage controlvm "виртуалка" poweroff. - Reseteaza: supraîncarcă mașina virtuală cu comanda
VBoxManage controlvm "виртуалка" reset. - SBD-STOP: suspendă demonul SBD cu comanda
killall -STOP sbd. - Închide: trimite o comandă la mașina virtuală prin SSH
systemctl poweroff, sistemul se oprește cu grație. - Deconectați: izolarea rețelei, comandă
VBoxManage controlvm "виртуалка" setlinkstate1 off.
Terminarea testării fie folosind comanda tmux standard „kill-window” Ctrl-b &, sau comanda „detach-client”. Ctrl-b d: în acest moment se termină testarea, tmux se închide, mașinile virtuale sunt oprite.
Probleme identificate în timpul testării
În prezent watchdog demon sbd lucrează la oprirea demonilor observați, dar nu la înghețarea lor. Și, ca urmare, defecțiuni care duc doar la îngheț Corosync и Pacemaker, dar nu agățat SBD. Pentru verificare Corosync deja au , acceptat la thread maestru. Au promis (în PR#83) că va exista ceva asemănător pentru Pacemaker, sper că până la Red Hat 8 se va face. Dar astfel de „defecțiuni” sunt speculative și pot fi simulate cu ușurință artificial folosind, de exemplu,
killall -STOP corosync, dar nu se întâlnesc niciodată în viața reală.У Pacemaker în varianta pentru CentOS 7 setat incorect sync_timeout у dispozitiv de cvorum, ca urmare , la care stăpânul trebuia să se mute. Vindecat prin mărire sync_timeout у dispozitiv de cvorum în timpul implementării (în script
setup/setup1). Acest amendament nu a fost acceptat de dezvoltatori Pacemaker, în schimb au promis că vor reproiecta infrastructura în așa fel (la un viitor nespecificat) încât acest timeout să fie calculat automat.Dacă configurația bazei de date specifică asta
LC_MESSAGES(mesaje text) Unicode poate fi utilizat, de ex.ru_RU.UTF-8, apoi la pornire Postgres într-un mediu în care localitatea nu este UTF-8, să zicem într-un mediu gol (aici stimulator cardiac+pgsqlms(paf) aleargă Postgres) apoi . Dezvoltatorii PostgreSQL nu au căzut de acord cu privire la ce să facă în acest caz. Costă, trebuie instalatLC_MESSAGES=en_US.UTF-8la configurarea (crearea) unei instanțe de bază de date.Dacă wal_receiver_timeout este setat (în mod implicit este 60s), atunci în timpul testului PostgreSQL-STOP pe master în clusterele tuchanka3 și tuchanka4 . Replicarea acolo este sincronă, așa că nu numai sclavul se oprește, ci și noul maestru. Funcționează prin setarea wal_receiver_timeout=0 la configurarea PostgreSQL.
Ocazional, am observat înghețari de replicare în PostgreSQL în testul ForkBomb (depășire de memorie). . Am întâlnit asta doar în clusterele tuchanka3 și tuchanka4, unde masterul a înghețat din cauza replicării sincrone. Problema a dispărut de la sine după mult timp (aproximativ două ore). Este nevoie de mai multe cercetări pentru a corecta acest lucru. Simptomele sunt similare cu bug-ul precedent, care este cauzat de un motiv diferit, dar cu aceleași consecințe.
Krogan poză luată de la cu permisiunea autorului:

Sursa: www.habr.com
