Blog JSystems - uwalniamy wiedzę!

Szukaj

PostgreSQL

Jak zapewnić automatyczny failover w PostgreSQL (Patroni)

W skrócie

  • Gdy padnie primary, ktoś musi ręcznie awansować replikę i przełączyć na nią ruch - w nocy trwa to długo, a baza stoi.
  • Sam PostgreSQL nie ma wbudowanego automatycznego failoveru; nie wie, czy naprawdę padł, czy tylko zerwała się sieć, i nie chce ryzykować dwóch primary naraz.
  • Dokładamy Patroni - nadzorcę, który przez rozproszony magazyn stanu (etcd/Consul) pilnuje, kto jest primary, sam awansuje replikę przy awarii i kieruje aplikację przez jeden stały punkt wejścia.

Replika daje kopię danych, ale nie przełącza ruchu sama z siebie. Do prawdziwej wysokiej dostępności potrzebny jest mechanizm automatycznego failoveru. W świecie PostgreSQL standardem jest Patroni - wyjaśniamy, jak i dlaczego działa.

Jak to wygląda w praktyce

Mamy primary i standby, replikacja działa. O trzeciej w nocy primary przestaje odpowiadać - awaria dysku albo padł cały host. Aplikacja zwraca błędy połączenia, bo wciąż celuje w martwy serwer. Standby ma świeże dane, ale sam z siebie pozostaje repliką tylko do odczytu - nikt go nie awansował. Ktoś musi się obudzić, zalogować, wykonać promocję repliki, przepiąć adres w aplikacji i sprawdzić, czy stary primary nie wstanie i nie zacznie przyjmować zapisów równolegle. To minuty albo godziny przestoju i realne ryzyko błędu pod presją. Chcemy, żeby to przełączenie odbywało się samo, w kilka-kilkanaście sekund, bez człowieka.

Dlaczego tak się dzieje

PostgreSQL świadomie nie podejmuje decyzji o failoverze. Pojedynczy serwer nie jest w stanie odróżnić, czy primary faktycznie padł, czy tylko chwilowo zerwało się połączenie sieciowe. Gdyby replika awansowała się przy każdym zerwaniu sieci, mogłoby powstać rozszczepienie (split-brain): dwa serwery uznające się za primary, oba przyjmujące zapisy, a potem nie do pogodzenia dane. Bezpieczne przełączenie wymaga zewnętrznego, wspólnego dla całego klastra źródła prawdy o tym, kto jest primary. Patroni rozwiązuje to przez rozproszony magazyn konfiguracji (DCS): etcd, Consul lub ZooKeeper. Każdy węzeł uruchamia agenta Patroni, który zarządza lokalnym PostgreSQL i utrzymuje w DCS klucz przywództwa z krótkim czasem życia. Tylko węzeł trzymający ten klucz jest primary. Gdy primary padnie i przestanie odnawiać klucz, ten wygasa, a pozostałe węzły przez DCS uzgadniają, który z nich (najświeższy) ma się awansować - dzięki wymogowi większości (quorum) nie da się mieć dwóch primary naraz.

Jak to rozwiązać krok po kroku

  1. Stawiamy rozproszony magazyn stanu. Najczęściej jest to klaster etcd na (co najmniej) trzech węzłach - nieparzysta liczba jest istotna, bo decyzje zapadają większością głosów. To on chroni przed split-brain.
  2. Na każdym węźle bazodanowym instalujemy PostgreSQL oraz Patroni (pakiet patroni[etcd]). Patroni sam będzie startował i konfigurował PostgreSQL - nie uruchamiamy bazy niezależnie z systemd.
  3. Piszemy plik konfiguracyjny Patroni dla każdego węzła (np. patroni.yml): sekcja etcd wskazuje adresy magazynu stanu, bootstrap.dcs ustala parametry klastra (m.in. ttl, loop_wait, retry_timeout), a postgresql zawiera dane połączeniowe i konto replikacyjne. Nazwa klastra (scope) musi być taka sama na wszystkich węzłach.
  4. Uruchamiamy Patroni na pierwszym węźle - zainicjuje nowy klaster i stanie się primary, zapisując klucz przywództwa w DCS.
  5. Uruchamiamy Patroni na kolejnych węzłach - wykryją istniejącego lidera przez DCS, sklonują bazę (Patroni potrafi użyć pg_basebackup) i wystartują jako repliki podpięte do primary.
  6. Przed aplikacją stawiamy jeden stały punkt wejścia. Zwykle to HAProxy odpytujący REST API Patroni (endpoint /primary zwraca sukces tylko na aktualnym primary), dzięki czemu ruch zapisu zawsze trafia tam, gdzie trzeba - niezależnie od tego, który węzeł akurat jest liderem.
  7. Testujemy failover w kontrolowanych warunkach: patronictl -c patroni.yml switchover dla przełączenia planowego. Sprawdzamy, że po zabiciu primary klaster sam awansuje replikę, a HAProxy przekieruje ruch.

Jak sprawdzić, że zadziałało

Stan całego klastra pokaże patronictl -c patroni.yml list - zobaczymy role węzłów (Leader, Replica), ich stan (running) i opóźnienie replikacji w bajtach. Test właściwy: zatrzymujemy proces PostgreSQL lub Patroni na primary i obserwujemy listę - w ciągu kilkunastu sekund (zależnie od ttl i loop_wait) jedna z replik powinna zmienić rolę na Leader. Jeśli aplikacja łączy się przez HAProxy, jej zapisy po krótkiej przerwie znów przechodzą, bo ruch trafił na nowy primary. Gdy stary węzeł wróci do życia, Patroni automatycznie podepnie go jako nową replikę (w razie potrzeby wykona pg_rewind), a nie jako drugi primary - i to jest dowód, że ochrona przed split-brain działa. Warto też sprawdzić w logach Patroni komunikaty o przejęciu przywództwa oraz endpoint REST /cluster, który zwraca aktualną topologię.

Wróć do listy: 100 najczęstszych pytań i problemów z PostgreSQL

Szkolenie Administracja, replikacja i tuning baz danych PostgreSQL

Sprawdź szkolenie: Administracja, replikacja i tuning baz danych PostgreSQL

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Szkolenie Zaawansowana administracja PostgreSQL - HA, DR, monitoring, skalowanie

Sprawdź szkolenie: Zaawansowana administracja PostgreSQL (HA, DR, monitoring, skalowanie)

To szkolenie może być dofinansowane z KFS lub BUR.

★★★★★Średnia ocena naszych szkoleń w Google: 5/5

Najczęściej zadawane pytania

Czy PostgreSQL ma wbudowany automatyczny failover?
Nie. PostgreSQL świadomie nie podejmuje decyzji o przełączeniu, bo pojedynczy serwer nie odróżni prawdziwej awarii primary od chwilowego zerwania sieci. Automatyczne przełączenie wymaga zewnętrznego nadzorcy, takiego jak Patroni, opartego o rozproszony magazyn stanu. Sam standby pozostaje repliką tylko do odczytu, dopóki ktoś lub coś go nie awansuje.
Do czego Patroni potrzebuje etcd albo Consula?
To rozproszony magazyn stanu (DCS), wspólne dla całego klastra źródło prawdy o tym, kto jest primary. Patroni trzyma tam klucz przywództwa z krótkim czasem życia; tylko węzeł z tym kluczem jest primary. Dzięki wymogowi większości głosów magazyn zapobiega sytuacji, w której dwa węzły jednocześnie uznają się za primary.
Czym jest split-brain i jak Patroni przed nim chroni?
Split-brain to rozszczepienie, w którym dwa serwery uznają się za primary i oba przyjmują zapisy, co prowadzi do nie do pogodzenia danych. Patroni chroni przed tym, wymagając większości (quorum) w rozproszonym magazynie stanu do awansu. Gdy primary traci łączność i nie odnawia klucza przywództwa, tylko jeden węzeł, uzgodniony przez większość, może go zastąpić.
Jak sprawdzić stan klastra i przetestować failover w Patroni?
Stan pokaże patronictl -c patroni.yml list z rolami węzłów, ich stanem i opóźnieniem replikacji. Przełączenie planowe wywołasz przez patronictl switchover. Test awaryjny: zatrzymaj PostgreSQL na primary i obserwuj listę, w ciągu kilkunastu sekund jedna z replik powinna zmienić rolę na Leader, a stary węzeł po powrocie zostanie podpięty jako nowa replika, nie drugi primary.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...