Blog JSystems - uwalniamy wiedzę!

Szukaj

PostgreSQL

Patroni z etcd - najczęstsze błędy konfiguracji

W skrócie

  • Klaster Patroni nie wstaje albo nie wybiera lidera, choć same bazy PostgreSQL są sprawne.
  • Najczęstsza przyczyna to rozjazd między tym, co widzi Patroni, a tym, co jest w etcd: złe adresy, niespójne wersje API, brak synchronizacji czasu albo dwa węzły piszące do jednego klucza.
  • Ujednolicamy adresy w sekcji etcd, wymuszamy poprawną wersję protokołu, pilnujemy zegara i sprawdzamy stan przez patronictl list oraz etcdctl.

Patroni to jeden z najpopularniejszych sposobów na zbudowanie klastra wysokiej dostępności PostgreSQL, a etcd pełni w nim rolę wspólnego magazynu stanu (DCS - Distributed Configuration Store). Kiedy oba elementy są poprawnie skonfigurowane, przełączanie lidera dzieje się samo. Kiedy nie są, dostajemy klaster, który wygląda zdrowo w logach PostgreSQL, a mimo to nie ma żadnego primary. Zebraliśmy błędy, które w praktyce pojawiają się najczęściej.

Jak to wygląda w praktyce

Objaw numer jeden to komenda patronictl list, która zwraca pustą tabelę albo wszystkie węzły w roli replica bez ani jednego lidera. Drugi typowy obraz to węzły, które cyklicznie startują i padają - w logu Patroni przewija się wtedy waiting for leader to bootstrap albo failed to update leader lock in DCS. Zdarza się też, że dwa węzły jednocześnie uważają się za lidera (split-brain), co widać po dwóch instancjach przyjmujących zapisy. Wspólnym mianownikiem jest to, że sam PostgreSQL działa - problem leży w warstwie koordynacji, czyli w komunikacji Patroni z etcd.

Dlaczego tak się dzieje

Patroni cały czas trzyma w etcd klucz z blokadą lidera i odświeża go co kilka sekund. Jeśli węzeł nie zdąży odświeżyć klucza przed upływem ttl, traci rolę primary i zaczyna się nowa elekcja. Najczęstsze przyczyny problemów: po pierwsze, rozjeżdżające się adresy - w sekcji etcd pliku YAML podajemy jeden host, a etcd nasłuchuje na innym interfejsie, więc połączenie się nie nawiązuje. Po drugie, wersja protokołu: nowsze Patroni domyślnie mówi do etcd przez API v3, a stara konfiguracja oczekuje v2 - stąd ciche błędy połączenia. Po trzecie, brak synchronizacji zegara między węzłami: skoro ttl i loop_wait operują na sekundach, rozjechany czas powoduje błędne wygasanie blokady. Po czwarte, dwa węzły ze skopiowaną konfiguracją i tym samym name nadpisują sobie nawzajem wpis w etcd.

Jak to rozwiązać krok po kroku

  1. Sprawdź, czy sam etcd jest zdrowy, zanim ruszysz Patroni: etcdctl endpoint health oraz etcdctl member list. Jeśli etcd nie ma kworum, żaden klaster Patroni nie wstanie.
  2. W pliku konfiguracyjnym Patroni ujednolić sekcję z adresami etcd. Dla API v3 użyj klucza etcd3 z listą hostów, na przykład hosts: 10.0.0.11:2379,10.0.0.12:2379,10.0.0.13:2379. Nie mieszaj sekcji etcd (v2) z etcd3 w jednym pliku.
  3. Upewnij się, że każdy węzeł ma unikalne name oraz poprawny restapi.connect_address i postgresql.connect_address wskazujące na adres widziany przez pozostałe węzły, a nie na 127.0.0.1.
  4. Wymuś synchronizację czasu: włącz chrony lub systemd-timesyncd na wszystkich węzłach i sprawdź timedatectl. Zegary muszą się zgadzać co do sekundy.
  5. Dobierz parametry czasowe z zapasem. W sekcji bootstrap.dcs ustaw ttl większy niż dwukrotność loop_wait plus retry_timeout, na przykład ttl: 30, loop_wait: 10, retry_timeout: 10. Zbyt niski ttl to najczęstsza przyczyna niepotrzebnych failoverów.
  6. Jeśli w etcd został osierocony klucz po starym klastrze, wyczyść go dopiero po pewności, że żaden węzeł nie jest liderem: przejrzyj etcdctl get --prefix /service/twoj-klaster/.
  7. Restartuj Patroni na węzłach pojedynczo i po każdym obserwuj patronictl list, aż pojawi się jeden Leader i reszta jako Replica z opóźnieniem równym zero.

Jak sprawdzić, że zadziałało

Poprawnie działający klaster pokazuje w patronictl list dokładnie jeden wiersz z rolą Leader i pozostałe jako Replica ze stanem streaming. Klucz lidera w etcd powinien mieć świeży TTL - sprawdzimy to przez etcdctl get /service/twoj-klaster/leader. Kontrolny test to ręczny patronictl switchover: po nim rola Leader przechodzi na inny węzeł bez błędów, a aplikacja po chwili znów zapisuje dane. Jeśli switchover przechodzi czysto, znaczy to, że warstwa koordynacji działa tak, jak powinna.

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

Dlaczego patronictl list nie pokazuje żadnego lidera?
Najczęściej dlatego, że Patroni nie może zapisać klucza lidera do etcd. Sprawdź zdrowie etcd przez etcdctl endpoint health, ujednolić adresy w sekcji konfiguracji i upewnij się, że zegary na wszystkich węzłach są zsynchronizowane. Zbyt niski parametr ttl względem loop_wait też powoduje, że blokada lidera ciągle wygasa i elekcja nie może się ustabilizować.
Czy w konfiguracji Patroni użyć sekcji etcd czy etcd3?
Dla nowoczesnego etcd korzystającego z API v3 użyj sekcji etcd3, bo starsza sekcja etcd mówi do API v2. Nie mieszaj obu sekcji w jednym pliku, bo prowadzi to do cichych błędów połączenia. Jeśli klaster niespodziewanie nie widzi etcd mimo poprawnych adresów, sprawdź właśnie zgodność wersji protokołu.
Skąd bierze się split-brain w klastrze Patroni?
Zwykle z rozjechanych zegarów albo ze zbyt niskiego ttl, przez co dwa węzły na chwilę jednocześnie uważają, że blokada lidera wygasła. Innym źródłem jest zatrzymywanie PostgreSQL poza Patroni, co wygląda dla klastra jak awaria i uruchamia niepotrzebną promocję repliki. Włączenie synchronizacji czasu i rozsądny ttl to podstawa zapobiegania.
Jak bezpiecznie wyczyścić osierocony klucz po starym klastrze w etcd?
Najpierw upewnij się, że żaden działający węzeł nie jest liderem powiązanym z tym kluczem. Przejrzyj zawartość przez etcdctl get z prefiksem ścieżki twojego klastra, zidentyfikuj wpisy po nazwie klastra i dopiero wtedy je usuń. Kasowanie kluczy w etcd na działającym klastrze bez tej weryfikacji może wywołać natychmiastową niepotrzebną elekcję.

Komentarze (0)

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

Brak komentarzy...