
Kunder kommer allt oftare med förfrÄgningar som: "Vi vill ha nÄgot som Amazon RDS, men billigare"; "Vi vill ha nÄgot liknande RDS, men i alla infrastrukturer". För att implementera en sÄdan managed-lösning pÄ Kubernetes har vi granskat tillstÄndet för de mest populÀra operatörerna för PostgreSQL (Stolon, operatörer frÄn Crunchy Data och Zalando) och gjort vÄrt val.
Den hÀr artikeln handlar om vÄra insikter, bÄde frÄn ett teoretiskt perspektiv (översikt över lösningar) och praktiskt (vad har valts och vad har vi Ästadkommit). Men först, lÄt oss klargöra vilka krav som stÀlls pÄ en potentiell ersÀttning för RDS...
Vad Àr RDS?
NÀr mÀnniskor pratar om RDS, sÄ menar de, enligt vÄr erfarenhet, en hanterad (managed) databas tjÀnst som:
- Àr enkel att konfigurera;
- har möjlighet att arbeta med snapshots och kunna ÄterstÀllas frÄn dem (helst med stöd för );
- möjlighet att skapa master-slave-topologier;
- har en rik lista av tillÀgg;
- erbjuder revision och hantering av anvÀndare/behörigheter.
Generellt kan tillvÀgagÄngssÀtten för att lösa den stÀllda uppgiften vara ganska olika, men vi drar oss för att anvÀnda Ansible. (En liknande slutsats gjorde ocksÄ kollegorna frÄn 2GIS efter att skapa "ett verktyg för snabb distribution av en felresistent Postgres-kluster.")
Operatörer Àr det allmÀnt accepterade tillvÀgagÄngssÀttet för att lösa sÄdana uppgifter inom Kubernetes-ekosystemet. Mer om dem i relation till databaser som körs inuti Kubernetes har teknisk direktör för "Flanta" redan berÀttat, , i .
NB: För att snabbt skapa enkla operatörer rekommenderar vi att titta pÄ vÄrt Open Source-verktyg . Genom att anvÀnda det kan detta göras utan kunskaper i Go, pÄ mer vÀlbekanta sÀtt för systemadministratörer: i Bash, Python etc.
Det finns flera populÀra K8s-operatörer för PostgreSQL:
- Stolon;
- Crunchy Data PostgreSQL Operator;
- Zalando Postgres Operator.
LÄt oss titta nÀrmare pÄ dem.
Val av operatör
Förutom de viktiga funktioner som redan nÀmnts förvÀntade vi oss ocksÄ, som infrastrukturingenjörer inom Kubernetes, följande frÄn operatörerna:
- deploy frÄn Git och med ;
- stöder pod anti-affinity;
- installation av node affinity eller node selector;
- installation av tolerations;
- möjligheter till justering;
- förstÄeliga teknologier och till och med kommandon.
Utan att gÄ in pÄ detaljer för varje punkt (frÄga i kommentarerna om det finns frÄgor kvar efter att ha lÀst hela artikeln), kan jag generellt pÄpeka att dessa parametrar behövs för en mer detaljerad beskrivning av specialiseringen av klusternoderna för att bestÀlla dem för specifika applikationer. PÄ sÄ sÀtt kan vi uppnÄ en optimal balans mellan prestanda och kostnad.
Nu â till sjĂ€lva PostgreSQL-operatörerna.
1. Stolon
frÄn det italienska företaget Sorint.lab i betraktades som en typ av referens bland operatörer för databashanteringssystem. Det Àr ett ganska gammalt projekt: den första offentliga versionen slÀpptes redan i november 2015(!), och GitHub-repot kan skryta med nÀstan 3000 stjÀrnor och 40+ bidragsgivare.
Och faktiskt Àr Stolon ett utmÀrkt exempel pÄ genomtÀnkt arkitektur:

Om konstruktionen av denna operatör kan man lĂ€sa mer detaljerat i presentationen eller . I stort sett kan man sĂ€ga att den klarar av allt som beskrivs: failover, proxy för transparent kundĂ„tkomst, sĂ€kerhetskopior⊠Dessutom erbjuder proxyĂ„tkomst genom en enda tjĂ€nst-endpoint â till skillnad frĂ„n de tvĂ„ andra lösningarna som diskuterats senare (de har tvĂ„ tjĂ€nster för Ă„tkomst till databasen).
Men Stolon , vilket gör att den inte kan distribueras sĂ„ enkelt och snabbt â "som varma bakverk" â för att skapa instanser av databashanteringssystemet i Kubernetes. Hanteringen sker via verktyget stolonctl, distribution â via Helm-diagram, och anvĂ€ndardefinierade anges i ConfigMap.
Ă ena sidan verkar det som att operatören inte riktigt Ă€r en operatör (eftersom den inte anvĂ€nder CRD). Men Ă„ andra sidan â det Ă€r ett flexibelt system som lĂ„ter dig konfigurera resurser i K8s pĂ„ det sĂ€tt som du vill.
Sammanfattningsvis tyckte vi personligen att det inte var optimalt att ha ett separat diagram för varje databas. SÄ vi började leta efter alternativ.
2. Crunchy Data PostgreSQL Operator
, en ung amerikansk startup, verkade vara ett logiskt alternativ. Dess offentliga historia började med den första versionen i mars 2017, och sedan dess har GitHub-repot fĂ„tt nĂ„got mindre Ă€n 1300 stjĂ€rnor och 50+ bidragsgivare. Den senaste versionen frĂ„n september testades för att fungera med Kubernetes 1.15â1.18, OpenShift 3.11+ och 4.4+, GKE och VMware Enterprise PKS 1.3+.
Arkitekturen för Crunchy Data PostgreSQL Operator uppfyller ocksÄ de angivna kraven:

Hantera görs via ett verktyg pgo, men det genererar i sin tur Custom Resources för Kubernetes. SÄ som potentiella anvÀndare blev vi glatt överraskade av operatören:
- det finns hantering via CRD;
- anvÀndarvÀnlig hantering (Àven den via CRD);
- integration med andra komponenter â en specialiserad samling av containerbilder för PostgreSQL och verktyg för att arbeta med den (inklusive pgBackRest, pgAudit, tillĂ€gg frĂ„n contrib osv.).
NÀr vi dock försökte börja anvÀnda operatören frÄn Crunchy Data uppstod nÄgra problem:
- Det fanns ingen möjlighet till toleranser â endast nodeSelector var tillgĂ€nglig.
- De skapade pod'arna var en del av Deployment, trots att vi distribuerade en stateful-applikation. Till skillnad frÄn StatefulSet kan inte Deployment skapa diskar.
Den sista nackdelen leder till roliga situationer: i testmiljön lyckades vi köra 3 repliker med en disk lokal lagring, vilket gjorde att operatören rapporterade att 3 repliker fungerade (Àven om sÄ inte var fallet).
En annan funktion hos denna operatör Àr dess fÀrdiga integration med olika hjÀlpsystem. Till exempel, det Àr enkelt att installera pgAdmin och pgBounce, och i förhandsinstÀllningen av Grafana och Prometheus övervÀgs. I den senaste noteras den förbÀttrade integrationen med projektet , vilket gör att operatören erbjuder en visuell presentation av PgSQL-metrics "out-of-the-box".
ĂndĂ„ ledde det mĂ€rkliga valet av genererade Kubernetes-resurser oss till att behöva hitta en alternativ lösning.
3. Zalando Postgres Operator
Zalando-produkter Ă€r vi vĂ€lbekanta med: vi har erfarenhet av att anvĂ€nda Zalenium och sjĂ€lvklart har vi provat â deras populĂ€ra HA-lösning för PostgreSQL. Om företagets tillvĂ€gagĂ„ngssĂ€tt för att skapa berĂ€ttade en av dess författare â Alexey Klyukin â i sĂ€ndningen av , och vi tyckte att den var intressant.
Detta Àr den yngsta lösningen bland de som behandlas i artikeln: den första versionen slÀpptes i augusti 2018. Trots det lilla antalet formella versioner har projektet gjort stora framsteg och redan övertrÀffat lösningen frÄn Crunchy Data med över 1300 stjÀrnor pÄ GitHub och det högsta antalet bidragsgivare (70+).
"Under huven" för denna operatör anvÀnds beprövade lösningar:
- Patroni och för hantering,
- â för sĂ€kerhetskopior,
- â som en anslutningspool.
SÄ hÀr presenteras operatörens arkitektur frÄn Zalando:

Operatören hanteras helt genom Custom Resources, skapar automatiskt en StatefulSet av containrar som sedan kan anpassas genom att lÀgga till olika sidecars i podden. Detta Àr en betydande fördel jÀmfört med operatören frÄn Crunchy Data.
Eftersom det var lösningen frÄn Zalando som vi valde bland tre övervÀgda alternativ, kommer en ytterligare beskrivning av dess funktioner att presenteras nedan, tillsammans med praktisk tillÀmpning.
Praktik med Postgres Operator frÄn Zalando
Distributionen av operatören sker mycket enkelt: det rÀcker med att ladda ner den aktuella versionen frÄn GitHub och tillÀmpa YAML-filerna frÄn katalogen . Som ett alternativ kan man Àven anvÀnda .
Efter installationen bör man se till att konfigurera . Detta görs via ConfigMap postgres-operator i det namnutrymme dÀr du installerade operatören. NÀr lagringslösningarna Àr konfigurerade kan du distribuera din första PostgreSQL-kluster.
Till exempel ser vÄr standarddistribution ut som följer:
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: staging-db
spec:
numberOfInstances: 3
patroni:
synchronous_mode: true
postgresql:
version: "12"
resources:
limits:
cpu: 100m
memory: 1Gi
requests:
cpu: 100m
memory: 1Gi
sidecars:
- env:
- name: DATA_SOURCE_URI
value: 127.0.0.1:5432
- name: DATA_SOURCE_PASS
valueFrom:
secretKeyRef:
key: password
name: postgres.staging-db.credentials
- name: DATA_SOURCE_USER
value: postgres
image: wrouesnel/postgres_exporter
name: prometheus-exporter
resources:
limits:
cpu: 500m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
teamId: staging
volume:
size: 2Gi
Denna manifest distribuerar en kluster med 3 instanser med sidecar i form av , varifrÄn vi hÀmtar applikationsmetrik. Som du ser Àr det vÀldigt enkelt, och om sÄ önskas kan man skapa ett bokstavligt talat obegrÀnsat antal kluster.
Det Ă€r vĂ€rt att notera Ă€ven webbpanelen för administration â . Den levereras tillsammans med operatören och gör det möjligt att skapa och ta bort kluster, samt arbeta med sĂ€kerhetskopior som operatören gör.

Lista över PostgreSQL-kluster

Hantera sÀkerhetskopior
En annan intressant funktion Àr stödet för . Denna mekanism skapar automatiskt roller i PostgreSQL, baserat pÄ den mottagna listan över anvÀndarnamn. DÀrefter gör API:et det möjligt att returnera listan över anvÀndare för vilka roller skapas automatiskt.
Problem och lösningar
Men anvÀndningen av operatören avslöjade snart flera betydande nackdelar:
- brist pÄ nodeSelector-stöd;
- oförmÄga att stÀnga av sÀkerhetskopior;
- nÀr funktionen för att skapa databaser anvÀnds, tilldelas inga standardbehörigheter;
- ibland saknas dokumentation eller sÄ Àr den inaktuell.
Lyckligtvis kan mĂ„nga av dessa problem lösas. LĂ„t oss börja med slutet â problemen med dokumentationen.
Du kommer troligen att stöta pÄ att det inte alltid Àr klart hur man stÀller in en sÀkerhetskopia och hur man kopplar en sÀkerhetskopieringsbucket till Operator UI. Detta nÀmns kort i dokumentationen, men en detaljerad beskrivning finns i :
- du mÄste skapa en hemlighet;
- överföra den till operatören i parametern
pod_environment_secret_namei CRD med operatörens instÀllningar eller i ConfigMap (beroende pÄ hur du valde att installera operatören).
Men som det visade sig Ă€r detta för nĂ€rvarande omöjligt. Just dĂ€rför har vi samlat med nĂ„gra extra tredjepartsanpassningar. Mer om den â se nedan.
Om du överför parametrar för sĂ€kerhetskopiering till operatören, nĂ€mligen â wal_s3_bucket och Ă„tkomstnycklarna till AWS S3, kommer den att sĂ€kerhetskopiera allt: inte bara databaser i produktion, utan Ă€ven staging. Det passade inte oss.
I beskrivningen av parametrarna för Spilo, vilket Àr en grundlÀggande Docker-wrapper för PgSQL vid anvÀndning av operatören, visade det sig: det gÄr att överföra parametern WAL_S3_BUCKET som tom, vilket stÀnger av sÀkerhetskopior. Dessutom, till vÄr stora glÀdje hittade jag ocksÄ en , som vi omedelbart accepterade i vÄr fork. Nu rÀcker det med att enkelt lÀgga till enableWALArchiving: false i resursen för PostgreSQL-klustret.
Ja, det fanns möjlighet att göra det annorlunda genom att starta 2 operatörer: en för staging (utan sÀkerhetskopior) och en för produktion. Men sÄ kunde vi klara oss med en.
Okej, vi lÀrde oss att ge databaser Ätkomst till S3 och sÀkerhetskopior började hamna i lagringen. Hur fÄr man sÀkerhetskopiorna att fungera i Operator UI?

I Operator UI mÄste du lÀgga till 3 variabler:
-
SPILO_S3_BACKUP_BUCKET -
AWS_ACCESS_KEY_ID -
AWS_SECRET_ACCESS_KEY
Efter detta kommer hanteringen av sÀkerhetskopior att bli tillgÀnglig, vilket i vÄrt fall kommer att förenkla arbetet med staging, sÄ att vi kan leverera snapshots frÄn produktion utan extra skript.
Som en ytterligare fördel nÀmndes möjligheten att arbeta med Teams API och de stora möjligheterna att skapa databaser och roller med hjÀlp av operatören. Men de skapade rollerna hade inga standardbehörigheter. DÀrför kunde en anvÀndare med lÀsbehörighet inte lÀsa de nya tabellerna.
Varför Ă€r det sĂ„? Trots att det i koden nödvĂ€ndiga GRANT, de tillĂ€mpas lĂ„ngt ifrĂ„n alltid. Det finns 2 metoder: syncPreparedDatabases och syncDatabases. I syncPreparedDatabases â trots att det i avsnittet preparedDatabases finns ett villkor defaultRoles och defaultUsers för att skapa roller, â tillĂ€mpas inte behörigheterna som standard. Vi Ă€r i fĂ€rd med att förbereda en patch sĂ„ att dessa rĂ€ttigheter automatiskt tillĂ€mpas.
Och den sista punkten bland de aktuella förbĂ€ttringarna â , som lĂ€gger till Node Affinity i den skapade StatefulSet. VĂ„ra kunder föredrar ofta att minska kostnaderna genom att anvĂ€nda spot-instanser, och det Ă€r uppenbart inte lĂ€mpligt att placera databastjĂ€nster pĂ„ dem. Denna frĂ„ga skulle ocksĂ„ kunna lösas med tolerans, men att ha Node Affinity ger större sĂ€kerhet.
Vad blev resultatet?
Som resultat av att lösa de nÀmnda problemen har vi forkat Postgres Operator frÄn Zalando till , dÀr den byggs med sÄ anvÀndbara patchar. Och för att öka bekvÀmligheten har vi ocksÄ .
Lista över PR:er som tagits emot i forken:
- ;
- ;
- ;
- .
Det vore fantastiskt om gemenskapen kunde stödja dessa PR:er sÄ att de kom med i upstream med nÀsta version av operatören (1.6).
Bonus! FramhÀvt projekt med migrering av produktion
Om du anvÀnder Patroni kan du migrera en livsproduktion med minimal nedtid till operatören.
Spilo möjliggör att skapa standby-kluster via S3-lagringar med , dÀr den binÀra loggen för PgSQL först sparas i S3 och sedan hÀmtas av replik. Men vad gör man om du inte anvÀnder Wal-E i en gammal infrastruktur? Lösningen pÄ detta problem har redan pÄ Habré.
Logisk replikering av PostgreSQL kommer till hjÀlp. Men vi ska inte gÄ in pÄ detaljer om hur man skapar pub-likningar och prenumerationer, eftersom⊠vÄr plan misslyckades.
Problemet Àr att databasen hade flera tunga tabeller med miljontals rader, som dessutom hela tiden fylldes pÄ och togs bort. med copy_data, nÀr en ny replik kopierar allt innehÄll frÄn mÀstaren, hÀngde helt enkelt inte med mÀstaren. InnehÄllskopieringen fungerade i en vecka men nÄdde aldrig mÀstaren. Till slut hjÀlpte det att fÄ klarhet i problemet genom kollegor frÄn Avito: man kan flytta data med hjÀlp av pg_dump. Jag kommer att beskriva vÄr (lite modifierade) version av denna algoritm.
Idén Àr att skapa en inaktiv prenumeration kopplad till en specifik replikationsslot och sedan korrigera transaktionsnumret. Det fanns repliker tillgÀngliga för produktionsarbetet. Detta Àr viktigt eftersom repliken kommer att skapa en konsekvent dump och fortsÀtta ta emot Àndringar frÄn master.
I de följande kommandona som beskriver migrationsprocessen kommer följande beteckningar att anvÀndas för vÀrdarna:
- master â ursprunglig server;
- replica1 â strömrepliken pĂ„ den gamla produktionen;
- replica2 â ny logisk replik.
Migrationsplan
1. Skapa en prenumeration för alla tabeller i schemat public av databasen dbname:
psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"
2. Skapa en replikationsslot pÄ master:
psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"
3. Stoppa replikationen pÄ den gamla repliken:
psql -h replica1 -c "select pg_wal_replay_pause();"
4. HÀmta transaktionsnumret frÄn master:
psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"
5. Ta en dump frÄn den gamla repliken. Vi kommer att göra detta med flera trÄdar, vilket kommer att pÄskynda processen:
pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname
6. Ladda upp dumpen till den nya servern:
pg_restore -h replica2 -F d -j 8 -d dbname dump/
7. Efter att dumpen har laddats kan replikationen startas pÄ strömrepliken:
psql -h replica1 -c "select pg_wal_replay_resume();"
7. Skapa en prenumeration pÄ den nya logiska repliken:
psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"
8. HĂ€mta oid prenumerationen:
psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"
9. Anta att vi har fÄtt oid=1000. TillÀmpa transaktionsnumret pÄ prenumerationen:
psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"
10. Starta replikationen:
psql -h replica2 -d dbname -c "alter subscription oldprod enable;"
11. Kontrollera statusen för prenumerationen, replikationen bör fungera:
psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"
12. Efter att replikationen har startat och databaserna har synkroniserats kan omkopplingen göras.
13. Efter att replikationen har stÀngts av Àr det nödvÀndigt att korrigera sekvenserna. Detta Àr vÀl beskrivna .
Tack vare denna plan blev omkopplingen av med minimal fördröjning.
Slutsats
Kubernetes-operatörer gör det möjligt att förenkla olika ÄtgÀrder genom att reducera dem till att skapa K8s-resurser. Men nÀr man uppnÄr fantastisk automatisering med deras hjÀlp, bör man komma ihÄg att det ocksÄ kan medföra vissa ovÀntade nuanser, sÄ var noga med att smart vÀlja operatörer.
Efter att ha granskat tre av de mest populĂ€ra Kubernetes-operatörerna för PostgreSQL, valde vi projektet frĂ„n Zalando. Vi stötte dock pĂ„ vissa svĂ„righeter, men resultatet överraskade verkligen positivt, sĂ„ vi planerar att utvidga denna erfarenhet till andra PgSQL-installationer. Om du har erfarenhet av liknande lösningar â vi ser fram emot att lĂ€sa dina detaljer i kommentarerna!
P.S.
LÀs Àven i vÄr blogg:
- «»;
- «»;
- «».
KĂ€lla: habr.com
