{"id":55467,"date":"2020-01-21T00:00:00","date_gmt":"2020-01-20T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya"},"modified":"2020-02-18T14:03:35","modified_gmt":"2020-02-18T11:03:35","slug":"postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya","title":{"rendered":"Postgres-dinsdag nr. 5: \"PostgreSQL en Kubernetes. CI\/CD. Automatisering van tests\"","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Postgres-dinsdag nr. 5: &quot;PostgreSQL en Kubernetes. CI\/CD. Automatisering van tests&quot;\" src=\"\/wp-content\/uploads\/2020\/01\/5eb8dd2afa4cab58a7359b305814d77f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAan het einde van het afgelopen jaar vond er een nieuwe live-uitzending van de Russische PostgreSQL-gemeenschap plaats <noindex><a rel=\"nofollow\" href=\"https:\/\/www.meetup.com\/postgresqlrussia\/\">#RuPostgres<\/a><\/noindex>, waar zijn medeoprichter Nikolaj Samochvalov sprak met technisch directeur Dmitri Stolyarov van \"Flant\" over deze database in de context van Kubernetes.<\/p>\n<p>We publiceren het transcript van het belangrijkste deel van deze discussie, en op <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/channel\/UC0SBGSNmBLrTZIkbN-lJHnw\">het YouTube-kanaal van de gemeenschap<\/a><\/noindex> is de volledige video opgenomen:<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"qXc9VTr4TFc\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/qXc9VTr4TFc\/hqdefault.jpg\" alt=\"Video afspelen\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><\/p>\n<h2>Databases en Kubernetes<\/h2>\n<p>\n<i><b>NS<\/b>: We gaan het vandaag niet hebben over VACUUM en CHECKPOINTs. We willen het hebben over Kubernetes. Ik weet dat je al jaren ervaring hebt. Ik heb je video's bekeken en sommige zelfs fragmenten opnieuw bekeken... Laten we meteen ter zake komen: waarom \u00fcberhaupt Postgres of MySQL in K8s?<\/i><\/p>\n<p><b>DS<\/b>: Er is geen eenduidig antwoord op deze vraag en dat kan er ook niet zijn. Maar in wezen is het eenvoud en gemak\u2026 potentieel. Iedereen wil toch managed services.<\/p>\n<p><i><b>NS<\/b>: Om het zo te hebben <noindex><a rel=\"nofollow\" href=\"https:\/\/aws.amazon.com\/rds\/\">RDS<\/a><\/noindex>, alleen bij jezelf?<\/i><\/p>\n<p><b>DS<\/b>: Ja: om het te hebben zoals RDS, maar waar dan ook.<\/p>\n<p><i><b>NS<\/b>: \"Waar dan ook\" \u2014 dat is een goede opmerking. In grote bedrijven is alles op verschillende locaties. Maar waarom zou je, als het een groot bedrijf is, geen kant-en-klaar oplossing nemen? Bijvoorbeeld, Nutanix heeft eigen ontwikkelingen, andere bedrijven (VMware\u2026) hebben dezelfde \"RDS, alleen bij jezelf\".<\/i><\/p>\n<p><b>DS<\/b>: Maar dat is iets wat we zeggen over een specifieke implementatie die alleen onder bepaalde omstandigheden werkt. En als we het over Kubernetes hebben, is er een enorme diversiteit aan infrastructuur (die in K8s kan zijn). In wezen is dit de standaard voor de API naar de cloud\u2026<\/p>\n<p><i><b>NS<\/b>: En het is ook gratis!<\/i><\/p>\n<p><b>DS<\/b>: Dat is niet zo belangrijk. Gratis zijn is niet zo relevant voor een groot segment van de markt. Wat belangrijker is\u2026 Je herinner je vast de presentatie over \"<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">Databases en Kubernetes<\/a><\/noindex>\u00bb?<\/p>\n<p><i><b>NS<\/b>: Ja.<\/i><\/p>\n<p><b>DS<\/b>: Ik begreep dat het op verschillende manieren werd opgevat. Een deel van de mensen dacht dat ik zei: \u201cLaten we allemaal databases in Kubernetes gebruiken!\u201d, terwijl anderen vonden dat dit helemaal absurde concepten waren. Ik wilde echter iets anders zeggen: \u201cKijk, wat er gebeurt, welke problemen er zijn en hoe je deze kunt oplossen. Is het nu een goed idee om databases in Kubernetes te draaien? Productie? Alleen als je houdt van... bepaalde dingen doen. Maar voor dev kan ik zeggen dat ik het aanbeveel. Voor dev is de dynamiek van het cre\u00ebren\/verwijderen van omgevingen erg belangrijk.\u201d<\/p>\n<p><i>NS: Met dev bedoel je alle omgevingen die niet prod zijn? Staging, QA\u2026<\/i><\/p>\n<p><b>DS<\/b>: Als we het hebben over perf-standa, dan is dat waarschijnlijk niet meer het geval omdat de eisen specifiek zijn. Als we het hebben over uitzonderlijke gevallen waarbij een zeer grote database op staging nodig is, dan is dat ook waarschijnlijk niet het geval... Als het een statische omgeving is die lang meegaat, wat is dan het voordeel van een database die in K8s is geplaatst?<\/p>\n<p><i><b>NS<\/b>: Geen enkel. Maar waar zien we statische omgevingen? Een statische omgeving is morgen al verouderd.<\/i><\/p>\n<p><b>DS<\/b>: Staging kan statisch zijn. We hebben klanten...<\/p>\n<p><i><b>NS<\/b>: Ja, die heb ik ook. Het is een groot probleem als je een database van 10 TB hebt, en staging is 200 GB...<\/i><\/p>\n<p><b>DS<\/b>: Ik heb een heel cool geval! Op staging bevindt zich een productie database waarin wijzigingen worden aangebracht. En er is een knop: \u201cuitrollen naar productie\u201d. Deze wijzigingen - deltas - worden (schijnt gewoon via een API gesynchroniseerd) in productie gebracht. Dit is een zeer exotische optie.<\/p>\n<p><i><b>NS<\/b>: Ik heb startups in de vallei gezien die nog op RDS zitten of zelfs op Heroku - dat zijn verhalen van 2-3 jaar geleden - en ze downloaden een dump naar hun laptop. Omdat de database slechts 80 GB is en er ruimte op de laptop is. Vervolgens kopen ze schijven voor iedereen om 3 databases te hebben voor verschillende ontwikkelingen. Dat gebeurt ook. Ik heb ook gezien dat ze niet bang zijn om prod naar staging te kopi\u00ebren - dat hangt sterk van het bedrijf af. Maar ik heb ook gezien dat ze erg bang zijn, en dat er vaak niet genoeg tijd en mensen zijn. Maar voordat we naar dit onderwerp gaan, wil ik graag iets horen over Kubernetes. Begrijp ik het goed dat niemand het momenteel in prod heeft?<\/i><\/p>\n<p><b>DS<\/b>: We hebben kleine databases in prod. Het gaat om volumes van tientallen gigabytes en niet-kritische services, waarvoor het te veel moeite was om replica's te maken (en er is ook geen behoefte aan). En op voorwaarde dat er normaal opslag is onder Kubernetes. Deze database werkte in een virtuele machine - voor de duidelijkheid in VMware, boven op SAN. We hebben het geplaatst in <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/\">PV<\/a><\/noindex> en nu kunnen we het van machine naar machine verplaatsen.<\/p>\n<p><i><b>NS<\/b>: Dat soort databases, tot 100 GB, kan je op goede schijven en bij een goed netwerk binnen enkele minuten uitrollen, toch? Een snelheid van 1 GB per seconde is al geen exotisch geval meer.<\/i><\/p>\n<p><b>DS<\/b>: Ja, voor een lineaire operatie is dat geen probleem.<\/p>\n<p><i><b>NS<\/b>: Ok\u00e9, we moeten alleen over prod nadenken. En als we Kubernetes voor niet-prod-omgevingen overwegen \u2014 hoe doen we dat? Ik zie dat Zalando <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\">een operator maakt<\/a><\/noindex>, in Crunchy <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CrunchyData\/postgres-operator\">ontwikkelen ze<\/a><\/noindex>, zijn er nog andere opties. En er is <noindex><a rel=\"nofollow\" href=\"https:\/\/ongres.com\/\">OnGres<\/a><\/noindex> \u2014 dat is onze goede bekende Alvaro uit Spanje: zij maken in wezen niet alleen een <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/326414\/\">operator<\/a><\/noindex>, maar een hele distributie (<noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/ongresinc\/stackgres\">StackGres<\/a><\/noindex>), waarin we naast Postgres ook een backup wilden stoppen, proxy Envoy\u2026<\/i><\/p>\n<p><b>DS<\/b>: Waar is Envoy voor? Voor het balanceren van de Postgres-verkeer?<\/p>\n<p><i><b>NS<\/b>: Ja. Ze zien dit als volgt: als je een Linux-distributie en de kernel neemt, dan is de gewone PostgreSQL de kernel, en ze willen een distributie maken die cloud-vriendelijk is en in Kubernetes kan draaien. Ze verbinden componenten (back-ups, etc.) en optimaliseren ze zodat ze goed functioneren.<\/i><\/p>\n<p><b>DS<\/b>: Heel gaaf! In wezen is dit software om je eigen beheerde Postgres op te zetten.<\/p>\n<p><i><b>NS<\/b>: Bij Linux-distributies zijn er altijd problemen: hoe je stuurprogramma's maakt zodat alle hardware wordt ondersteund. Hun idee is dat ze in Kubernetes willen werken. Ik weet dat we bij de operator Zalando recent een koppeling met AWS hebben gezien, en dat is al niet zo goed. Er zou toch geen afhankelijkheid van een specifieke infrastructuur moeten zijn \u2014 wat is dan de zin?<\/i><\/p>\n<p><b>DS<\/b>: Ik weet niet in welke situatie Zalando zich specifiek heeft verbonden, maar in Kubernetes is de opslag nu zo gemaakt dat je niet op een generieke manier een schijfback-up kunt maken. Recent is de mogelijkheid voor snapshots in de laatste versie van de standaard toegevoegd, maar waar is het ge\u00efmplementeerd? Eerlijk gezegd, het is nog steeds zo onvolwassen... <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465417\/\">CSI-specificaties<\/a><\/noindex> \u2014 we proberen CSI boven AWS, GCE, Azure, vSphere, maar zodra je het begint te gebruiken, zie je dat het nog niet klaar is.<\/p>\n<p><i><b>NS<\/b>: Daarom moet je soms afhankelijk zijn van de infrastructuur. Ik denk dat dit nog een vroege fase is \u2014 groeiproblemen. Vraag: wat zou je adviseren voor beginners die PgSQL in K8s willen proberen? Welke operator misschien?<\/i><\/p>\n<p><b>DS<\/b>: Het probleem is dat Postgres voor ons slechts 3% is. We hebben nog een lange lijst met verschillende software in Kubernetes, die ik niet allemaal zal opsommen. Bijvoorbeeld, Elasticsearch. Er zijn veel operators: sommige ontwikkelen zich actief, andere niet. Wij hebben voor onszelf eisen opgesteld over wat er in de operator moet zitten om deze serieus te nemen. In de operator specifiek voor Kubernetes \u2014 niet in de 'operator om iets te doen in de omstandigheden van Amazon'... In feite gebruiken we op grote schaal (= bij bijna al onze klanten) de enige operator \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/spotahome\/redis-operator\">voor Redis<\/a><\/noindex> <i>(we publiceren binnenkort ook een artikel over hem)<\/i>.<\/p>\n<p><i><b>NS<\/b>: Maar is er ook geen voor MySQL? Ik weet dat Percona... omdat ze nu met zowel MySQL, MongoDB als Postgres werken, moeten ze wel iets universeler maken: voor alle databases, voor alle cloudproviders.<\/i><\/p>\n<p><b>DS<\/b>: We hebben de operators voor MySQL nog niet bekeken. Voor ons is dat momenteel niet de belangrijkste focus. MySQL werkt prima in standalone. Waarom een operator, als je gewoon de database kunt opstarten... Je kunt een Docker-container met Postgres opstarten, of je kunt het op de simpele manier doen.<\/p>\n<p><i><b>NS<\/b>: Daar was ook een vraag over. Helemaal zonder operator?<\/i><\/p>\n<p><b>DS<\/b>: Ja, in 100% van de gevallen draait onze PostgreSQL zonder operator. Tot nu toe zo. We gebruiken actief een operator voor Prometheus, voor Redis. We hebben plannen om een operator voor Elasticsearch te vinden \u2014 dat is het meest dringende, omdat we het in 100% van de gevallen op Kubernetes willen zetten. Net zoals we willen dat MongoDB ook altijd op Kubernetes draait. Er verschijnen bepaalde wensen \u2014 er is het gevoel dat we in deze gevallen iets kunnen doen. Maar over Postgres hebben we zelfs niet gekeken. Natuurlijk weten we van het bestaan van verschillende opties, maar feitelijk hebben we standalone.<\/p>\n<h2>Database voor testen in Kubernetes<\/h2>\n<p>\n<i><b>NS<\/b>: Laten we overgaan naar het onderwerp testen. Hoe pas je wijzigingen in de database toe \u2014 vanuit een DevOps-perspectief. Er zijn microservices, veel databases, en er verandert voortdurend iets ergens. Hoe zorg je voor een normale CI\/CD, zodat alles vanuit het perspectief van de database in orde is? Wat is jouw aanpak?<\/i><\/p>\n<p><b>DS<\/b>: Er kan niet \u00e9\u00e9n antwoord zijn. Er zijn verschillende parameters. De eerste is de grootte van de database die we willen implementeren. Je noemde al dat bedrijven er verschillend over denken om een kopie van de prod-database op dev en stage te hebben.<\/p>\n<p><i><b>NS<\/b>: Onder GDPR-voorwaarden denk ik dat ze er steeds voorzichtiger mee omgaan... Ik kan je vertellen dat ze al zijn begonnen met boetes in Europa.<\/i><\/p>\n<p><b>DS<\/b>: Maar vaak kun je software schrijven die een dump van de productie maakt en deze obfuskeert. Je krijgt productiegegevens (snapshot, dump, binaire kopie\u2026), maar ze zijn geanonimiseerd. In plaats daarvan kunnen er ook generatie-scripts zijn: dit kunnen fixtures zijn of gewoon een script dat een grote database genereert. Het probleem is: hoe lang duurt het om het basisbeeld te maken? En hoe lang duurt het om het uit te rollen in de juiste omgeving?<\/p>\n<p>We zijn tot het schema gekomen: als de klant een fixture-dataset heeft (minimale versie van de database), gebruiken we die standaard. Als het gaat om review-omgevingen, wanneer we een branch hebben aangemaakt, hebben we een instantie van de applicatie opgestart \u2014 daar implementeren we een kleine database. Maar het is goed gegaan en <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/417509\/\">optie<\/a><\/noindex>, wanneer we elke dag (s nachts) een dump van de productie maken en op basis daarvan een Docker-container met PostgreSQL en MySQL verzamelen met deze geladen gegevens. Als je uit dit beeld de database 50 keer moet uitrollen, is dat vrij eenvoudig en snel te doen.<\/p>\n<p><i><b>NS<\/b>: Gewoon door te kopi\u00ebren?<\/i><\/p>\n<p><b>DS<\/b>: Gegevens worden rechtstreeks in het Docker-image opgeslagen. Dit betekent dat we een kant-en-klaar image hebben, laten we zeggen van 100 GB. Dankzij de lagen in Docker kunnen we dit image snel het vereiste aantal keren uitrollen. Het is een eenvoudige manier, maar het werkt redelijk goed.<\/p>\n<p><i><b>NS<\/b>: Vervolgens, wanneer je test, verandert het rechtstreeks binnen Docker, toch? Copy-on-write binnen Docker \u2014 we gooien het weg en beginnen opnieuw, alles is goed. Geweldig! En gebruiken jullie dit al volop?<\/i><\/p>\n<p><b>DS<\/b>: Al een tijd.<\/p>\n<p><i><b>NS<\/b>: Wij doen ook heel vergelijkbare dingen. Alleen gebruiken wij geen Docker's copy-on-write, maar een andere.<\/i><\/p>\n<p><b>DS<\/b>: Hij is niet generiek. Maar de Docker-versie werkt overal.<\/p>\n<p><i><b>NS<\/b>: In theorie, ja. Maar we hebben ook modules daar, je kunt verschillende modules maken en met verschillende bestandssystemen werken. Hier is het punt. Wij kijken van de kant van Postgres anders naar dit alles. Nu heb ik vanuit de Docker-kant gekeken en gezien dat alles werkt. Maar als de database enorm is, bijvoorbeeld 1 TB, dan duurt het allemaal al lang: zowel de nachtelijke bewerkingen als het in Docker stoppen... En als we 5 TB in Docker moeten stoppen... Of gaat alles goed?<\/i><\/p>\n<p><b>DS<\/b>: Wat maakt het uit: het zijn gewoon blobs, alleen bits en bytes.<\/p>\n<p><i><b>NS<\/b>: Het verschil is: doen jullie dat via dump en restore?<\/i><\/p>\n<p><b>DS<\/b>: Absoluut niet noodzakelijk. De manieren om dit image te genereren kunnen verschillen.<\/p>\n<p><i><b>NS<\/b>: Voor sommige klanten hebben we ervoor gezorgd dat in plaats van een reguliere generatie van de basisafbeelding, we deze voortdurend up-to-date houden. Het is in wezen een replica, maar de gegevens worden niet direct van de master verkregen, maar via een archief. Een binaire archief waarin WAL's dagelijks worden toegepast, daar worden ook backups gemaakt... Deze WAL's komen vervolgens aan \u2014 met een kleine vertraging (slechts 1-2 seconden) \u2014 bij de basisafbeelding. Van daaruit klonen we op elke mogelijke manier \u2014 standaard gebruiken we nu ZFS.<\/i><\/p>\n<p><b>DS<\/b>: Maar met ZFS ben je beperkt tot \u00e9\u00e9n node.<\/p>\n<p><i><b>NS<\/b>: Ja. Maar ZFS heeft ook een magische <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/cd\/E18752_01\/html\/819-5461\/gbchx.html\">send<\/a><\/noindex>: waarmee je een snapshot kunt verzenden en zelfs (dit heb ik nog niet echt getest, maar...) kun je de delta tussen twee <code>PGDATA<\/code>. In feite hebben we nog een hulpmiddel dat we niet echt hebben overwogen voor dergelijke taken. In PostgreSQL is er <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/12\/app-pgrewind.html\">pg_rewind<\/a><\/noindex>, werkend als een 'slimme' rsync, dat veel overslaat wat je niet hoeft te bekijken omdat er zeker niets is veranderd. We kunnen een snelle synchronisatie tussen twee servers doen en precies terugrollen.<\/i><\/p>\n<p><i>Dus, we proberen van deze, meer DBA-kant, een tool te maken die hetzelfde mogelijk maakt als wat je zei: we hebben \u00e9\u00e9n database, maar we willen 50 keer iets testen, bijna gelijktijdig.<\/i><\/p>\n<p><b>DS<\/b>: 50 keer betekent dat je 50 Spot-instanties moet bestellen.<\/p>\n<p><i><b>NS<\/b>: Nee, we doen alles op \u00e9\u00e9n machine.<\/i><\/p>\n<p><b>DS<\/b>: Maar hoe ga je 50 keer implementeren, als deze ene database, laten we zeggen, een terabyte is? Waarschijnlijk heeft die voorwaardelijk 256 GB RAM nodig?<\/p>\n<p><i><b>NS<\/b>: Ja, soms heb je veel geheugen nodig \u2014 dat is normaal. Maar een voorbeeld uit het leven. Op de productie machine 96 kernen en 600 GB. Daarbij worden voor de DB 32 kernen gebruikt (zelfs soms 16 kernen nu) en 100-120 GB geheugen.<\/i><\/p>\n<p><b>DS<\/b>: En past daar 50 kopie\u00ebn in?<\/p>\n<p><i><b>NS<\/b>: Maar de kopie is \u00e9\u00e9n, daarna werkt het copy-on-write (ZFS)... Ik zal meer vertellen.<\/i><\/p>\n<p><i>Bijvoorbeeld, wij hebben een database van 10 TB. We hebben een schijf hiervoor gemaakt, ZFS heeft het nog met 30-40% gecomprimeerd. Aangezien we geen belastingstest doen, is de exacte responstijd niet belangrijk voor ons: als het tot 2 keer langzamer is \u2014 dat is goed.<\/i><\/p>\n<p><i>We geven programmeurs, QA, DBA's, enzovoort de mogelijkheid om tests uit te voeren in 1-2 threads. Bijvoorbeeld, ze kunnen een migratie starten. Het vereist niet meteen 10 cores \u2014 het heeft 1 backend van Postgres, 1 core nodig. De migratie zal starten \u2014 misschien, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/12\/routine-vacuuming.html#AUTOVACUUM\">autovacuum<\/a><\/noindex> zal ook starten, dan wordt de tweede kern ingezet. We hebben 16-32 kernen toegewezen, zodat 10 mensen tegelijkertijd kunnen werken, geen probleem.<\/i><\/p>\n<p><i>Aangezien fysiek <code>PGDATA<\/code> gelijktijdig, het blijkt zo te zijn dat we Postgres in feite bedriegen. Waar het om draait: bijvoorbeeld starten we 10 Postgres-instanties tegelijk. Wat is meestal het probleem? Ze plaatsen <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-resource.html\">shared_buffers<\/a><\/noindex>, laten we zeggen, op 25%. Bijgevolg is dat 200 GB. Meer dan drie van deze kun je al niet starten, omdat het geheugen op is.<\/i><\/p>\n<p><i>Maar op een gegeven moment realiseerden we ons dat dat niet nodig was: we zetten shared_buffers op 2 GB. PostgreSQL heeft <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE\">effective_cache_size<\/a><\/noindex>, en in werkelijkheid be\u00efnvloedt alleen dat <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Query_plan\">de plannen<\/a><\/noindex>. Dat zetten we op 0,5 TB. En het doet er niet eens toe dat ze er in werkelijkheid niet zijn: het maakt plannen alsof ze er zijn.<\/i><\/p>\n<p><i>Bijgevolg, wanneer we een bepaalde migratie testen, kunnen we alle plannen verzamelen \u2014 we zullen zien hoe het op productie zal verlopen. De seconden zullen anders zijn (langzamer), maar de gegevens die we daadwerkelijk uitlezen, en de plannen zelf (hoeveel JOIN's, enz.) zijn precies hetzelfde als op productie. En tegelijkertijd kunnen we veel van dergelijke controles op \u00e9\u00e9n machine uitvoeren.<\/i><\/p>\n<p><b>DS<\/b>: Denk je niet dat er hier een paar problemen zijn? Ten eerste is dit een oplossing die alleen op PostgreSQL werkt. Deze aanpak is heel specifiek, niet generiek. Ten tweede gaat Kubernetes (en alles waar cloudtechnologie momenteel naartoe gaat) uit van meerdere knooppunten, en deze knooppunten zijn efemere. En in jouw geval is het een stateful, persistente knoop. Deze dingen roepen tegenstrijdigheden bij me op.<\/p>\n<p><i><b>NS<\/b>: Ten eerste \u2014 het is puur een Postgres-idee. Ik denk dat als we een of andere direct IO en een bufferpool hebben die bijna het volledige geheugen benut, deze aanpak niet zal werken \u2014 de plannen zullen anders zijn. Maar we werken voorlopig alleen met Postgres, we denken niet aan anderen.<\/i><\/p>\n<p><i>Over Kubernetes. Je vertelt zelf overal dat onze database persistent is. Als een instantie crasht, is het belangrijkste om de schijf te behouden. Onze gehele platform draait ook op Kubernetes, en de component met PostgreSQL is apart (hoewel die daar ooit ook zal zijn). Dus het is zo: de instantie is gecrasht, maar we hebben zijn PV behouden en gewoon aangesloten op een andere (nieuwe) instantie, alsof er niets is gebeurd.<\/i><\/p>\n<p><b>DS<\/b>: Vanuit mijn oogpunt cre\u00ebren we pods in Kubernetes. K8s is elastisch: knooppunten worden automatisch besteld naargelang de behoefte. De taak is simpelweg om een pod te cre\u00ebren en te zeggen dat deze X bronnen nodig heeft, en verder regelt K8s het zelf. Maar de ondersteuning voor opslag in Kubernetes is nog steeds onbetrouwbaar: in <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/467477\/\">1.16<\/a><\/noindex>, in <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/476998\/\">1.17<\/a><\/noindex> (deze release is uitgebracht <i>weken<\/i> geleden) worden deze functies alleen maar in b\u00e8ta.<\/p>\n<p>Na de periode van zes maanden tot een jaar zal het min of meer stabiel zijn, of in ieder geval zo worden gepresenteerd. Dan lost de mogelijkheid van snapshots en resizing uw probleem volledig op. Want u heeft een basis. Ja, deze kan misschien niet heel snel zijn, maar de snelheid hangt af van wat er \"onder de motorkap\" zit, omdat sommige implementaties kopi\u00ebren en copy-on-write op het niveau van de opslag subsystemen kunnen.<\/p>\n<p><i><b>NS<\/b>: Dan moeten alle engines (Amazon, Google...) ook deze versie snel gaan ondersteunen \u2014 dat kost ook tijd.<\/i><\/p>\n<p><b>DS<\/b>: Tot nu toe gebruiken we ze niet. We gebruiken de onze.<\/p>\n<h2>Lokale ontwikkeling voor Kubernetes<\/h2>\n<p>\n<i><b>NS<\/b>: Ben jij ooit geconfronteerd met die behoefte, waarbij je op \u00e9\u00e9n machine alle pods moet opzetten en een kleine test moet uitvoeren. Om snel een proof of concept te krijgen en te zien of de applicatie werkt in Kubernetes, zonder daarvoor een heleboel machines in te zetten. Er is Minikube, toch?<\/i><\/p>\n<p><b>DS<\/b>: Ik denk dat dit geval \u2014 alles op \u00e9\u00e9n knooppunt implementeren \u2014 uitsluitend over lokale ontwikkeling gaat. Of sommige uitings van zo'n patroon. Er zijn <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/333470\/\">Minikube<\/a><\/noindex>, er is <noindex><a rel=\"nofollow\" href=\"https:\/\/k3s.io\/\">k3s<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/kubernetes-sigs\/kind\">KIND<\/a><\/noindex>. We gaan gebruiken maken van Kubernetes IN Docker. We zijn daar nu mee begonnen voor tests.<\/p>\n<p><i><b>NS<\/b>: Ik dacht vroeger dat dit een poging was om alle pods in \u00e9\u00e9n Docker-image te verpakken. Maar het blijkt heel iets anders te zijn. Er zijn nog steeds aparte containers, aparte pods \u2014 gewoon in Docker.<\/i><\/p>\n<p><b>DS<\/b>: Ja. En daar is een best leuke simulatie gemaakt, maar het idee is zo\u2026 We hebben een tool voor deployment \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex>. We willen daarin een modus maken \u2014 bij wijze van spreken <code>werf up<\/code>: \u2018Verhoog mijn lokale Kubernetes\u2019. En dan een hypothetische <code>werf follow<\/code>. Dan kan de ontwikkelaar aanpassen in de IDE, terwijl in het systeem een proces draait dat de wijzigingen opmerkt en de images opnieuw bouwt en deze opnieuw deplo\u00efeert in de lokale K8s. Zo willen we proberen het probleem van lokale ontwikkeling op te lossen.<\/p>\n<h2>Snapshots en klonen van databases in de realiteit van K8s<\/h2>\n<p>\n<i><b>NS<\/b>: Als we terugkeren naar copy-on-write. Ik heb opgemerkt dat cloudproviders ook snapshots hebben. Ze werken anders. Bijvoorbeeld, in GCP: je hebt een multi-terabyte instantie aan de oostkust van de VS. Je maakt periodiek snapshots. Je start uit een snapshot een kopie van de schijf aan de westkust \u2014 binnen enkele minuten is alles klaar, het werkt heel snel, alleen de cache moet in het geheugen worden gevuld. Maar deze klonen (snapshots) zijn bedoeld om een nieuwe schijf te 'provisionen'. Dat is geweldig wanneer je veel instanties moet cre\u00ebren.<\/i><\/p>\n<p><i>Maar voor tests, lijkt het me dat de snapshots waar jij het over hebt in Docker of ik het heb over ZFS, btrfs en zelfs LVM... \u2014 ze stellen je in staat om op \u00e9\u00e9n machine eigenlijk geen nieuwe gegevens te genereren. In de cloud moet je bovendien elke keer ervoor betalen en wachten, niet seconden, maar minuten (en in het geval van <noindex><a rel=\"nofollow\" href=\"https:\/\/aws.amazon.com\/about-aws\/whats-new\/2019\/11\/amazon-ebs-fast-snapshot-restore-eliminates-need-for-prewarming-data-into-volumes-created-snapshots\/\">lazy load<\/a><\/noindex>, mogelijk zelfs uren).<\/i><\/p>\n<p><i>In plaats daarvan kun je deze data in een seconde of twee verkrijgen, de test draaien en weggooien. Deze snapshots lossen verschillende problemen op. In het eerste geval \u2014 om te schalen en nieuwe replicas te krijgen, en in het tweede \u2014 voor tests.<\/i><\/p>\n<p><b>DS<\/b>: Ik ben het daar niet mee eens. Het normaal klonen van volumes is een taak voor de cloud. Ik heb hun implementatie niet bekeken, maar ik weet hoe wij dit op hardware doen. We hebben Ceph, daarin kan je elke fysieke schijf(,<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.ceph.com\/docs\/master\/rbd\/\">RBD<\/a><\/noindex>) zeggen <i>clone<\/i> en binnen enkele tientallen milliseconden een tweede schijf met dezelfde specificaties krijgen, <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/IOPS\">IOPS<\/a><\/noindex>en dergelijke. Je moet begrijpen dat daar een slimme copy-on-write is. Waarom zou de cloud dit niet ook doen? Ik ben er zeker van dat ze dat op de een of andere manier proberen te realiseren.<\/p>\n<p><i><b>NS<\/b>: Maar ze zullen toch seconden, tientallen seconden nodig hebben om een instantie op te starten, Docker daarheen te brengen, enzovoort.<\/i><\/p>\n<p><b>DS<\/b>: Waarom moet je een hele instantie opstarten? We hebben immers een instantie met 32 cores, met 16\u2026 en daarin kunnen er een aantal passen \u2014 bijvoorbeeld vier. Wanneer we de vijfde aanvragen, wordt er al een instantie opgestart, en daarna wordt deze weer verwijderd.<\/p>\n<p><i><b>NS<\/b>: Ja, interessant, in Kubernetes blijkt het een ander verhaal te zijn. Onze database is niet in K8s, en er is slechts \u00e9\u00e9n instantie. Maar voor het klonen van een multiterabyte database is niet meer dan twee seconden nodig.<\/i><\/p>\n<p><b>DS<\/b>: Dat is geweldig. Maar mijn oorspronkelijke punt is dat dit geen generieke oplossing is. Ja, het is geweldig, maar het is alleen geschikt voor Postgres en alleen op \u00e9\u00e9n knooppunt.<\/p>\n<p><i><b>NS<\/b>: Het is niet alleen geschikt voor Postgres: dit zijn plannen, zoals ik al beschreef, die alleen daarmee zullen werken. Maar als we ons niet druk maken over plannen, en we gewoon alle gegevens nodig hebben voor functionele testdoeleinden, dan is dit geschikt voor elke DBMS.<\/i><\/p>\n<p><b>DS<\/b>: Jaren geleden deden we iets vergelijkbaars met LVM-snapshots. Dat is klassiek. Deze aanpak werd heel actief gebruikt. Gewoon stateful knooppunten zijn een probleem. Want je moet ze niet laten vallen, altijd aan ze denken\u2026<\/p>\n<p><i><b>NS<\/b>: Zie jij hier niet een mogelijkheid voor een hybride? Stel, stateful is een pod, deze werkt voor verschillende mensen (veel testers). We hebben \u00e9\u00e9n volume, maar dankzij het bestandssysteem zijn de klonen lokaal. Als de pod crasht, blijft de schijf bestaan \u2014 de pod start opnieuw op, leest informatie over alle klonen, herstelt alles en zegt: 'Hier zijn je klonen op deze poorten gestart, werk maar verder met hen.'.<\/i><\/p>\n<p><b>DS<\/b>: Technisch gezien betekent dit dat binnen Kubernetes dit \u00e9\u00e9n pod is, waarin we veel PostgreSQL-instanties draaien.<\/p>\n<p><i><b>NS<\/b>: Ja. Hij heeft een limiet: stel dat er tegelijkertijd niet meer dan 10 mensen mee werken. Als er 20 nodig zijn \u2014 zetten we een tweede dergelijke pod op. Volledig mogelijk om deze te klonen, waardoor we een tweede volledige schijf krijgen, met daarop dezelfde 10 'dunne' klonen. Zie jij die mogelijkheid niet?<\/i><\/p>\n<p><b>DS<\/b>: Er moeten hier beveiligingsvragen worden toegevoegd. Deze organisatievorm houdt in dat deze pod hoge privileges (capabilities) heeft, omdat hij niet-standaardbewerkingen op het bestandssysteem kan uitvoeren... Maar ik herhaal: ik geloof dat Kubernetes op de middellange termijn de storage zal verbeteren, de cloud zal de hele situatie met volumes oplossen - alles zal 'gewoon werken'. Er zal resize, klonen... Er is een volume - we zeggen: 'Maak er een nieuwe op basis van die', en binnen anderhalve seconde hebben we wat we nodig hebben.<\/p>\n<p><i><b>NS<\/b>: I don't believe in a second and a half for many terabytes. In Ceph, you do it yourself, but you are talking about clouds. Go to the cloud, clone an EBS volume of many terabytes on EC2 and see what kind of performance you get. It won't take a few seconds. I'm really curious to see when they reach that level. I understand what you\u2019re saying, but I\u2019ll allow myself to disagree.<\/i><\/p>\n<p><b>DS<\/b>: Okay, but I said in the medium term, not in the short term. Over the next few years.<\/p>\n<h2>About the PostgreSQL operator from Zalando<\/h2>\n<p>\nIn the middle of this meeting, Alexey Klyukin, a former developer from Zalando, also joined to talk about the story of the PostgreSQL operator:<\/p>\n<blockquote><p>It's great that this topic is being addressed: both Postgres and Kubernetes. When we started working on it at Zalando in 2017, it was a topic that everyone wanted to engage with, but no one was doing. Everyone was already getting Kubernetes, but when asked how to handle databases, even people like <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/kelseyhightower\">Kelsey Hightower<\/a><\/noindex>, who preached K8s, said approximately the following:<\/p>\n<p><i>\"Go to managed services and use them, don\u2019t run databases in Kubernetes. Otherwise, your K8s might decide to upgrade, take down all nodes, and your data will be gone far, far away.\"<\/i><\/p>\n<p>We decided to create an operator that would, despite this advice, run Postgres databases in Kubernetes. And we had a good basis \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/patroni\">Patroni<\/a><\/noindex>. Dit is een automatische failover voor PostgreSQL, correct uitgevoerd, dat wil zeggen gebruikmakend van etcd, consul of ZooKeeper als opslag voor clusterinformatie. Zo'n opslag die iedereen die vraagt, bijvoorbeeld wie de huidige leider is, dezelfde informatie zal geven - ondanks dat alles verdeeld is - om split brain te voorkomen. Bovendien hadden we <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/patroni\/tree\/master\/docker\">Docker-image<\/a><\/noindex> ervoor.<\/p>\n<p>Over het algemeen kwam de behoefte aan auto failover bij het bedrijf na de migratie van een interne fysieke datacenter naar de cloud. De cloud was gebaseerd op een eigen PaaS (Platform-as-a-Service) oplossing. Het was open-source, maar om het op te zetten was veel werk nodig. Het werd genoemd <noindex><a rel=\"nofollow\" href=\"https:\/\/stups.io\/\">STUPS<\/a><\/noindex>.<\/p>\n<p>In het begin was er helemaal geen Kubernetes. Juist, toen de eigen oplossing werd uitgerold, was K8s al aanwezig, maar zo onvolwassen dat het niet geschikt was voor productie. Dit was, als ik het goed heb, in 2015 of 2016. Tegen 2017 was Kubernetes min of meer volwassen geworden - er ontstond de noodzaak om daarheen te migreren.<\/p>\n<p>En we hadden al een Docker-container. Er was een PaaS die Docker gebruikte. Waarom niet K8s proberen? Waarom niet onze eigen operator schrijven? Murat Kabilov, die bij ons kwam vanuit Avito, begon dit als een vrijwilligersproject - \"spelen\" - en het project \"steeg op\".<\/p>\n<p>Maar eigenlijk wilde ik vertellen over AWS. Waarom er historisch gezien code was die verband hield met AWS...<\/p>\n<p>Wanneer je iets in Kubernetes start, moet je begrijpen dat K8s een work in progress is. Het ontwikkelt zich voortdurend, verbetert en soms gaat het zelfs kapot. Je moet goed letten op alle veranderingen in Kubernetes, en bereid zijn om je erin te verdiepen en te leren hoe het in detail werkt - mogelijk meer dan je zou willen. Dit geldt in principe voor elk platform waarop je je databases draait...<\/p>\n<p>Dus, toen we de operator maakten, hadden we Postgres dat werkte met een externe schijf (in dit geval EBS, aangezien we in AWS werkten). De database groeide en op een gegeven moment was een resize nodig: bijvoorbeeld, de oorspronkelijke grootte van EBS was 100 TB, de database had deze grootte bereikt, en nu willen we EBS naar 200 TB vergroten. Hoe? Je kunt een dump\/restore naar een nieuwe instantie maken, maar dat duurt lang en leidt tot downtime.<\/p>\n<p>Daarom wilden we een resize die het EBS-volume zou vergroten en vervolgens de bestandssysteem vertellen het nieuwe ruimte te gebruiken. We hebben dit gedaan, maar op dat moment had Kubernetes geen API voor resize-operaties. Aangezien we op AWS werkten, hebben we code geschreven voor zijn API.<\/p>\n<p>Niemand staat in de weg om hetzelfde te doen voor andere platforms. In de operator is er geen beperking dat deze alleen op AWS kan worden uitgevoerd, en niet op andere platforms. Kortom, dit is een Open Source-project: als iemand de implementatie van een nieuwe API wil versnellen - voel je vrij. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zalando\/postgres-operator\">GitHub<\/a><\/noindex>, pull-requests \u2014 het Zalando-team probeert er vrij snel op te reageren en de operator te bevorderen. Voor zover ik weet, heeft het project <noindex><a rel=\"nofollow\" href=\"https:\/\/summerofcode.withgoogle.com\/archive\/2019\/organizations\/6187982082539520\/\">deelgenomen<\/a><\/noindex> aan Google Summer of Code en andere soortgelijke initiatieven. Zalando werkt hier heel actief aan.\n<\/p><\/blockquote>\n<p><\/p>\n<h2>P.S. Bonus!<\/h2>\n<p>\nAls je ge\u00efnteresseerd bent in het onderwerp PostgreSQL en Kubernetes, willen we ook uw aandacht vestigen op de afgelopen Postgres-dinsdag, waar Nikolai sprak met <b>Alexander Kukushkin van Zalando<\/b>. De video ervan is beschikbaar <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=FE0xi7SBqsg\">hier<\/a><\/noindex>.<\/p>\n<h2>P.P.S.<\/h2>\n<p>\nLees ook op onze blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/431500\/\">Databases en Kubernetes (overzicht en video van de presentatie)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/475036\/\">Migratie van Cassandra naar Kubernetes: kenmerken en oplossingen<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/461149\/\">Een uitdagende migratie van MongoDB naar Kubernetes<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/450662\/\">Moeizame migratie van RabbitMQ naar Kubernetes<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/479438\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u043c\u0438\u043d\u0443\u0432\u0448\u0435\u0433\u043e \u0433\u043e\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0441\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u043f\u0440\u044f\u043c\u043e\u0439 \u044d\u0444\u0438\u0440 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u0433\u043e PostgreSQL-\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 #RuPostgres, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0435\u0433\u043e \u0441\u043e\u043e\u0441\u043d\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u041d\u0438\u043a\u043e\u043b\u0430\u0439 \u0421\u0430\u043c\u043e\u0445\u0432\u0430\u043b\u043e\u0432 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b \u0441 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u00ab\u0424\u043b\u0430\u043d\u0442\u0430\u00bb \u0414\u043c\u0438\u0442\u0440\u0438\u0435\u043c \u0421\u0442\u043e\u043b\u044f\u0440\u043e\u0432\u044b\u043c \u043f\u0440\u043e \u044d\u0442\u0443 \u0421\u0423\u0411\u0414 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Kubernetes. \u041c\u044b \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0441\u0442\u0435\u043d\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u044d\u0442\u043e\u0439 \u0434\u0438\u0441\u043a\u0443\u0441\u0441\u0438\u0438, \u0430 \u043d\u0430 YouTube-\u043a\u0430\u043d\u0430\u043b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u0430 \u043f\u043e\u043b\u043d\u0430\u044f \u0432\u0438\u0434\u0435\u043e\u0437\u0430\u043f\u0438\u0441\u044c: \u0411\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 Kubernetes \u041d\u0421: \u041c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u0440\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":55468,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-55467","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\/nl\/blog\/administrirovanie\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\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\udd47Postgres-\u0432\u0442\u043e\u0440\u043d\u0438\u043a \u21165: \u00abPostgreSQL \u0438 Kubernetes. CI\/CD. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00bb | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya\" \/>\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-01-20T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:03:35+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\udd47Postgres-dinsdag \u21165: \u00abPostgreSQL en Kubernetes. CI\/CD. Automatisering van testen\u00bb | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","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\udd47Postgres-\u0432\u0442\u043e\u0440\u043d\u0438\u043a \u21165: \u00abPostgreSQL \u0438 Kubernetes. CI\/CD. \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00bb | ProHoster","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/postgres-vtornik-5-postgresql-i-kubernetes-ci-cd-avtomatizatsiya-testirovaniya","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-01-20T21:00:00+00:00","article:modified_time":"2020-02-18T11:03:35+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"55467","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 19:43:31","updated":"2022-10-06 02:34:09","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/55467","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=55467"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/55467\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/55468"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=55467"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=55467"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=55467"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}