Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

У артыкуле я раскажу, як мы падышлі да пытання адмоваўстойлівасці PostgreSQL, чаму гэта стала для нас важна і што ў выніку атрымалася.

У нас высоканагружаны сэрвіс: 2,5 карыстальнікаў па ўсім свеце, 50К + актыўных карыстальнікаў кожны дзень. Сервера знаходзяцца ў Amazone у адным рэгіёне Ірландыі: у працы стала 100+ розных сервераў, з іх амаль 50 – з базамі дадзеных.

Увесь backend - вялікае маналітнае stateful-дадатак на Java, якое трымае пастаяннае websocket злучэнне з кліентам. Пры адначасовай працы некалькіх карыстальнікаў на адной дошцы ўсе яны бачаць змены ў рэжыме рэальнага часу, таму што кожную змену мы запісваем у базу. У нас прыкладна 10К запытаў у секунду да нашых баз. У пікавай нагрузцы ў Redis мы пішам па 80-100К запытаў у секунду.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Чаму мы перайшлі з Redis на PostgreSQL

Першапачаткова наш сэрвіс працаваў з Redis, key-value сховішчам, якое захоўвае ўсе даныя ў аператыўнай памяці сервера.

Плюсы Redis:

  1. Высокая хуткасць адказу, т.я. усё захоўваецца ў памяці;
  2. Выгода бэкапу і рэплікацыі.

Мінусы Redis для нас:

  1. Няма сапраўдных транзакцый. Мы спрабавалі імітаваць іх на ўзроўні нашага прыкладання. Нажаль, гэта не заўсёды добра працавала і патрабавала напісанні вельмі складанага кода.
  2. Аб'ём дадзеных абмежаваны колькасцю памяці. Пры павелічэнні колькасці дадзеных памяць будзе расці, і, у выніку, мы ўпрэмся ў характарыстыкі абранага інстанса, што ў AWS патрабуе прыпынку нашага сэрвісу для змены тыпу інстанса.
  3. Неабходна ўвесь час падтрымліваць узровень нізкага latency, т.к. у нас вельмі вялікая колькасць запытаў. Аптымальны для нас узровень затрымкі – 17-20 ms. Пры ўзроўні 30-40 ms мы атрымліваем доўгія адказы на запыты нашага дадатку і дэградацыю сэрвісу. На жаль, у нас гэта здарылася ў верасні 2018 года, калі адзін з інстансаў з Redis чамусьці атрымаў latency у 2 разы больш, чым звычайна. Для рашэння праблемы мы спынілі сэрвіс у сярэдзіне працоўнага дня для пазапланавага maintenance і замянілі праблемны інстанс Redis.
  4. Лёгка атрымаць некансінстэнтнасць дадзеных нават пры малаважных памылках у кодзе і потым выдаткаваць шмат часу на напісанне кода для выпраўлення гэтых дадзеных.

Мы ўлічылі мінусы і зразумелі, што нам неабходна пераехаць на нешта зручнейшае, са звычайнымі транзакцыямі і меншай залежнасцю ад latency. Правялі даследаванне, прааналізавалі мноства варыянтаў і абралі PostgreSQL.

На новую БД мы пераязджаем ужо 1,5 гады і перавезлі толькі невялікую частку дадзеных, таму зараз працуем адначасова з Redis і PostgreSQL. Падрабязней аб этапах пераезду і пераключэнні дадзеных паміж БД напісана ў артыкуле майго калегі.

Калі мы толькі пачыналі пераязджаць, наша дадатак працавала напрамую з БД і звярталася да майстра Redis і PostgreSQL. Кластар PostgreSQL складаўся з майстра і рэплікі з асінхроннай рэплікацыяй. Так выглядала схема працы з базамі:
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Укараненне PgBouncer

Пакуль мы пераязджалі, прадукт таксама развіваўся: павялічвалася колькасць карыстачоў і колькасць сервераў, якія працавалі з PostgreSQL, і нам стала бракаваць злучэнняў. PostgreSQL на кожнае злучэнне стварае асобны працэс і спажывае рэсурсы. Павялічваць колькасць канэктаў можна да вызначанага моманту, інакш ёсць шанец атрымаць неаптымальную працу БД. Ідэальным варыянтам у такой сітуацыі будзе выбар мэнэджара канэктаў, які паўстане перад базай.

У нас было два варыянты для мэнэджэра злучэнняў: Pgpool і PgBouncer. Але першы не падтрымлівае транзакцыйны рэжым працы з базай, таму мы выбралі PgBouncer.

Мы наладзілі наступную схему працы: наша дадатак звяртаецца да аднаго PgBouncer, за якім знаходзяцца masters PostgreSQL, а за кожным майстрам - адна рэпліка з асінхроннай рэплікацыяй.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Пры гэтым мы не маглі захоўваць увесь аб'ём дадзеных у PostgreSQL і для нас была важная хуткасць працы з базай, таму мы пачалі шаляваць PostgreSQL на прыкладным узроўні. Апісаная вышэй схема з'яўляецца для гэтага адносна зручнай: пры даданні новага шарда PostgreSQL дастаткова абнавіць канфігурацыю PgBouncer і дадатак можа адразу працаваць з новым шардам.

Адмаўстойлівасць PgBouncer

Гэтая схема прапрацавала да моманту, пакуль адзіны інстанс PgBouncer не памёр. Мы знаходзімся ў AWS, дзе ўсе інстансы запушчаны на жалезе, якое перыядычна памірае. У такіх выпадках інстанс проста пераязджае на новае жалеза і зноў працуе. Так адбылося і з PgBouncer, аднак ён стаў недаступны. Вынікам гэтага падзення стала недаступнасць нашага сэрвісу на працягу 25 хвілін. AWS для такіх сітуацый рэкамендуе выкарыстоўваць надмернасць на баку карыстальніка, што не было рэалізавана ў нас на той момант.

Пасля гэтага мы сур'ёзна задумаліся аб адмоваўстойлівасці PgBouncer і кластараў PostgreSQL, таму што падобная сітуацыя магла паўтарыцца з любым інстансам у нашым AWS акаўнце.

Схему адмоваўстойлівасці PgBouncer мы пабудавалі наступным чынам: усе сервера прыкладання звяртаюцца да Network Load Balancer, за якім стаяць два PgBouncer. Кожны з PgBouncer глядзіць на адны і тыя ж master PostgreSQL кожнага шарда. У выпадку паўтарэння сітуацыі з падзеннем інстансу AWS, увесь трафік перанакіроўваецца праз іншы PgBouncer. Адмаўстойлівасць Network Load Balancer забяспечвае AWS.

Такая схема дазваляе без праблем дадаваць новыя серверы PgBouncer.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Стварэнне адмоваўстойлівага кластара PostgreSQL

Пры рашэнні гэтай задачы мы разглядалі розныя варыянты: самапісны failover, repmgr, AWS RDS, Patroni.

Самапісныя скрыпты

Могуць маніторыць працу майстра і, у выпадку яго падзення, прасоўваць рэпліку да майстра і абнаўляць канфігурацыю PgBouncer.

Плюсы такога падыходу ў максімальнай прастаце, таму што вы самі пішыце скрыпты і сапраўды разумееце, як яны працуюць.

Мінусы:

  • Майстар мог не памерці, замест гэтага мог адбыцца сеткавы збой. Failover, не ведаючы аб гэтым, прасуне рэпліку да майстра, а стары майстар будзе працягваць працаваць. У выніку мы атрымаем два сервера ў ролі master і не будзем ведаць, на якім з іх апошнія актуальныя дадзеныя. Такую сітуацыю называюць яшчэ split-brain;
  • Мы засталіся без рэплікі. У нашай канфігурацыі майстар і адна рэпліка, пасля пераключэння рэпліка прасоўваецца да майстра і ў нас больш няма рэплік, таму даводзіцца ў ручным рэжыме дадаваць новую рэпліку;
  • Патрэбны дадатковы маніторынг працы failover, пры гэтым у нас 12 шардаў PostgreSQL, а значыць мы павінны маніторыць 12 кластараў. Пры павелічэнні колькасці шардов трэба яшчэ не забыцца абнавіць failover.

Самапісны failover выглядае вельмі складана і патрабуе нетрывіяльнай падтрымкі. Пры адным PostgreSQL кластары гэта будзе самым простым варыянтам, але ён не маштабуецца, таму не падыходзіць для нас.

Repmgr

Replication Manager for PostgreSQL clusters, які ўмее кіраваць працай кластара PostgreSQL. Пры гэтым у ім няма аўтаматычнага failover са скрынкі , таму для працы запатрабуецца пісаць сваю абгортку па-над гатовым рашэннем. Так што ўсё можа атрымаецца нават складаней, чым з самапіснымі скрыптамі, таму Repmgr мы нават не сталі спрабаваць.

AWS RDS

Падтрымлівае ўсё неабходнае для нас, умее рабіць бэкапы і падтрымлівае пул канэктаў. Мае аўтаматычнае пераключэнне: пры смерці майстра рэпліка становіцца новым майстрам, а AWS мяняе dns запіс на новага майстра, пры гэтым рэплікі могуць знаходзіцца ў розных AZ.

Да мінусаў можна аднесці адсутнасць тонкіх налад. Як прыклад тонкіх налад: на нашых інстансах стаяць абмежаванні для tcp канэктаў, чаго, нажаль, нельга зрабіць у RDS:

net.ipv4.tcp_keepalive_time=10
net.ipv4.tcp_keepalive_intvl=1
net.ipv4.tcp_keepalive_probes=5
net.ipv4.tcp_retries2=3

Акрамя таго ў AWS RDS кошт амаль у два разы даражэй звычайнага кошту instance, што і паслужыла галоўнай прычынай адмовы ад гэтага рашэння.

Patroni

Гэта шаблон на python для кіравання PostgreSQL з добрай дакументацыяй, аўтаматычным failover і зыходным кодам на github.

Плюсы Patroni:

  • Распісаны кожны параметр канфігурацыі, зразумела як што працуе;
  • Аўтаматычны failover працуе са скрынкі;
  • Напісаны на python, а паколькі мы самі шмат пішам на python, то нам будзе прасцей разбірацца з праблемамі і, магчыма, нават дапамагчы развіццю праекта;
  • Цалкам кіруе PostgreSQL, дазваляе змяняць канфігурацыю адразу на ўсіх нодах кластара, а калі для ўжывання новай канфігурацыі патрабуецца перазапуск кластара, тое гэта можна зрабіць ізноў жа з дапамогай Patroni.

Мінусы:

  • З дакументацыі незразумела, як правільна працаваць з PgBouncer. Хоць мінусам гэта назваць складана, таму што задача Patroni – кіраваць PostgreSQL, а як будуць хадзіць падлучэнні да Patroni – ужо наша праблема;
  • Мала прыкладаў укаранення Patroni на вялікіх аб'ёмах, пры гэтым шмат прыкладаў укаранення з нуля.

У выніку для стварэння адмоваўстойлівага кластара мы абралі менавіта Patroni.

Працэс укаранення Patroni

Да Patroni у нас было 12 шардаў PostgreSQL у канфігурацыі адзін майстар і адна рэпліка з асінхроннай рэплікацыяй. Сервера прыкладання звярталіся да баз дадзеных праз Network Load Balancer, за якім стаялі два instance з PgBouncer, а за імі знаходзіліся ўсе PostgreSQL серверы.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Для ўкаранення Patroni нам трэба было абраць размеркаванае сховішча канфігурацыі кластара. Patroni працуе з размеркаванымі сістэмамі захоўвання канфігурацый, такімі як etcd, Zookeeper, Сonsul. У нас як раз на продзе ёсць паўнавартасны кластар Consul, які працуе ў звязку з Vault і больш мы яго ніяк не выкарыстоўваны. Выдатная нагода пачаць выкарыстоўваць Consul па прызначэнні.

Як працуе Patroni з Consul

У нас ёсць кластар Сonsul, які складаецца з трох нод і кластар Patroni, які складаецца з лідэра і рэплікі (у Patroni майстар называецца лідэрам кластара, а слейвы - рэплікамі). Кожны інстанс кластара Patroni стала пасылае ў Consul інфармацыю аб стане кластара. Таму з Сonsul заўсёды можна пазнаць бягучую канфігурацыю кластара Patroni і таго, хто з'яўляецца лідэрам у дадзены момант.

Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Для падлучэння Patroni да Сonsul дастаткова вывучыць афіцыйную дакументацыю, у якой напісана, што неабходна паказаць хост у фармаце http ці https у залежнасці ад таго, як мы працуем з Сonsul, і схему падлучэння, апцыянальна:

host: the host:port for the Consul endpoint, in format: http(s)://host:port
scheme: (optional) http or https, defaults to http

Выглядае проста, але тут пачынаюцца падводныя камяні. З Сonsul мы працуем па абароненым злучэнні праз https і наш канфіг падключэння будзе выглядаць наступным чынам:

consul:
  host: https://server.production.consul:8080 
  verify: true
  cacert: {{ consul_cacert }}
  cert: {{ consul_cert }}
  key: {{ consul_key }}

Але так не працуе. Пры старце Patroni не можа падлучыцца да Сonsul, таму што спрабуе ўсё роўна ісці па http.

Разабрацца з праблемай дапамог зыходны код Patroni. Добра, што ён напісаны на python. Апыняецца параметр host ніяк не парыцца, а пратакол неабходна паказаць у scheme. Вось так выглядае працавальны блок канфігурацыі для працы з Сonsul у нас:

consul:
  host: server.production.consul:8080
  scheme: https
  verify: true
  cacert: {{ consul_cacert }}
  cert: {{ consul_cert }}
  key: {{ consul_key }}

Consul-template

Такім чынам, сховішча для канфігурацыі мы абралі. Цяпер трэба зразумець, як PgBouncer будзе перамыкаць сваю канфігурацыю пры змене лідэра ў кластары Patroni. У дакументацыі на гэтае пытанне адказу няма, т.я. тамака ў прынцыпе не апісаная праца з PgBouncer.

У пошуках рашэння мы знайшлі артыкул (назву, нажаль, не памятаю), дзе было напісана, што Сonsul-template вельмі дапамог у звязку PgBouncer і Patroni. Гэта падштурхнула нас на даследаванне працы Consul-Template.

Аказалася, што Сonsul-template увесь час маніторыць канфігурацыю кластара PostgreSQL у Сonsul. Пры змене лідэра ён абнаўляе канфігурацыю PgBouncer і адпраўляе каманду на яе перазагрузку.

Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Вялікі плюс template у тым, што ён захоўваецца ў выглядзе кода, таму пры даданні новага шарда дастаткова зрабіць новы коміт і абнавіць template у аўтаматычным рэжыме, падтрымліваючы прынцып Infrastructure as code.

Новая архітэктура з Patroni

У выніку мы атрымалі такую ​​схему працы:
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Усе серверы прыкладання звяртаюцца да балансавальніка → за ім стаяць два instance PgBouncer → на кожным instance запушчаны Сonsul-template, які маніторыць стан кожнага кластара Patroni і сочыць за актуальнасцю канфіга PgBouncer, які накіроўвае запыты на бягучага лідэра кожнага кластара.

Ручное тэсціраванне

Гэтую схему перад высновай на прод мы запусцілі на невялікім тэставым асяроддзі і праверылі працу аўтаматычнага пераключэння. Адкрывалі дошку, перасоўвалі стыкер і ў гэты момант "забівалі" лідэра кластара. У AWS для гэтага дастаткова выключыць інстанс праз кансоль.

Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Стыкер на працягу 10-20 секунд вяртаўся назад, а потым ізноў пачынаў нармальна перамяшчацца. Значыць, кластар Patroni спрацаваў дакладна: змяніў лідэра, адправіў інфармацыю ў Сonsul, а Сonsul-template адразу падхапіў гэтую інфармацыю, замяніў канфігурацыю PgBouncer і адправіў каманду на reload.

Як выжыць пад высокай нагрузкай і захаваць мінімальны даунтайм?

Усё працуе выдатна! Але ўзнікаюць новыя пытанні: Як гэта спрацуе пад высокай нагрузкай? Як хутка і бяспечна раскачаць усё на production?

Адказаць на першае пытанне нам дапамагае тэставае асяроддзе, на якім мы праводзім нагрузачнае тэсціраванне. Яна цалкам ідэнтычная production па архітэктуры і мае згенераваныя тэставыя дадзеныя, якія па аб'ёме прыкладна роўныя production. Мы вырашаем проста "забіць" адзін з майстроў PostgreSQL падчас тэсту і паглядзець, што будзе. Але перад гэтым важна праверыць аўтаматычную раскатку, бо на гэтым асяроддзі ў нас ёсць некалькі шардаў PostgreSQL, так што мы атрымаем выдатнае тэсціраванне канфігурацыйных скрыптоў перад продам.

Абедзве задачы выглядаюць амбіцыйна, але ў нас PostgreSQL 9.6. Можа мы адразу на 11.2/XNUMX абновімся?

Мы вырашаем зрабіць гэта ў 2 этапы: спачатку абнавіць версію да 11.2/XNUMX, потым запусціць Patroni.

Абнаўленне PostgreSQL

Для хуткага абнаўлення версіі PostgreSQL неабходна выкарыстоўваць опцыю -k, у якой ствараюцца hard link на дыску і няма неабходнасці ў капіяванні вашых дадзеных. На базах у 300-400 ГБ абнаўленне займае 1 секунду.

У нас шмат шардаў, таму абнаўленне трэба зрабіць у аўтаматычным рэжыме. Для гэтага мы напісалі Ansible playbook, які выконвае ўвесь працэс абнаўлення за нас:

/usr/lib/postgresql/11/bin/pg_upgrade 
<b>--link </b>
--old-datadir='' --new-datadir='' 
 --old-bindir=''  --new-bindir='' 
 --old-options=' -c config_file=' 
 --new-options=' -c config_file='

Тут важна адзначыць, што перад запускам апгрэйду неабходна выканаць яго з параметрам -check, Каб быць упэўненым у магчымасці апгрэйду. Гэтак жа наш сцэнар робіць падмену канфігаў на час апгрэйду. Сцэнар у нас выканаўся за 30 секунд, гэта выдатны вынік.

Запуск Patroni

Для вырашэння другой праблемы дастаткова зірнуць на канфігурацыю Patroni. У афіцыйным рэпазітары ёсць прыклад канфігурацыі з initdb, які адказвае за ініцыялізацыю новай базы пры першым запуску Patroni. Але так як у нас ёсць ужо гатовая база, то мы проста выдалілі гэты раздзел з канфігурацыі.

Калі мы пачалі ставіць Patroni ужо на гатовы кластар PostgreSQL і запускаць яго, то сутыкнуліся з новай праблемай: абодва сервера запускаліся як leader. Patroni нічога не ведае аб раннім стане кластара і спрабуе запусціць абодва сервера як два асобныя кластары з аднолькавым імем. Для вырашэння гэтай праблемы неабходна выдаліць дырэкторыю з дадзенымі на slave:

rm -rf /var/lib/postgresql/

Гэта неабходна зрабіць толькі на slave!

Пры падлучэнні чыстай рэплікі Patroni робіць basebackup leader і аднаўляе яго на рэпліку, а затым даганяе актуальны стан па wal-логам.

Яшчэ адна складанасць, з якой мы сутыкнуліся, усе кластары PostgreSQL па змаўчанні называюцца main. Калі кожны кластар нічога не ведае пра іншы - гэта нармальна. Але калі вы хочаце выкарыстоўваць Patroni, то ўсе кластара павінны мець унікальнае імя. Рашэнне - памяняць імя кластара ў канфігурацыі PostgreSQL.

Нагрузачны тэст

Мы запусцілі тэст, які імітуе працу карыстальнікаў на дошках. Калі нагрузка дасягнула нашага сярэдняга дзённага значэння, мы паўтарылі сапраўды такі ж тэст, мы выключылі 20 instance з leader PostgreSQL. Аўтаматычны failover спрацаваў так, як мы чакалі: Patroni змяніў лідэра, Сonsul-template абнавіў канфігурацыю PgBouncer і адправіў каманду на reload. Па нашых графікамі ў Grafana было бачна, што ёсць затрымкі на 30-XNUMX секунд і невялікі аб'ём памылак з сервераў, звязаных са злучэннем да базы. Гэта нармальная сітуацыя, такія значэнні дапушчальныя для нашага failover і сапраўды лепш, чым даунтайм сэрвісу.

Выснова Patroni на production

У выніку ў нас атрымаўся наступны план:

  • Дэплой Сonsul-template на серверы PgBouncer і запуск;
  • Абнаўленні PostgreSQL да версіі 11.2;
  • Змена імя кластара;
  • Запуск кластара Patroni.

Пры гэтым наша схема дазваляе зрабіць першы пункт практычна ў любы час, мы можам па чарзе прыбраць кожны PgBouncer з працы і выканаць на яго дэплой і запуск consul-template. Так мы і зрабілі.

Для хуткага раскочвання мы выкарыстоўвалі Ansible, бо ўсе playbook мы ўжо праверылі на тэставым асяроддзі, а час выканання поўнага сцэнара было ад 1,5 да 2 хвілін для кожнага шарда. Мы маглі ўсё выкаціць па чарзе на кожны шард без спынення нашага сэрвісу, але нам прыйшлося б на некалькі хвілін выключаць кожны PostgreSQL. У гэтым выпадку карыстачы, чые дадзеныя ёсць на гэтым шардзе, не маглі б паўнавартасна працаваць у гэты час, а гэта для нас непрымальна.

Выйсцем з гэтай сітуацыі стаў планавы maintenance, які праходзіць у нас кожныя 3 месяцы. Гэта акно для планавых работ, калі мы поўнасцю выключаем наш сэрвіс і абнаўляем інстансы баз дадзеных. Да чарговага акна заставаўся адзін тыдзень, і мы вырашылі проста пачакаць і дадаткова падрыхтавацца. За час чакання мы дадаткова падстрахаваліся: для кожнага шарда PostgreSQL паднялі па запасной рэпліцы на выпадак няўдачы, каб захаваць самыя апошнія дадзеныя, і дадалі па новым інстансе для кожнага шарда, які павінен стаць новай рэплікай у кластары Patroni, каб не выконваць каманду для выдалення дадзеных . Усё гэта дапамагло максімальна зменшыць рызыку памылкі.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Мы перазапусцілі наш сэрвіс, усё зарабіла як трэба, карыстачы працягнулі працаваць, але на графіках мы заўважылі анамальна высокую нагрузку на Сonsul-сервера.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

Чаму мы не ўбачылі гэта на тэставым асяроддзі? Гэта праблема вельмі добра ілюструе, што неабходна прытрымлівацца прынцыпу Infrastructure as code і дапрацоўваць усю інфраструктуру, пачынаючы з тэставых асяроддзяў і заканчваючы production. Інакш вельмі лёгка атрымаць такую ​​праблему, якую мы атрымалі. Што адбылося? Сonsul спачатку з'явіўся на production, а потым на тэставых асяроддзях, у выніку на тэставых асяроддзях версія Consul была вышэй, чым на production. Як раз у адным з рэлізаў была вырашана ўцечка CPU пры працы з consul-template. Таму мы проста абнавілі Consul, вырашыўшы такім чынам праблему.

Restart Patroni cluster

Аднак мы атрымалі новую праблему, пра якую нават не падазравалі. Пры абнаўленні Consul мы проста выдаляем ноду Consul з кластара з дапамогай каманды consul leave → Patroni падлучаецца да іншага Consul серверу → усё працуе. Але калі мы дайшлі да апошняга інстансу кластара Consul і адправілі яму каманду consul leave, усе кластары Patroni проста перазапусціліся, а ў логах мы ўбачылі наступную памылку:

ERROR: get_cluster
Traceback (most recent call last):
...
RetryFailedError: 'Exceeded retry deadline'
ERROR: Error communicating with DCS
<b>LOG: database system is shut down</b>

Кластар Patroni не змог атрымаць інфармацыю аб сваім кластары і перазапусціў.

Для пошуку рашэння мы звярнуліся да аўтараў Patroni праз issue на github. Яны прапанавалі паляпшэнні нашых канфігурацыйных файлаў:

consul:
 consul.checks: []
bootstrap:
 dcs:
   retry_timeout: 8

Мы змаглі паўтарыць праблему на тэставым асяроддзі і пратэставалі там гэтыя параметры, але, нажаль, яны не спрацавалі.

Праблема да гэтага часу застаецца нявырашанай. Мы плануем паспрабаваць наступныя варыянты рашэння:

  • Выкарыстоўваць Сonsul-agent на кожным інстансе кластара Patroni;
  • Выправіць праблему ў кодзе.

Нам зразумела месца ўзнікнення памылкі: верагодна, праблема ў выкарыстанні default timeout, які не перавызначаецца праз файл канфігурацыі. Пры выдаленні апошняга сервера Сonsul з кластара адбываецца завісанне ўсяго Сonsul-кластара, якое доўжыцца даўжэй секунды, з-за гэтага Patroni не можа атрымаць стан кластара і цалкам перазапускае ўвесь кластар.

На шчасце, болей ніякіх памылак мы не сустрэлі.

Вынікі выкарыстання Patroni

Пасля паспяховага запуску Patroni мы дадалі па дадатковай рэпліцы ў кожным кластары. Цяпер у кожным кластары ёсць падабенства кворуму: адзін лідэр і дзве рэплікі, - для падстрахоўкі на выпадак split-brain пры пераключэнні.
Адмоўаўстойлівы кластар PostgreSQL + Patroni. Вопыт укаранення

На production Patroni працуе больш за тры месяцы. За гэты час ён ужо паспеў нас выбавіць. Нядаўна ў AWS памёр лідэр аднаго з кластараў, аўтаматычны failover спрацаваў і карыстачы працягнулі працаваць. Patroni выканаў сваю галоўную задачу.

Невялікі вынік выкарыстання Patroni:

  • Выгода змены канфігурацыі. Дастаткова змяніць канфігурацыю на адным інстансе і яна падцягнецца на ўвесь кластар. Калі патрабуецца перазагрузка для прымянення новай канфігурацыі, то Patroni пра гэта паведаміць. Patroni можа перазапусціць увесь кластар з дапамогай адной каманды, што таксама вельмі зручна.
  • Аўтаматычны failover працуе і ўжо паспеў нас выбавіць.
  • Абнаўленне PostgreSQL без даунтайма прыкладання. Неабходна спачатку абнавіць рэплікі на новую версію, затым змяніць лідара ў кластары Patroni і абнавіць старога лідара. Пры гэтым адбываецца неабходнае тэсціраванне аўтаматычнага failover.

Крыніца: habr.com

Дадаць каментар