{"id":90103,"date":"2020-07-29T13:42:32","date_gmt":"2020-07-29T11:42:32","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij"},"modified":"2020-07-29T13:42:32","modified_gmt":"2020-07-29T11:42:32","slug":"patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij","title":{"rendered":"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/6404cba13214f499d1f347cca0aacbe7.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hovedm\u00e5let med Patroni er at sikre h\u00f8j tilg\u00e6ngelighed for PostgreSQL. Men Patroni er blot en skabelon og ikke et klart v\u00e6rkt\u00f8j (som det faktisk er n\u00e6vnt i dokumentationen). Ved f\u00f8rste \u00f8jekast, n\u00e5r man ops\u00e6tter Patroni i et testmilj\u00f8, kan man se, hvor nyttigt det er, og hvordan det nemt h\u00e5ndterer vores fors\u00f8g p\u00e5 at nedbryde klyngen. Men i praksis, i et produktionsmilj\u00f8, g\u00e5r det ikke altid s\u00e5 smukt og elegant, som i testmilj\u00f8et.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/ff445e6d76a2ad46a232b705e104446f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lad mig fort\u00e6lle lidt om mig selv. Jeg startede som systemadministrator. Jeg har arbejdet med webudvikling. Siden 2014 har jeg arbejdet hos Data Egret. Virksomheden besk\u00e6ftiger sig med r\u00e5dgivning inden for Postgres. Og vi betjener specifikt Postgres og arbejder med det hver dag, s\u00e5 vi har forskellig ekspertise forbundet med driften. <\/p>\n<p><\/p>\n<p>I slutningen af 2018 begyndte vi stille og roligt at bruge Patroni. Der er samlet erfaring, og vi har diagnosticeret det, finjusteret det og n\u00e5et frem til vores bedste praksis. Og i denne pr\u00e6sentation vil jeg tale om dem.<\/p>\n<p><\/p>\n<p>Udover Postgres kan jeg ogs\u00e5 godt lide Linux. Jeg elsker at dykke ned i det og udforske det, jeg kan godt lide at kompilere kerner. Jeg elsker virtualisering, containere, Docker, Kubernetes. Alt dette interesserer mig, fordi det er pr\u00e6get af gamle administratorvaner. Jeg elsker at finde ud af noget om overv\u00e5gning. Og jeg elsker Postgres-relaterede opgaver som administration, det vil sige replikation og backup. I min fritid skriver jeg i Go. Jeg er ikke softwareingeni\u00f8r, men jeg skriver bare for min egen skyld i Go. Og jeg nyder det. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/02cfd9293af5a8410c91e39afe2c75e6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Jeg tror, mange af jer ved, at der ikke er HA (h\u00f8j tilg\u00e6ngelighed) i PostgreSQL som standard. For at f\u00e5 HA skal man installere noget, konfigurere det, l\u00e6gge kr\u00e6fter i det og opn\u00e5 det. <\/li>\n<li>Der er flere v\u00e6rkt\u00f8jer, og Patroni er et af dem, der l\u00f8ser HA p\u00e5 en ret cool og effektiv m\u00e5de. Men n\u00e5r vi s\u00e6tter det hele op i et testmilj\u00f8 og starter det, kan vi se, at det fungerer, vi kan genskabe nogle problemer, se hvordan Patroni h\u00e5ndterer dem, og vi vil se, at det hele fungerer glimrende. <\/li>\n<li>Men i praksis har vi st\u00f8dt p\u00e5 forskellige problemer. Og jeg vil tale om disse problemer.<\/li>\n<li>Jeg vil fort\u00e6lle, hvordan vi diagnosticerede det, hvad vi justerede - hjalp det os eller ikke. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/7126b45b40dd08521e80a3c150382bec.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Jeg vil ikke fort\u00e6lle, hvordan man installerer Patroni, fordi man kan finde det p\u00e5 internettet, man kan se konfigurationsfilerne for at forst\u00e5, hvordan det hele startes og konfigureres. Man kan f\u00e5 indsigt i diagrammer og arkitekturer ved at finde information om dette online. <\/li>\n<li>Jeg vil ikke tale om andres erfaringer. Jeg vil kun fort\u00e6lle om de problemer, som vi selv stod overfor. <\/li>\n<li>Jeg vil heller ikke tale om problemer, der ligger uden for Patroni og PostgreSQL. For eksempel, n\u00e5r vi har problemer med balancering, is\u00e6r hvis vores klynge falder fra hinanden, vil jeg ikke tale om det. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/3f8d179e7c78ce83e8842ef5c72fe30d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og en lille disclaimer, inden jeg starter vores pr\u00e6sentation. <\/p>\n<p><\/p>\n<p>Alle de problemer, vi stod overfor, opstod i de f\u00f8rste 6-7-8 m\u00e5neder af driften. Med tiden udviklede vi vores interne best practices, og problemerne forsvandt. S\u00e5 pr\u00e6sentationen blev planlagt for cirka et halvt \u00e5r siden, da alt dette stadig var friskt i hukommelsen, og jeg huskede det klart. <\/p>\n<p><\/p>\n<p>Under forberedelsen til pr\u00e6sentationen kiggede jeg tilbage p\u00e5 gamle post-mortems og gennemgik logfilerne. Nogle detaljer kunne v\u00e6re glemt, eller nogle aspekter kunne v\u00e6re underforsket under analysen af problemerne, s\u00e5 i nogle tilf\u00e6lde kan det virke, som om problemerne ikke er blevet fuldt ud behandlet, eller der mangler information. Jeg beder om tolmodighed med dette. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/30d414284a41fcbc3bf417c9da28ca52.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvad er Patroni?<\/p>\n<p><\/p>\n<ul>\n<li>Det er en skabelon til opbygning af HA. S\u00e5dan st\u00e5r der i dokumentationen. Og fra mit synspunkt er det en meget korrekt pr\u00e6cisering. Patroni er ikke en s\u00f8lvkugle, der vil l\u00f8se alle dine problemer, dvs. det kr\u00e6ver en indsats for at f\u00e5 det til at fungere og bringe v\u00e6rdi. <\/li>\n<li>Det er en agenttjeneste, der installeres p\u00e5 hver tjeneste med en database, og som fungerer som en slags init-system for din Postgres. Den starter Postgres, stopper den, genstarter den, \u00e6ndrer konfigurationen og \u00e6ndrer topologien i din klynge. <\/li>\n<li>For at gemme tilstanden af klyngen, dens nuv\u00e6rende repr\u00e6sentation af, hvordan den ser ud, er der brug for et lager. Fra denne synsvinkel har Patroni valgt at gemme tilstande i et eksternt system. Det er et system til distribueret konfiguration. Det kan v\u00e6re Etcd, Consul, ZooKeeper eller kubernetes' Etcd, alts\u00e5 en af disse muligheder. <\/li>\n<li>En af funktionerne ved Patroni er, at du f\u00e5r auto-failover direkte ud af boksen, s\u00e5 l\u00e6nge du konfigurerer det. I sammenligning med Repmgr, f\u00e5r du failover som en del af pakken. Med Repmgr f\u00e5r vi switchover, men hvis vi \u00f8nsker auto-failover, skal det konfigureres separat. Patroni har allerede auto-failover klar fra starten.<\/li>\n<li>Og der er mange andre ting. For eksempel h\u00e5ndtering af konfigurationer, tilf\u00f8jelse af nye replikaer, sikkerhedskopiering osv. Men det ligger uden for denne pr\u00e6sentation, s\u00e5 jeg vil ikke tale om det. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/fed0f1ce931df99ca76ae1116f8098cc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og en kort opsummering \u2013 den prim\u00e6re opgave for Patroni er at sikre en god og p\u00e5lidelig auto-failover, s\u00e5 vores kluster forbliver operationelt, og applikationen ikke bem\u00e6rker \u00e6ndringer i klusterets topologi. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/fac52620957efa47ced330e7cc8084e0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Men n\u00e5r vi begynder at bruge Patroni, bliver vores system en smule mere komplekst. Hvis vi tidligere havde Postgres, f\u00e5r vi nu b\u00e5de Patroni og et DCS, hvor tilstanden opbevares. Og alt dette skal fungere sammen. Hvad kan g\u00e5 galt?<\/p>\n<p><\/p>\n<p>Her er hvad der kan g\u00e5 galt:<\/p>\n<p><\/p>\n<ul>\n<li>Postgres kan g\u00e5 ned. Dette kan v\u00e6re enten master eller replika, en af dem kan fejle. <\/li>\n<li>Selve Patroni kan ogs\u00e5 g\u00e5 ned. <\/li>\n<li>DCS kan g\u00e5 ned, hvor tilstanden opbevares.<\/li>\n<li>Og netv\u00e6rket kan ogs\u00e5 fejle. <\/li>\n<\/ul>\n<p><\/p>\n<p>Jeg vil komme ind p\u00e5 alle disse punkter i pr\u00e6sentationen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/1aeaf46d37bf1935b514b0581e0dbd0b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeg vil se p\u00e5 tilf\u00e6lde i takt med, at de bliver mere komplekse, ikke ud fra, at sagen involverer mange komponenter. Men ud fra subjektive oplevelser, hvor nogle sager har v\u00e6ret sv\u00e6re at analysere... og omvendt, hvor andre sager har v\u00e6ret nemmere. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/65b0c98bf2284610e955ced5eb998f39.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og det f\u00f8rste tilf\u00e6lde er det enkleste. Det er n\u00e5r vi tager en database-kluster og p\u00e5 samme kluster implementerer vores DCS-lager. Dette er den mest almindelige fejl. Det er en arkitektonisk fejl, dvs. at kombinere forskellige komponenter p\u00e5 \u00e9t sted. <\/p>\n<p><\/p>\n<p>S\u00e5, der skete en failover, lad os finde ud af, hvad der var sket. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/244b69d623fe2205c2d9ed2aa4620067.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og her er vi interesserede i, hvorn\u00e5r failoveren skete. Dvs. vi er interesserede i det \u00f8jeblik, hvor der skete en \u00e6ndring i klusterets tilstand. <\/p>\n<p><\/p>\n<p>Men failover er ikke altid \u00f8jeblikkelig, d.v.s. det tager ikke en bestemt tid; det kan tage lidt l\u00e6ngere, og det kan vare ved.<\/p>\n<p><\/p>\n<p>Derfor har det en starttid og en sluttid, dvs. det er en langvarig begivenhed. Vi opdeler alle begivenheder i tre intervaller: vi har tid f\u00f8r failover, under failover og efter failover. Dvs. vi ser p\u00e5 alle begivenheder p\u00e5 denne tidslinje. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a0ed61afe55d1a157147e0d80b17e5d1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og det f\u00f8rste, vi g\u00f8r, n\u00e5r failover sker, er at finde \u00e5rsagen, hvad der skete, der f\u00f8rte til failover. <\/p>\n<p><\/p>\n<p>Hvis vi ser p\u00e5 loggene, vil det v\u00e6re de klassiske Patroni-logs. Her fort\u00e6ller den os, at serveren blev master, og rollen som master blev overf\u00f8rt til denne node. Dette er fremh\u00e6vet. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/9998c69f7d0d4358b277f4e0e7b4350f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dern\u00e6st skal vi forst\u00e5, hvorfor failover skete, dvs. hvilke begivenheder der fik rollen som master til at flytte fra en node til en anden. Og i dette tilf\u00e6lde er det ret simpelt. Vi har en fejl i interaktionen med opbevaringssystemet. Masteren forstod, at den ikke kunne arbejde med DCS, dvs. der opstod et eller andet problem med interaktionen. Og den siger, at den ikke l\u00e6ngere kan v\u00e6re master og fratr\u00e6der sine bef\u00f8jelser. Denne linje 'demoted self' siger netop dette. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/4a8eca27689546b4b0fc3c666a3c37c4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvis vi ser p\u00e5 de begivenheder, der gik forud for failover, kan vi se de samme \u00e5rsager, der var problemet for forts\u00e6ttelsen af masterens arbejde. <\/p>\n<p><\/p>\n<p>Hvis vi ser p\u00e5 Patroni-loggene, ser vi, at vi har en masse fejl, timeouts, dvs. Patroni-agenten kan ikke arbejde med DCS. I dette tilf\u00e6lde er det Consul-agenten, som kommunikerer via port 8500. <\/p>\n<p><\/p>\n<p>Og problemet her er, at Patroni og databasen k\u00f8rer p\u00e5 samme v\u00e6rt. Og p\u00e5 denne node k\u00f8rte ogs\u00e5 Consul-serverne. Ved at skabe belastning p\u00e5 serveren skabte vi problemer for <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/da\/server\/\"   title=\"servere\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1515\">servere<\/a> Consul. De kunne ikke kommunikere ordentligt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/0d8dba6641809560e6b32825d481e30b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Efter lidt tid, n\u00e5r belastningen faldt, kunne vores Patroni igen kommunikere med agenterne. Den normale drift genoptog. Og den samme server Pgdb-2 blev igen master. Dvs. der var et lille flip, der fik noden til at fratr\u00e6de sine masterbef\u00f8jelser, og derefter tog den dem tilbage, dvs. alt blev som f\u00f8r. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/131b93e0bd83099e1b99b53742419e13.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og dette kan betragtes som en falsk udl\u00f8ser, eller det kan ses som om, at Patroni gjorde det rigtige. Dvs. den forstod, at den ikke kunne opretholde tilstanden i klyngen og fratr\u00e5dte sine bef\u00f8jelser.<\/p>\n<p><\/p>\n<p>Og problemet opstod, fordi Consul-serverne er p\u00e5 det samme udstyr som databaserne. Derfor p\u00e5virker enhver belastning, hvad enten det er belastning p\u00e5 diske eller processorer, ogs\u00e5 interaktionen med Consul-klusteret.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/142c7cf839c8da078451f7ba9d5499e5.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og vi besluttede, at dette ikke skulle leve sammen, vi har tildelt en separat klynge til Consul. Og Patroni arbejdede allerede med en separat Consul, dvs. der var en separat Postgres-klynge og en separat Consul-klynge. Dette er den grundl\u00e6ggende instruktion om, hvordan man skal adskille alle disse ting og holde dem, s\u00e5 de ikke lever sammen. <\/p>\n<p><\/p>\n<p>Som et alternativ kan man justere parametrene ttl, loop_wait, retry_timeout, dvs. fors\u00f8ge at overleve de kortvarige belastningsspidser ved at \u00f8ge disse parametre. Men det er ikke den mest hensigtsm\u00e6ssige l\u00f8sning, fordi denne belastning kan v\u00e6re langvarig. Og vi vil simpelthen overskride gr\u00e6nserne for disse parametre. Og det kan muligvis ikke hj\u00e6lpe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/c51f35dcd88b1c792acec231c0c6c66c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det f\u00f8rste problem, som du forst\u00e5r, er simpelt. Vi lagde DCS sammen med databasen og fik dermed et problem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/cc2a98d9790441577fb4080406cbc53f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det andet problem ligner det f\u00f8rste. Det ligner ved, at vi endnu en gang har problemer med interaktionen med DCS-systemet.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/e5c01b105adca48cc620085db8dd2d2b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvis vi ser p\u00e5 loggene, vil vi se, at vi igen har en kommunikationsfejl. Og Patroni siger, at jeg ikke kan interagere med DCS, s\u00e5 den nuv\u00e6rende master skifter til replika-tilstand.<\/p>\n<p><\/p>\n<p>Den gamle master bliver en replika, her virker Patroni som forventet. Den k\u00f8rer pg_rewind for at spole transaktionsjournalen tilbage og derefter forbinder til den nye master og indhenter den nye master. Her fungerer Patroni som han skal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/29255f4790abb15b64dbf9ee0b41c7fc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Her skal vi finde det sted, der forudgik filev\u00e5geren, dvs. de fejl, der for\u00e5rsagede, at vi fik en filev\u00e5ger. Og i den henseende er det ret nemt at arbejde med loggene i Patroni. Den skriver de samme meddelelser med bestemte intervaller. Og hvis vi begynder hurtigt at spole gennem disse logs, vil vi se i loggene, at loggene har \u00e6ndret sig, hvilket betyder, at der er begyndt at opst\u00e5 problemer. Vi g\u00e5r hurtigt tilbage til det sted, ser hvad der foreg\u00e5r. <\/p>\n<p><\/p>\n<p>Og i en normal situation ser loggene omtrent s\u00e5dan ud. Ejeren af l\u00e5sen tjekkes. Og hvis ejeren for eksempel er skiftet, kan der opst\u00e5 nogle begivenheder, som Patroni skal reagere p\u00e5. Men i dette tilf\u00e6lde er alt i orden. Vi leder efter det sted, hvor fejlene begyndte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/f48ebd22a405f5b2900621451c68f543.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og n\u00e5r vi ruller tilbage til det punkt, hvor fejlene begyndte at opst\u00e5, ser vi, at der skete en auto-failover. Da vores fejl var relateret til interaktionen med DCS, og i vores tilf\u00e6lde brugte vi Consul, ser vi ogs\u00e5 i Consul-loggene, hvad der skete der. <\/p>\n<p><\/p>\n<p>Ved omtrent at matche tiden for failoveren med tiden i Consul-loggene ser vi, at vores naboer i Consul-klusteret begyndte at tvivle p\u00e5 eksistensen af andre medlemmer af Consul-klusteret.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/63b02ac5b4f5a34a2822f1eee2b1f2f8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og hvis vi kigger p\u00e5 loggene fra andre Consul-agenter, kan vi ogs\u00e5 se, at der sker en form for netv\u00e6rks-kollaps. Og alle medlemmer af Consul-klusteret tvivler p\u00e5 hinandens eksistens. Og dette var en katalysator for failoveren. <\/p>\n<p><\/p>\n<p>Hvis vi ser p\u00e5, hvad der skete f\u00f8r disse fejl, kan vi se, at der har v\u00e6ret forskellige fejl, for eksempel deadline og RPC fejl, det vil sige, der er tydeligvis et problem med interaktionen mellem medlemmerne af Consul-klusteret. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/b15c912f2afb49d9d85e7bb9361ce449.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det simpleste svar er at reparere netv\u00e6rket. Men for mig, som st\u00e5r p\u00e5 talerstolen, er det nemt at sige. Men forholdene er s\u00e5dan, at kunden ikke altid har mulighed for at reparere netv\u00e6rket. De kan v\u00e6re i datacentret og have begr\u00e6nsede muligheder for at reparere netv\u00e6rket eller p\u00e5virke udstyret. S\u00e5 derfor er der behov for andre l\u00f8sninger. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/1dbdb66233acc3bc321a30a1c5fe14f9.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der er muligheder:<\/p>\n<p><\/p>\n<ul>\n<li>Den simpleste l\u00f8sning, som endda er beskrevet i dokumentationen, er at deaktivere Consul-tjek, det vil sige simpelthen at sende et tomt array. Og vi beder Consul-agenten om ikke at bruge nogen tjek. Ved hj\u00e6lp af disse tjek kan vi ignorere disse netv\u00e6rksstorme og undg\u00e5 at initiere failover. <\/li>\n<li>En anden mulighed er at genchecke raft_multiplier. Dette er en parameter for selve Consul-serveren. Som standard er den sat til 5. Dette niveau anbefales i dokumentationen til staging-milj\u00f8er. I bund og grund p\u00e5virker det frekvensen af beskedudveksling mellem medlemmerne af Consul-netv\u00e6rket. Denne parameter p\u00e5virker i princippet hastigheden af kommunikation mellem medlemmerne af Consul-klusteret. Og for produktion anbefales det allerede at s\u00e6nke det, s\u00e5 noderne oftere udveksler beskeder. <\/li>\n<li>En anden mulighed, vi er begyndt at bruge, er at \u00f8ge prioriteten af Consul-processerne blandt de \u00f8vrige processer for operativsystemets procesplanl\u00e6gger. Der er en parameter kaldet \"nice\", som netop definerer prioriteten for processerne, der tages i betragtning af OS-planl\u00e6ggeren ved planl\u00e6gning. Vi har s\u00e6nket nice-v\u00e6rdien for Consul-agenterne, alts\u00e5 h\u00e6vet prioriteten, s\u00e5 operativsystemet giver Consul-proceserne mere tid til at arbejde og udf\u00f8re deres kode. I vores tilf\u00e6lde l\u00f8ste det vores problem. <\/li>\n<li>En anden mulighed er ikke at bruge Consul. Jeg har en ven, der er stor tilh\u00e6nger af Etcd. Og vi sk\u00e6ndes regelm\u00e6ssigt om, hvad der er bedre, Etcd eller Consul. Men n\u00e5r det kommer til hvad der er bedst, er vi normalt enige om, at Consul har en agent, der skal k\u00f8re p\u00e5 hver node med databasen. Det vil sige, at interaktionen mellem Patroni og Consul-klusteret foreg\u00e5r gennem denne agent. Og denne agent bliver et flaskehals. Hvis der sker noget med agenten, kan Patroni ikke l\u00e6ngere arbejde med Consul-klusteret. Og det er et problem. I forhold til Etcd er der ingen agent. Patroni kan arbejde direkte med listen af Etcd-servere og kommunikere med dem. P\u00e5 den m\u00e5de, hvis I bruger Etcd i jeres virksomhed, vil Etcd nok v\u00e6re det bedste valg frem for Consul. Men hos vores kunder er vi altid begr\u00e6nset af, hvad kunden har valgt at bruge. Og for det meste har alle kunder Consul. <\/li>\n<li>Og det sidste punkt er at gennemg\u00e5 parameterne. Vi kan h\u00e6ve disse parametre i en st\u00f8rre retning i h\u00e5bet om, at vores kortvarige netv\u00e6rksproblemer vil v\u00e6re korte og ikke overstige intervallet for disse parametre. P\u00e5 den m\u00e5de kan vi mindske Patronis aggressivitet ved udf\u00f8relsen af automatiserede failovers, hvis der opst\u00e5r netv\u00e6rksproblemer.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/f0043050da20f6368dabf66ec9a4eade.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeg tror, at mange, der bruger Patroni, er bekendt med denne kommando. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/9f78f59dab166e47ac78436802156d04.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Denne kommando viser den aktuelle tilstand af klusteret. Og ved f\u00f8rste \u00f8jekast kan dette billede se normalt ud. Vi har en master, vi har en replika, der er ingen replikationslag. Men dette billede er normalt kun indtil vi ved, at der skal v\u00e6re tre noder i dette kluster, ikke kun to. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a39c891f8620ba210b6bce0727e0fa8b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Derfor blev auto-failover aktiveret. Efter dette auto-failover mistede vi replikatet. Vi skal finde ud af, hvorfor det forsvandt, og f\u00e5 det tilbage, genskabe det. Vi g\u00e5r igen ind i loggene og kigger p\u00e5, hvad der for\u00e5rsagede auto-failover.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/e6e67d46cb20c8d7e58c7505157f68e1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I dette tilf\u00e6lde blev den anden replika master. Alt er i orden her. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/b86ccea68b0c6013a23bbd2804e48320.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi skal se p\u00e5 replikaen, der er falmet, og som ikke er i klyngen. Vi \u00e5bner loggene fra Patroni og ser, at der opstod et problem i forbindelse med at tilslutte sig klyngen under pg_rewind. For at tilslutte sig klyngen skal vi spole transaktionsloggen tilbage, anmode om den n\u00f8dvendige transaktionslog fra masteren og indhente masteren. <\/p>\n<p><\/p>\n<p>I dette tilf\u00e6lde har vi ikke transaktionsloggen, og replikatet kan ikke starte. Derfor stopper vi Postgres med en fejl. Og derfor er den ikke i klyngen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/dadbd44b766674b719d85781ef7f0caa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi skal forst\u00e5, hvorfor den ikke er i klyngen, og hvorfor der ikke var logs. Vi g\u00e5r til den nye master og ser, hvad der er i dens logs. Det viser sig, at da pg_rewind blev udf\u00f8rt, opstod der et checkpoint. Og nogle af de gamle transaktionslogs blev simpelthen omd\u00f8bt. Da den gamle master fors\u00f8gte at tilslutte sig den nye master og anmode om disse logs, var de allerede blevet omd\u00f8bt, de var simpelthen ikke tilg\u00e6ngelige.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/f2d5c37324f9436b2bdad1290612d86f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeg har sammenlignet tidsstempler, da disse begivenheder fandt sted. Der var kun 150 millisekunders forskel, dvs. checkpointet blev afsluttet p\u00e5 369 millisekunder, og WAL-segmenterne blev omd\u00f8bt. Og blot 517 millisekunder senere, efter 150 millisekunder, blev rewind startet p\u00e5 den gamle replika. Dvs. vi havde bogstaveligt talt brug for 150 millisekunder for at sikre, at replikatet ikke kunne tilslutte sig og komme i gang. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/99dd80deb8466bfc3aff568456e07102.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den dyreste og mest omfattende l\u00f8sning er Redis-Enterprise. Dette er en pakkel\u00f8sning med fuld teknisk support. Selvom det ser ideelt ud fra en teknisk synsvinkel, var det ikke passende for os af ideologiske \u00e5rsager.<\/p>\n<p><\/p>\n<p>Vi brugte oprindeligt replikationsslots. Vi troede, det var godt. Selvom vi i den f\u00f8rste fase af driften deaktiverede slots. Vi troede, at hvis slots skulle samle mange WAL-segmenter, kunne vi bringe masteren ned. Den ville falde. Vi k\u00e6mpede et stykke tid uden slots. Og vi inds\u00e5, at vi havde brug for slots, s\u00e5 vi genoptog dem. <\/p>\n<p><\/p>\n<p>Men der er et problem: n\u00e5r masteren g\u00e5r over til replikaen, sletter den slots, og sammen med slots sletter den WAL-segmenter. For at undg\u00e5 dette problem besluttede vi at h\u00e6ve parameteren wal_keep_segments. Den er som standard 8 segmenter. Vi h\u00e6vede den til 1.000 og s\u00e5 p\u00e5, hvor meget ledig plads vi havde. Og vi gav 16 gigabyte til wal_keep_segments. Dvs. ved omstilling har vi altid en buffer p\u00e5 16 gigabyte transaktionslogs p\u00e5 alle noder.<\/p>\n<p><\/p>\n<p>Og desuden \u2013 det er ogs\u00e5 relevant for l\u00e6ngere vedligeholdelsesopgaver. Antag, at vi skal opdatere en af replikaerne. Og vi vil gerne slukke den. Vi skal opdatere softwaren, m\u00e5ske operativsystemet, noget andet. Og n\u00e5r vi slukker replikaen, slettes ogs\u00e5 slotten for denne replika. Og hvis vi bruger en lille wal_keep_segments, s\u00e5 n\u00e5r replikaen er frav\u00e6rende i l\u00e6ngere tid, vil transaktionslogfilerne blive afspillet. Vi genstarter replikaen, den vil anmode om de transaktionslogs, hvor den stoppede, men de kan v\u00e6re utilg\u00e6ngelige p\u00e5 masteren. Og replikaen vil heller ikke kunne tilslutte sig. Derfor holder vi en stor buffer af logs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/dad55c828128ce92f649a99cc53ce54b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/63e70f0b098567f3a6d4fd66a0c293bb.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi har en produktionsdatabase. Der arbejder projekter allerede. <\/p>\n<p><\/p>\n<p>Der skete en filfejl. Vi gik ind og s\u00e5 \u2013 alt er i orden, replikaerne er p\u00e5 plads, der er ingen replikeringslag. Der er heller ingen fejl i logs, alt er i orden. <\/p>\n<p><\/p>\n<p>Produktteamet siger, at der tilsyneladende skulle v\u00e6re nogle data, men vi ser dem kun i en kilde, og i databasen kan vi ikke se dem. Og vi skal finde ud af, hvad der skete med dem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/568ca9aa31680d5e0c9d4ed9693b14e6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det er klart, at pg_rewind overskrev dem. Det forstod vi straks, men vi gik for at se, hvad der skete. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a8fee389201d96e81761cd276c5265c3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I logs kan vi altid finde ud af, hvorn\u00e5r filfejlen skete, hvem der blev master, og vi kan bestemme, hvem den gamle master var, og hvorn\u00e5r den \u00f8nskede at blive replika, dvs. vi har brug for disse logs for at afklare, hvor meget af transaktionslogs der gik tabt.<\/p>\n<p><\/p>\n<p>Vores gamle master genstartede. Og i autostart var Patroni angivet. Patroni startede. Han startede Postgres lige efter. Mere pr\u00e6cist, f\u00f8r starten af Postgres og f\u00f8r han gjorde det til en replika, startede Patroni processen pg_rewind. F\u00f8lgelig slettede han en del af transaktionsjournalerne, downloadede nye og oprettede forbindelse. Her arbejdede Patroni fantastisk, dvs. som det skulle v\u00e6re. Klyngen blev gendannet. Vi havde 3 noder, efter failoveren havde vi 3 noder \u2013 alt var super. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/b747a24f53e20ed098c2dc0afc79bead.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi har mistet en del data, og vi skal forst\u00e5, hvor meget vi har mistet. Vi leder efter det pr\u00e6cise tidspunkt, hvor vi havde rewind. Vi kan finde det ud fra disse logposter. Rewind blev startet, gjorde noget, og blev afsluttet.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/5b7bacffb52e3ccd529a3a734c441295.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi skal finde den position i transaktionsloggen, hvor den gamle master stoppede. I dette tilf\u00e6lde er det denne markering. Og vi har brug for den anden markering, dvs. den afstand, som adskiller den gamle master fra den nye. <\/p>\n<p><\/p>\n<p>Vi bruger den almindelige pg_wal_lsn_diff og sammenligner disse to markeringer. Og i dette tilf\u00e6lde f\u00e5r vi 17 megabyte. Om det er meget eller lidt, bestemmer hver for sig. Fordi for nogen er 17 megabyte lidt, for andre er det meget og uacceptabelt. Det afh\u00e6nger helt af forretningens behov. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/55335fce85961e159459c38300a0ad12.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Men hvad har vi konstateret for os selv? <\/p>\n<p><\/p>\n<p>For det f\u00f8rste skal vi afg\u00f8re, om vi altid har brug for automatisk opstart af Patroni efter systemgenstart. Ofte er det s\u00e5dan, at vi skal tilg\u00e5 den gamle master, se hvor langt den er kommet. M\u00e5ske inspicere segmenterne i transaktionsloggen, se hvad der er der. Og forst\u00e5, om vi kan miste disse data, eller om vi skal starte den gamle master i standalone-tilstand for at hente disse data. <\/p>\n<p><\/p>\n<p>Og f\u00f8rst derefter skal vi tr\u00e6ffe beslutning om, hvorvidt vi kan lade disse data g\u00e5, eller om vi kan genoprette dem og tilslutte denne node som en replika i vores klynge.<\/p>\n<p><\/p>\n<p>Derudover er der parameteren \u00abmaximum_lag_on_failover\u00bb. Som standard, hvis jeg husker korrekt, har denne parameter v\u00e6rdien 1 megabyte. <\/p>\n<p><\/p>\n<p>Hvordan fungerer det? Hvis vores replika er forsinket med 1 megabyte data i replikationslag, deltager denne replika ikke i valgene. Og hvis der pludselig sker en failover, ser Patroni p\u00e5, hvilke replikas der er forsinkede. Hvis de er forsinkede med et stort antal transaktionsloger, kan de ikke blive master. Det er en meget god beskyttelsesfunktion, der forhindrer, at vi mister mange data. <\/p>\n<p><\/p>\n<p>Men der er et problem, at replikationslaget i Patroni-klyngen og DCS opdateres med et bestemt interval. hvis jeg ikke tager fejl, er standard ttl-v\u00e6rdien 30 sekunder.<\/p>\n<p><\/p>\n<p>Der kan v\u00e6re situationer, hvor replikationslag for replikaer i DCS er \u00e9t, men den faktiske lag kan v\u00e6re helt anderledes eller m\u00e5ske overhovedet ikke eksisterer, dvs. dette er ikke realtime. Og den afspejler ikke altid det virkelige billede. Det er derfor ikke v\u00e6rd at basere kompliceret logik p\u00e5 denne. <\/p>\n<p><\/p>\n<p>Og risikoen for datatab er altid til stede. I v\u00e6rste fald anvendes \u00e9n formel, mens en anden formel anvendes i gennemsnitlige tilf\u00e6lde. Dvs. n\u00e5r vi planl\u00e6gger implementeringen af Patroni og vurderer, hvor mange data vi kan miste, er vi n\u00f8dt til at tage h\u00f8jde for disse formler og have en id\u00e9 om, hvor meget data vi kan miste. <\/p>\n<p><\/p>\n<p>Og der er gode nyheder. N\u00e5r den gamle master skrider fremad, kan dette ske p\u00e5 grund af nogle baggrundsprocesser. Dvs. der var en autovakuum, der skrev data og gemte dem i transaktionsloggen. Disse data kan vi blot ignorere og miste. Der er ikke noget problem i det. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a86e8971ab4ef41b89af9cf0bdf519ba.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og s\u00e5dan ser loggene ud, hvis maximum_lag_on_failover er indstillet, og der er sket en failover, og det er n\u00f8dvendigt at v\u00e6lge en ny master. Replikatet vurderer sig selv som ude af stand til at deltage i valget. Og det n\u00e6gter at deltage i kapl\u00f8bet om lederskabet. Og det venter p\u00e5, at en ny master bliver valgt, s\u00e5 det kan oprette forbindelse til denne. Dette er et yderligere skridt for at undg\u00e5 datatab.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/f760788e5951facdd08b2069037830fa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/c32f26e7526e1873f3bfd7d3693fcc72.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Her har vores produktteam skrevet, at deres produkt har problemer med at arbejde med Postgres. P\u00e5 samme tid kan man ikke tilg\u00e5 selve masteren, fordi den ikke er tilg\u00e6ngelig via SSH. Og der sker heller ikke nogen auto-failover. <\/p>\n<p><\/p>\n<p>Denne host blev tvangsgenstartet. P\u00e5 grund af genstarten skete der en auto-failover, selvom der ogs\u00e5 kunne have v\u00e6ret lavet en manuel auto-failover, som jeg forst\u00e5r nu. Og efter genstarten g\u00e5r vi allerede for at se, hvad der er sket med den nuv\u00e6rende master. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/95efb82e0647a396a21683cd53a69547.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>P\u00e5 samme tid vidste vi p\u00e5 forh\u00e5nd, at vi havde problemer med diskene, dvs. vi vidste allerede fra overv\u00e5gningen, hvor vi skulle grabe, og hvad vi skulle lede efter. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/367aaab607d833d96a573ddbbbced502.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi gik ind i Postgres-loggen og begyndte at se, hvad der skete der. Vi s\u00e5 transaktioner, der tog en til tre sekunder, hvilket ikke er normalt. Vi s\u00e5, at vores autovakuum startede meget langsomt og m\u00e6rkeligt. Og vi s\u00e5 tempor\u00e6re filer p\u00e5 disken. Dvs. dette er alle indikatorer p\u00e5 problemer med diskene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/7e0cfce7a81901ef9ef736c3fefc8dce.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi kiggede i systemets dmesg (i kernel loggen). Og s\u00e5, at vi har problemer med en af diske. Disk subsystemet var en software RAID. Vi kiggede i \/proc\/mdstat og s\u00e5, at vi manglede en disk. Alts\u00e5, her er der en RAID med 8 diske, og vi mangler en. Hvis man ser n\u00e6rmere p\u00e5 slidset, kan man se, at sde mangler. S\u00e5 at sige, vi har mistet en disk. Dette udl\u00f8ste diskproblemer, og applikationerne oplevede ogs\u00e5 problemer ved arbejdet med Postgres-klyngen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/4b09b3aa761cb504fa79173ef280faac.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og i dette tilf\u00e6lde ville Patroni ikke have hjulpet, fordi Patroni ikke har til opgave at overv\u00e5ge serverens tilstand, diskens tilstand. Og vi skal overv\u00e5ge s\u00e5danne situationer med ekstern overv\u00e5gning. Vi har til den eksterne overv\u00e5gning hurtigt tilf\u00f8jet diskoverv\u00e5gning. <\/p>\n<p><\/p>\n<p>Og der var en tanke \u2013 kunne fencing eller en software watchdog hj\u00e6lpe os? Vi mente, at det n\u00e6ppe ville hj\u00e6lpe os i dette tilf\u00e6lde, fordi under problemer fortsatte Patroni med at interagere med DCS-klyngen og s\u00e5 ingen problemer. Alts\u00e5, fra DCS og Patronis synspunkt var alt godt med klyngen, selvom der reelt var diskproblemer og tilg\u00e6ngelighedsproblemer med databasen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/15fdac78535355d4eb889efcc27efc46.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Efter min mening er dette et af de m\u00e6rkeligste problemer, som jeg har unders\u00f8gt i lang tid, l\u00e6st mange logs igennem, og jeg kaldte det klynge-simulatoren. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/b5259774931c290eda6673deb14b6c48.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Problemet var, at den gamle master ikke kunne blive en normal replika, s\u00e5ledes at Patroni startede den, og Patroni viste, at denne node var til stede som replika, men samtidig var den ikke en normal replika. Nu vil du se, hvorfor. Dette har jeg gemt fra analysen af det problem. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/c35a5d102a46764bbf96e5a75ee88171.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og hvordan begyndte det hele? Det begyndte, som ved det tidligere problem, med diskneds\u00e6nkninger. Vi havde kommitteringer p\u00e5 en eller to pr. sekund. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/435c1b350a89f288e0e10ca9d5a2ec6e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der var forbindelsestab, dvs. klienterne blev afbrudt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/920cb1f3f3b40578e15e6ff711e85c50.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der var l\u00e5sninger af forskellig sv\u00e6rhedsgrad. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/285d6292d89b928a85e95602ee57d38a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og s\u00e5ledes var disk subsystemet ikke s\u00e6rlig responsivt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/ebe71d49360e7f604ecd6a3c8276cb73.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og det mest mystiske for mig er den ankomne immediate shutdown request. Postgres har tre slukkeramode:<\/p>\n<p><\/p>\n<ul>\n<li>Der er graceful, hvor vi venter p\u00e5, at alle klienter afslutter sig selv. <\/li>\n<li>Der er fast, hvor vi tvinger klienterne til at afslutte, fordi vi g\u00e5r til slukning. <\/li>\n<li>Og immediate. I dette tilf\u00e6lde informerer immediate ikke engang kunderne om, at de skal logge af, det logger bare af uden varsel. Alle kunder f\u00e5r til geng\u00e6ld en meddelelse fra operativsystemet RST (TCP-meddelelse om, at forbindelsen er blevet afbrudt, og kunden ikke har noget at fange). <\/li>\n<\/ul>\n<p><\/p>\n<p>Hvem sendte dette signal? Baggrundsprocesserne Postgres sender ikke s\u00e5danne signaler til hinanden, dvs. dette er kill-9. De sender ikke s\u00e5danne signaler til hinanden, de reagerer kun p\u00e5 det, dvs. dette er en n\u00f8dgenstart af Postgres. Hvem der sendte det, ved jeg ikke. <\/p>\n<p><\/p>\n<p>Jeg kiggede p\u00e5 kommandoen 'last' og s\u00e5, at der var en person, der ogs\u00e5 loggede ind p\u00e5 denne server sammen med os, men jeg var for genert til at stille sp\u00f8rgsm\u00e5let. Det kunne muligvis have v\u00e6ret kill -9. Jeg ville have set kill -9 i loggene, da Postgres skriver, at den har modtaget kill -9, men jeg s\u00e5 ikke dette i loggene. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/fe8e844649cea3384ebfde86e36eba44.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da jeg fortsatte med at unders\u00f8ge, s\u00e5 jeg, at Patroni ikke havde skrevet til loggen i lang tid \u2013 54 sekunder. Og hvis man sammenligner to tidsstempler, var der her cirka 54 sekunder uden meddelelser. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/ffb1c4db3d7de591d77d56ed2fcc4f2a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og i denne tid skete der en auto-failover. Patroni fungerede igen perfekt. Vores gamle master var utilg\u00e6ngelig, noget skete der med den. Og der begyndte valg af en ny master. Her fungerede alt godt. Vores pgsql01 blev den nye leder. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/6b2457653e9f77af44cd64b4aff021a0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi har en replika, der blev master. Og der er en anden replika. Og med den anden replika var der netop problemer. Den fors\u00f8gte at genkonfigurere sig selv. S\u00e5 vidt jeg forst\u00e5r, fors\u00f8gte den at \u00e6ndre recovery.conf, genstarte Postgres og forbinde til den nye master. Den skriver til hver 10. sekund beskeder om, at den pr\u00f8ver, men det lykkes ikke for den. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/381818f189e19c3e1154074b4652f837.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og under disse fors\u00f8g modtager den gamle master et immediate-shutdown signal. Masteren genstarter. Og genopretningen stopper ogs\u00e5, fordi den gamle master g\u00e5r i genstart. Dvs. replikaen kan ikke oprette forbindelse til den, fordi den er i slukningsmodus. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/d8a8cde925fa8fe601d44ab908ae69dc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I et eller andet \u00f8jeblik begyndte den at fungere, men replikationen startede ikke. <\/p>\n<p><\/p>\n<p>Jeg har en eneste hypotese, at der i recovery.conf var adressen til den gamle master. Og da den nye master opstod, fors\u00f8gte den anden replika stadig at oprette forbindelse til den gamle master. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/425ea3af1f1e186f4760e1fb1f5419fa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Da Patroni startede p\u00e5 den anden replika, startede noden, men kunne ikke oprette forbindelse til replikationen. Og der opstod et replikationslag, som s\u00e5 omtrent s\u00e5dan ud. Dvs. alle tre noder var til stede, men den anden node var bagud. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/f564eacd9944666c9a3f5bea634ede6b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>N\u00e5r man kigger p\u00e5 de logfiler, der blev skrevet, kunne man se, at replikationen ikke kunne starte, fordi transaktionsregistrene var forskellige. Og de transaktionsregistre, som masteren tilb\u00f8d, som var angivet i recovery.conf, passede simpelthen ikke til vores nuv\u00e6rende node. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/6b09947d157c9ef0a190da2df2cb5892.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og her begik jeg en fejl. Jeg skulle have kigget p\u00e5, hvad der stod i recovery.conf, for at tjekke min hypotese om, at vi ikke tilsluttede os den rigtige master. Men jeg var stadig ved at forst\u00e5 det, og det faldt ikke mig ind, eller jeg s\u00e5, at replikationen var forsinket, og at den skulle genindl\u00e6ses, dvs. jeg arbejdede lidt sl\u00f8set. Det var min fejl. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/159f2256fd81428fd0d82a255528887d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Efter 30 minutter kom admin allerede ind, dvs. jeg genstartede Patroni p\u00e5 replikationen. Jeg havde allerede opgivet den, jeg troede, den skulle genindl\u00e6ses. Og jeg t\u00e6nkte \u2013 jeg genstarter Patroni, m\u00e5ske vil det g\u00f8re noget godt. Recovery startede, og databasen \u00e5bnede endda, den var klar til at modtage forbindelser. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/aeac98750386c8389d39e006a229cc85.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Replikationen blev startet. Men efter et minut gik den ned med en fejl, fordi transaktionsregistrene ikke passede. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/17eaba000a79c80c29d1bc3902de05e6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeg t\u00e6nkte, jeg ville genstarte en gang til. Jeg genstartede Patroni \u00e9n gang til, og jeg genstartede ikke Postgres, men jeg genstartede netop Patroni i h\u00e5bet om, at den p\u00e5 magisk vis ville starte databasen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a85b38e033c45ad73da317f41e0ef24a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Replikationen blev startet igen, men posterne i transaktionsregistrene var forskellige; de var ikke de samme, som de var ved det tidligere fors\u00f8g p\u00e5 at starte op. Replikationen stoppede igen. Og beskeden var allerede en smule anderledes. Og den var ikke s\u00e6rlig informativ for mig. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/fd90d708230bd54af685786c7e361ee1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og pludselig kom tanken til mig \u2013 hvad hvis jeg genstarter Postgres og samtidig laver et checkpoint p\u00e5 den nuv\u00e6rende master for at flytte punktet i transaktionsregistrene lidt l\u00e6ngere frem, s\u00e5 recovery kan starte fra et andet punkt? Plus vi havde ogs\u00e5 nogle WAL-reserver. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/19e67f95d1a74141a013947c9aa39e38.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jeg genstartede Patroni, lavede et par checkpoints p\u00e5 masteren, et par restart-punkter p\u00e5 replikationen, da den \u00e5bnede. Og det hjalp. Jeg t\u00e6nkte l\u00e6nge over, hvorfor det hjalp, og hvordan det fungerede. Og replikationen startede. Og replikationen br\u00f8d ikke l\u00e6ngere ned. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/418ca59a681be84f51ed374a73a759c9.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Et s\u00e5dant problem er for mig et af de mere g\u00e5defulde, som jeg stadig grublede over, hvad der egentlig skete. <\/p>\n<p><\/p>\n<p>Hvilke konklusioner kan vi drage herfra? Patroni kan fungere som designet, uden fejl. Men det er ikke en 100 % garanti for, at alt er i orden. En replika kan starte, men den kan v\u00e6re i en semi-funktionel tilstand, og applikationen skal ikke arbejde med en s\u00e5dan replika, da den vil indeholde gamle data. <\/p>\n<p><\/p>\n<p>Og efter en failover er det altid vigtigt at kontrollere, at alt er i orden med klyngen, dvs. at der er det n\u00f8dvendige antal replikater, og at der ikke er nogen replikationslag.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/aca7047ff33d3efe14071b798b554091.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og mens vi gennemg\u00e5r disse problemer, vil jeg formulere anbefalinger. Jeg har fors\u00f8gt at samle dem i to slides. Sandsynligvis kunne alle historierne samles i to slides og kun blive fortalt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/d4ad31b26d83c8846fe4097a11d70849.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>N\u00e5r du bruger Patroni, skal du have overv\u00e5gning. Du skal altid vide, hvorn\u00e5r en auto-failover har fundet sted, for hvis du ikke ved, at du har haft en auto-failover, kontrollerer du ikke klyngen. Og det er skidt.<\/p>\n<p><\/p>\n<p>Efter hver failover skal vi altid manuelt kontrollere klyngen. Vi skal sikre, at vi altid har det aktuelle antal replikater, at der ikke er nogen replikationslag, og at der ikke er fejl relateret til streamingreplikation, Patroni eller DCS-systemet i loggene.<\/p>\n<p><\/p>\n<p>Automatikken kan fungere succesfuldt; Patroni er et meget godt v\u00e6rkt\u00f8j. Det kan fungere, men det vil ikke bringe klyngen til den \u00f8nskede tilstand. Og hvis vi ikke finder ud af dette, vil vi f\u00e5 problemer.<\/p>\n<p><\/p>\n<p>Og Patroni er ikke en s\u00f8lvkugle. Vi skal stadig have en forst\u00e5else af, hvordan Postgres fungerer, hvordan replikation fungerer, og hvordan Patroni arbejder med Postgres og sikrer interaktionen mellem noderne. Dette er n\u00f8dvendigt for at kunne l\u00f8se de opst\u00e5ede problemer manuelt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/ea4162df3561d2ea7001f2ef6788eaaa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvordan n\u00e6rmer jeg mig diagnostik? Det er s\u00e5dan, at vi arbejder med forskellige kunder, og ingen har en ELK-stack, s\u00e5 vi m\u00e5 sortere i loggene ved at \u00e5bne 6 konsoller og 2 faner. I den ene fane er loggene fra Patroni for hver node, mens den anden fane indeholder loggene fra Consul eller Postgres om n\u00f8dvendigt. Det er meget sv\u00e6rt at diagnosticere. <\/p>\n<p><\/p>\n<p>Hvilke tilgange har jeg udviklet? For det f\u00f8rste ser jeg altid, hvorn\u00e5r failoveren indtr\u00e6f. Og for mig er dette et skillepunkt. Jeg ser, hvad der skete f\u00f8r failoveren, under failoveren og efter failoveren. Failoveren har to tidspunkter: start- og sluttid. <\/p>\n<p><\/p>\n<p>Derefter ser jeg i loggene p\u00e5 begivenhederne op til failoveren, hvad der gik forud for failoveren, dvs. jeg s\u00f8ger efter \u00e5rsagerne til, hvorfor failoveren skete. <\/p>\n<p><\/p>\n<p>Og det giver et billede af, hvad der skete, og hvad der kan g\u00f8res i fremtiden for at undg\u00e5 s\u00e5danne omst\u00e6ndigheder (og dermed undg\u00e5 en failover).<\/p>\n<p><\/p>\n<p>Og hvor ser vi normalt? Jeg ser:<\/p>\n<p><\/p>\n<ul>\n<li>F\u00f8rst i loggene fra Patroni. <\/li>\n<li>Derefter ser jeg Postgres-loggene eller DCS-loggene afh\u00e6ngigt af hvad der er fundet i loggene fra Patroni. <\/li>\n<li>Og systemloggene giver nogle gange ogs\u00e5 indsigt i, hvad der var \u00e5rsagen til failoveren. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/a53618e366020e1a550d852fc308c188.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvordan ser jeg p\u00e5 Patroni? Jeg ser meget positivt p\u00e5 Patroni. Efter min mening er det det bedste, der findes i dag. Jeg kender mange andre produkter. Dette er Stolon, Repmgr, Pg_auto_failover, PAF. 4 v\u00e6rkt\u00f8jer. Jeg har pr\u00f8vet dem alle. Patroni har jeg bedre kendt mig med. <\/p>\n<p><\/p>\n<p>Hvis man sp\u00f8rger mig: \"Anbefaler jeg Patroni?\". Jeg siger ja, fordi jeg kan lide Patroni. Og jeg f\u00f8ler, at jeg har l\u00e6rt at bruge det. <\/p>\n<p><\/p>\n<p>Hvis du er interesseret i at se, hvilke andre problemer der kan v\u00e6re med Patroni, udover dem, jeg har n\u00e6vnt, kan du altid bes\u00f8ge siden <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/patroni\/issues\/\">issues<\/a><\/noindex> p\u00e5 GitHub. Der er mange forskellige historier, og der diskuteres mange interessante problemer. Og i sidste ende har nogle fejl blevet registreret og l\u00f8st, dvs. det er interessant l\u00e6sning. <\/p>\n<p><\/p>\n<p>Der er interessante historier om, hvordan folk skyder sig selv i foden. Meget l\u00e6rerigt. Du l\u00e6ser og forst\u00e5r, at man ikke skal g\u00f8re s\u00e5dan. Man s\u00e6tter sig selv en checkmark. <\/p>\n<p><\/p>\n<p>Og jeg vil gerne give en stor tak til Zalando for at de udvikler dette projekt, is\u00e6r til Alexander Kukushkin og Alexey Klyukin. Alexey Klyukin er en af medforfatterne, han arbejder ikke l\u00e6ngere hos Zalando, men det er to personer, der begyndte at arbejde med dette produkt. <\/p>\n<p><\/p>\n<p>Og jeg mener, at Patroni er en virkelig cool ting. Jeg er glad for, at den findes, det er sp\u00e6ndende. Og en stor tak til alle bidragsydere, der skriver patches til Patroni. Jeg h\u00e5ber, at Patroni med tiden bliver mere modnet, cool og fungerende. Den fungerer allerede, men jeg h\u00e5ber, at den bliver endnu bedre. S\u00e5 hvis du planl\u00e6gger at bruge Patroni, s\u00e5 v\u00e6r ikke bange. Det er en god l\u00f8sning, det kan implementeres og bruges. <\/p>\n<p><\/p>\n<p>Det var alt. Hvis du har sp\u00f8rgsm\u00e5l, s\u00e5 sp\u00f8rg endelig.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Patroni Failure Stories or How to crash your PostgreSQL cluster. Alexey Lesovskiy\" src=\"\/wp-content\/uploads\/2020\/07\/85c2fef2455999b48413c9fc3b235ed6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sp\u00f8rgsm\u00e5l<\/p>\n<p><\/p>\n<p><em>Tak for pr\u00e6sentationen! Hvis vi stadig skal se meget grundigt efter en failover, hvorfor har vi s\u00e5 en automatisk failover?<\/em> <\/p>\n<p><\/p>\n<p>Fordi det er en ny ting. Vi har arbejdet med det i kun et \u00e5r. Det er bedre at v\u00e6re forsigtig. Vi \u00f8nsker at g\u00e5 ind og se, om alt virkelig har fungeret som det skal. Det er et niveau af voksent mistillid \u2013 det er bedre at efterkontrollere og se. <\/p>\n<p><\/p>\n<p><em>For eksempel, vi gik ind om morgenen og kiggede, ikke?<\/em><\/p>\n<p><\/p>\n<p>Ikke om morgenen, vi f\u00e5r normalt besked om auto-failover n\u00e6sten med det samme. Vi modtager notifikationer, vi ser, at auto-failoveren fandt sted. Vi g\u00e5r n\u00e6sten med det samme ind og kigger. Men alle disse tjek skal overg\u00e5s til overv\u00e5gningsniveauet. Hvis man henvender sig til Patroni via REST API, er der en historie. Ud fra historien kan man se tidsstempler for, hvorn\u00e5r failoveren skete. Baseret p\u00e5 dette kan man lave overv\u00e5gning. Man kan se historien og hvor mange h\u00e6ndelser der har v\u00e6ret. Hvis vi har f\u00e5et flere h\u00e6ndelser, betyder det, at der har v\u00e6ret en auto-failover. Man kan g\u00e5 ind og tjekke. Eller vores automatisering i overv\u00e5gningen har tjekket, at alle vores repliker er p\u00e5 plads, der ikke er nogen lag, og alt er i orden. <\/p>\n<p><\/p>\n<p><em>Tak!<\/em><\/p>\n<p><\/p>\n<p><em>Tusind tak for den fremragende pr\u00e6sentation! Hvis vi flyttede DCS-klienten langt v\u00e6k fra Postgres-klienten, skal denne klient s\u00e5 ogs\u00e5 vedligeholdes periodisk? Hvilke best practices er der for, hvilke dele af DCS-klienten der skal slukkes, hvad der skal g\u00f8res osv.? Hvordan fungerer hele denne struktur under s\u00e5danne omst\u00e6ndigheder? Og hvordan skal disse ting g\u00f8res?<\/em><\/p>\n<p><\/p>\n<p>For \u00e9n virksomhed var det n\u00f8dvendigt at lave en problemmatrix for, hvad der sker, hvis en eller flere komponenter fejler. Baseret p\u00e5 denne matrix gennemg\u00e5r vi systematisk alle komponenter og skaber scenarier i tilf\u00e6lde af, at disse komponenter svigter. Hver fejlscenarie kan derfor have en handlingsplan for genopretning. Og for DCS er det en del af standardinfrastrukturen. Administratoren administrerer det, og vi stoler allerede p\u00e5 administratorer, der styrer dette, og deres evne til at reparere det i tilf\u00e6lde af en n\u00f8dsituation. Hvis DCS slet ikke findes, er det os, der implementerer det, men vi f\u00f8lger ikke n\u00f8je med, fordi vi ikke har ansvaret for infrastrukturen, men giver anbefalinger til, hvad og hvordan der skal overv\u00e5ges. <\/p>\n<p><\/p>\n<p><em>Dvs. har jeg forst\u00e5et korrekt, at man skal deaktivere Patroni, deaktivere failoveren, deaktivere alt, f\u00f8r man g\u00f8r noget med v\u00e6rterne?<\/em><\/p>\n<p><\/p>\n<p>Det afh\u00e6nger af, hvor mange knuder vi har i DCS-klusteret. Hvis der er mange knuder, og hvis vi kun tager \u00e9n knude (replica) ud af drift, s\u00e5 er der stadig quorum i klusteret. Og Patroni forbliver funktionsdygtig. Og der trigges ikke noget. Hvis vi har nogle komplekse operationer, der involverer flere knuder, hvis frav\u00e6r kan bryde quorum, s\u00e5 ja, det kan give mening at s\u00e6tte Patroni p\u00e5 pause. Han har en tilsvarende kommando \u2013 patronictl pause, patronictl resume. Vi s\u00e6tter bare p\u00e5 pause, og autofailover aktiveres ikke i denne periode. Vi udf\u00f8rer vedligeholdelse p\u00e5 DCS-klusteret, og derefter fjerner vi pausen og forts\u00e6tter med at k\u00f8re.<\/p>\n<p><\/p>\n<p><em>Mange tak!<\/em><\/p>\n<p><\/p>\n<p><em>Tusind tak for pr\u00e6sentationen! Hvordan forholder produktteamet sig til, at data kan g\u00e5 tabt?<\/em> <\/p>\n<p><\/p>\n<p>Produktteamet er ligeglade, men teamlederne er bekymrede. <\/p>\n<p><\/p>\n<p><em>Hvilke garantier findes der?<\/em><\/p>\n<p><\/p>\n<p>Det er meget sv\u00e6rt med garantier. Der er et foredrag af Alexander Kukushkin \"Hvordan man beregner RPO og RTO\", alts\u00e5 genopretningstid og hvor meget data vi kan miste. Jeg tror, vi skal finde disse slides og studere dem. S\u00e5 vidt jeg husker, er der konkrete trin til, hvordan man beregner disse ting. Hvor mange transaktioner vi kan miste, hvor meget data vi kan miste. Som en mulighed kan vi bruge synkron replikation p\u00e5 Patroni-niveau, men det er en tve\u00e6gget sv\u00e6rd: vi har enten dataintegritet eller taber i hastighed. Der er synkron replikation, men den garanterer heller ikke 100% beskyttelse mod datatab.<\/p>\n<p><\/p>\n<p><em>Alexey, tak for en fantastisk pr\u00e6sentation! Har du erfaring med at bruge Patroni til zero level protection? Alts\u00e5 i kombination med synkron standby? Det er det f\u00f8rste sp\u00f8rgsm\u00e5l. Det andet sp\u00f8rgsm\u00e5l. I har brugt forskellige l\u00f8sninger. Vi har brugt Repmgr, men uden autofailover og planl\u00e6gger nu at tilf\u00f8je autofailover. Vi overvejer Patroni som en alternativ l\u00f8sning. Hvad kan du sige er fordelene i forhold til Repmgr?<\/em><\/p>\n<p><\/p>\n<p>Det f\u00f8rste sp\u00f8rgsm\u00e5l om synkrone replikater var. Ingen bruger synkron replikation, fordi alle er bange for det (Flere kunder bruger det allerede, og har ikke bem\u00e6rket problemer med ydeevnen \u2014 <em>Noter fra pr\u00e6sent\u00f8ren<\/em>). Men vi har lavet en regel for os selv om, at der skal v\u00e6re mindst tre noder i en synkron replikationsklynge, fordi hvis vi har to noder, og hvis master eller replika g\u00e5r ned, s\u00e5 overf\u00f8rer Patroni denne node til Standalone-tilstand, s\u00e5 applikationen fortsat kan k\u00f8re. I dette tilf\u00e6lde er der risici for datatab.<\/p>\n<p><\/p>\n<p>Vedr\u00f8rende det andet sp\u00f8rgsm\u00e5l, har vi brugt Repmgr og bruger det stadig hos nogle af vores kunder af historiske grunde. Hvad kan vi sige? I Patroni kommer auto-failover som standard, mens auto-failover i Repmgr kommer som en ekstra funktion, der skal aktiveres. Vi skal starte Repmgr daemon p\u00e5 hver node, og s\u00e5 kan vi konfigurere auto-failover. <\/p>\n<p><\/p>\n<p>Repmgr tjekker, om Postgres-noderne er i live. Repmgr-processerne tjekker for hinandens eksistens, hvilket ikke er en s\u00e6rlig effektiv tilgang, da der kan opst\u00e5 komplekse tilf\u00e6lde af netv\u00e6rksisolering, hvor en stor Repmgr-klynge kan splittes op i flere sm\u00e5 og forts\u00e6tte med at fungere. Jeg har ikke fulgt med i Repmgr i lang tid, m\u00e5ske har de fikset det ... eller m\u00e5ske ikke. Men det at flytte information om klyngens tilstand til DCS, som Stolon og Patroni g\u00f8r, er den mest levedygtige l\u00f8sning. <\/p>\n<p><\/p>\n<p><em>Alexey, jeg har et sp\u00f8rgsm\u00e5l, m\u00e5ske et naivt. I et af de f\u00f8rste eksempler tog I DCS ud fra den lokale maskine og over til en fjern node. Vi forst\u00e5r, at netv\u00e6rket er noget, der har sine egne s\u00e6regenheder, det lever sit eget liv. Hvad sker der, hvis DCS-klyngen bliver utilg\u00e6ngelig af en eller anden grund? Jeg vil ikke n\u00e6vne \u00e5rsagerne, der kan v\u00e6re mange: fra d\u00e5rligt arbejde af netv\u00e6rksteknikere til reelle problemer.<\/em> <\/p>\n<p><\/p>\n<p>Jeg n\u00e6vnte ikke h\u00f8jt, men DCS-klyngen skal ogs\u00e5 v\u00e6re fejlbestandig, dvs. det skal v\u00e6re et ulige antal noder, s\u00e5 kvorum kan samles. Hvad sker der, hvis DCS-klyngen bliver utilg\u00e6ngelig, eller ikke kan samle et kvorum, dvs. en form for netv\u00e6rks-split eller nedbrud af noder? I dette tilf\u00e6lde g\u00e5r Patroni-klyngen over i read only-tilstand. Patroni-klyngen kan ikke bestemme status for klyngen og hvad den skal g\u00f8re. Den kan ikke kontakte DCS og gemme den nye status for klyngen, derfor g\u00e5r hele klyngen ind i read only. Den venter enten p\u00e5 manuel indgriben fra operat\u00f8ren eller p\u00e5 at DCS bliver genoprettet.<\/p>\n<p><\/p>\n<p><em>Groft sagt bliver DCS for os en tjeneste, der er liges\u00e5 vigtig som selve databasen?<\/em><\/p>\n<p><\/p>\n<p>Ja ja. I mange moderne virksomheder er Service Discovery en uundg\u00e5elig del af infrastrukturen. Det implementeres ofte f\u00f8r databasen i infrastrukturen overhovedet er til stede. For at sige det p\u00e5 en anden m\u00e5de, n\u00e5r infrastrukturen er startet op, og datacenteret er bygget, s\u00e5 har vi automatisk Service Discovery. Hvis det er Consul, kan DNS ogs\u00e5 bygges p\u00e5 det. Hvis det er Etcd, kan det v\u00e6re en del af Kubernetes-klyngen, hvor alt andet allerede vil blive implementeret. Jeg mener, at Service Discovery allerede er en uundg\u00e5elig del af moderne infrastrukturer, og man t\u00e6nker p\u00e5 det meget tidligere end databaser. <\/p>\n<p><\/p>\n<p><em>Tak!<\/em><\/p>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/512768\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c Patroni \u2014 \u044d\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 High Availability \u0434\u043b\u044f PostgreSQL. \u041d\u043e Patroni \u2014 \u044d\u0442\u043e \u043b\u0438\u0448\u044c template, \u0430 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 (\u0447\u0442\u043e, \u0432 \u043e\u0431\u0449\u0435\u043c, \u0438 \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438). \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 Patroni \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u043b\u0430\u0431\u0435, \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u044d\u0442\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0438 \u043a\u0430\u043a \u043e\u043d \u043b\u0435\u0433\u043a\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0448\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0440\u0430\u0437\u0432\u0430\u043b\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":90104,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-90103","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Patroni Failure Stories or How to crash your PostgreSQL cluster. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041b\u0435\u0441\u043e\u0432\u0441\u043a\u0438\u0439 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-29T11:42:32+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-29T11:42:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Patroni Failure Stories eller hvordan man crasher sin PostgreSQL klynge. Alexey Lesovsky | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Patroni Failure Stories or How to crash your PostgreSQL cluster. \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u041b\u0435\u0441\u043e\u0432\u0441\u043a\u0438\u0439 | ProHoster","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/patroni-failure-stories-or-how-to-crash-your-postgresql-cluster-aleksej-lesovskij","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-29T11:42:32+00:00","article:modified_time":"2020-07-29T11:42:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"90103","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:58:48","updated":"2026-02-09 16:50:35","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/90103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=90103"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/90103\/revisions"}],"predecessor-version":[{"id":158759,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/90103\/revisions\/158759"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/90104"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=90103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=90103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=90103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}