Postgres-martedì n. 5: «PostgreSQL e Kubernetes. CI/CD. Automazione dei test»

Postgres-martedì n. 5: «PostgreSQL e Kubernetes. CI/CD. Automazione dei test»

Alla fine dello scorso anno si è svolta un'altra diretta della comunità russa di PostgreSQL #RuPostgres, durante la quale il cofondatore Nikolai Samokhvalov ha conversato con il direttore tecnico di "Flant" Dmitry Stolyarov su questo DBMS nel contesto di Kubernetes.

Pubbliciamo il verbale della parte principale di questa discussione, e su canale YouTube della comunità è stata pubblicata la registrazione video completa:

Guarda il video

Database e Kubernetes

NS: Oggi non parleremo di VACUUM e CHECKPOINT. Vogliamo parlare di Kubernetes. So che hai già molti anni di esperienza. Ho visto i tuoi video e alcuni li ho anche rivisti a pezzi... Iniziamo subito: perché Postgres o MySQL in K8s?

DS: Non c'è una risposta definitiva a questa domanda. Ma in generale, si tratta di semplicità e comodità... potenziali. A tutti piacciono i servizi gestiti.

NS: Come RDS: solo che a casa tua?

DS: Sì: come RDS, solo ovunque.

NS: "Ovunque" è una buona osservazione. Nelle grandi aziende tutto è situato in posti diversi. E allora perché, se si tratta di una grande azienda, non prendere una soluzione pronta? Ad esempio, Nutanix ha i suoi sviluppi, altre aziende (VMware…) hanno lo stesso "RDS, solo a casa".

DS: Ma stiamo parlando di una realizzazione specifica, che funzionerà solo in determinate condizioni. E se parliamo di Kubernetes, qui c'è una grande varietà di infrastruttura (che può essere in K8s). In sostanza è uno standard per API verso il cloud...

NS: E anche gratuito!

DS: Non è così importante. La gratuità è importante per un segmento di mercato non molto grande. Ciò che conta è un'altra cosa... Probabilmente ti ricordi la relazione "Database e Kubernetes»?

NS: Sì.

DS: Ho capito che è stata ricevuta in modo molto ambiguo. Alcune persone hanno pensato che stessi dicendo: "Ragazzi, andiamo a usare tutti i DB in Kubernetes!", mentre altri hanno deciso che si trattava di orrende biciclette. Ma io volevo dire un'altra cosa: "Guardate cosa sta succedendo, quali problemi ci sono e come possiamo risolverli. Adesso andare con i database in Kubernetes? In produzione? Beh, solo se ti piace… occuparti di determinate cose. Ma per il dev, posso dire che lo consiglio. Per il dev è molto importante la dinamicità nella creazione/cancellazione degli ambienti."

NS: Con dev intendi tutti gli ambienti che non sono prod? Staging, QA…

DS: Se parliamo di perf-stand, probabilmente no, perché i requisiti sono specifici. Se parliamo di casi particolari, dove su staging è necessaria un'enorme DB, probabilmente no... Se si tratta di un ambiente statico, a lungo termine, quale beneficio c'è nel fatto che il database si trovi in K8s?

NS: Nessuno. Ma dove vediamo ambienti statici? Gli ambienti statici sono già obsoleti domani.

DS: Lo staging può essere statico. Abbiamo clienti…

NS: Sì, ne ho anche io. È un grosso problema avere un database di 10 TB, mentre lo staging è di 200 GB…

DS: Ho un caso molto interessante! Nel nostro staging c'è il database di produzione, in cui vengono apportate modifiche. E c'è un pulsante: «rilascialo in produzione». Queste modifiche — le differenze — vengono caricate (sembra che si sincronizzino semplicemente tramite API) in produzione. È un'opzione molto esotica.

NS: Ho visto startup nella Silicon Valley che sono in RDS o addirittura in Heroku ancora — queste sono storie di 2-3 anni fa — e scaricano il dump sul loro laptop. Perché il database è solo di 80 GB e c'è spazio nel laptop. Poi comprano dischi per ciascuno, così da avere 3 database per condurre diversi sviluppi. Succede anche questo. Ho visto anche che non hanno paura di copiare da prod a staging — dipende molto dall'azienda. Ma ho anche visto che hanno molta paura, e che spesso manca il tempo e le mani. Ma prima di passare a questo argomento, vorrei sentire parlare di Kubernetes. Ho capito bene che in produzione non ce l'ha ancora nessuno?

DS: Abbiamo database piccoli in produzione. Si tratta di volumi di decine di gigabyte e servizi non critici, per i quali non ci si è presi la briga di fare repliche (e non c'è nemmeno una tale esigenza). E a condizione che ci sia un buon storage sotto Kubernetes. Questo database funzionava in una macchina virtuale — condizionatamente in VMware, sopra un sistema di archiviazione. L'abbiamo trasferito in PV e ora possiamo spostarlo da una macchina all'altra.

NS: Database di questa dimensione, fino a 100 GB, su buoni dischi e con una buona rete possono essere distribuiti in pochi minuti, giusto? Una velocità di 1 GB al secondo non è più esotica.

DS: Sì, per un'operazione lineare non è un problema.

NS: Ok, per prod dobbiamo solo pensarci. E se consideriamo Kubernetes per ambienti non di produzione — come procedere? Vedo che in Zalando fanno un operatore, in Crunchy stanno sviluppando, e ci sono anche altre opzioni. E c'è OnGres — è il nostro buon amico Alvaro dalla Spagna: in sostanza fanno non solo operatore, ma un'intera distribuzione (StackGres), in cui oltre al Postgres' stesso è stato deciso di includere anche il backup, un proxy Envoy…

DS: A cosa serve Envoy? Per il bilanciamento del traffico di Postgres?

NS: Sì. Cioè, lo vedono così: se prendiamo una distribuzione di Linux e il suo kernel, l'ordinario PostgreSQL è il kernel, mentre loro vogliono creare una distribuzione che sia amichevole con il cloud e possa girare in Kubernetes. Stanno integrando componenti (backup, ecc.) e affinando affinché funzionino bene.

DS: Molto interessante! In sostanza, è un software per creare il proprio Postgres gestito.

NS: Le distribuzioni Linux hanno sempre problemi: come fare i driver affinché l'intero hardware venga supportato. E la loro idea è che funzioneranno in Kubernetes. So che nell'operatore Zalando abbiamo recentemente visto un'integrazione con AWS e questo non è molto positivo. Non dovrebbe esserci un'integrazione con un'infrastruttura specifica — qual è allora il senso?

DS: Non so in quale situazione specifica si sia legato Zalando, ma attualmente in Kubernetes lo storage è fatto in modo tale che non è possibile effettuare un backup su disco in modo generico. Recentemente, nello standard — nell'ultima versione della specifica CSI — è stata introdotta la possibilità di snapshot, ma dove è stata implementata? Onestamente, è tutto ancora così grezzo… Stiamo provando CSI su AWS, GCE, Azure, vSphere, ma appena inizi a utilizzarlo, diventa evidente che non è ancora pronto.

NS: Per questo a volte è necessario legarsi all'infrastruttura. Penso che sia ancora una fase iniziale — i problemi di crescita. Domanda: cosa consiglieresti ai neofiti che vogliono provare PgSQL in K8s? Quale operatore, magari?

DS: Il problema è che per noi Postgres è il 3%. Abbiamo anche una lunga lista di vari software in Kubernetes, non ci sarà nemmeno bisogno di elencarli tutti. Per esempio, Elasticsearch. Ci sono un sacco di operatori: alcuni si stanno sviluppando attivamente, altri no. Abbiamo redatto internamente dei criteri su cosa deve avere un operatore affinché lo prendessimo sul serio. Parlo di un operatore specificamente per Kubernetes — non di 'un operatore per fare qualcosa nelle condizioni di Amazon'… Infatti, stiamo utilizzando abbastanza massicciamente (= quasi tutti i clienti) l'unico operatore — per Redis (presto pubblicheremo un articolo anche su di lui).

NS: E per MySQL non esiste nemmeno? So che Percona… dato che ora si occupano di MySQL, MongoDB e Postgres, dovrebbero creare qualcosa di universale: per tutti i database, per tutti i fornitori di cloud.

DS: Non abbiamo avuto tempo di esaminare gli operatori per MySQL. Per noi questo non è attualmente il focus principale. MySQL funziona bene in modalità standalone. A cosa serve un operatore, se puoi semplicemente avviare il database… Puoi avviare un container Docker con Postgres, oppure farlo in modo semplice.

NS: C'era anche questa domanda. Davvero senza operatore?

DS: Sì, siamo al 100% con PostgreSQL avviato senza operatore. Per ora è così. Utilizziamo attivamente l'operatore per Prometheus, per Redis. Abbiamo in programma di trovare un operatore per Elasticsearch, poiché è quello che ha maggiore urgenza, perché vogliamo installarlo nel 100% dei casi in Kubernetes. Allo stesso modo, vogliamo arrivare a installare sempre MongoDB in Kubernetes. Qui si presentano delle esigenze specifiche: c'è la sensazione che in questi casi si possa fare qualcosa. Per quanto riguarda Postgres, non abbiamo nemmeno guardato. Certo, sappiamo dell'esistenza di varie opzioni, ma di fatto abbiamo standalone.

Database per test in Kubernetes

NS: Passiamo al tema del testing. Come distribuire le modifiche nel database — dal punto di vista della prospettiva DevOps. Ci sono microservizi, molti database, c'è sempre qualcosa che cambia. Come garantire un buon CI/CD affinché dal punto di vista del DBMS sia tutto a posto? Qual è il tuo approccio?

DS: Non può esserci una risposta unica. Ci sono diversi parametri. Il primo è la dimensione del database che vogliamo distribuire. Hai accennato al fatto che nelle aziende si hanno approcci diversi riguardo al fatto che la copia del database di produzione sia presente su dev e stage.

NS: E in contesti di GDPR, penso che siano sempre più cauti… Posso dire che in Europa hanno già iniziato a multare.

DS: Ma spesso è possibile scrivere software che esegue un dump dalla produzione e lo offusca. Si ottengono dati di produzione (snapshot, dump, copia binaria…), ma sono anonimizzati. In alternativa, possono esistere script per la generazione: possono essere fixture o semplicemente uno script che genera un grande database. Il problema è: quanto tempo ci vuole per creare l'immagine di base? E quanto tempo ci vuole per distribuirla nel contesto desiderato?

Siamo arrivati a uno schema: se il cliente ha un insieme di dati fixture (versione minima del database), allora di default utilizziamo quelli. Se si tratta di ambienti di review, quando abbiamo creato un branch, si è avviato un'istanza dell'applicazione — lì distribuiamo un piccolo database. Ma è andata bene anche. una versione, quando dal production facciamo un dump ogni giorno (di notte) e costruiamo un container Docker con PostgreSQL e MySQL basato su questi dati caricati. Se da questa immagine bisogna distribuire la base 50 volte, è piuttosto semplice e veloce.

NS: Con una semplice copia?

DS: I dati sono memorizzati direttamente nell'immagine Docker. Cioè, abbiamo un'immagine pronta, magari di 100 GB. Grazie ai layer in Docker possiamo distribuire rapidamente questa immagine il numero necessario di volte. È un metodo semplice, ma funziona piuttosto bene.

NS: Poi, quando testate, viene cambiato direttamente all'interno di Docker, giusto? Copy-on-write all'interno di Docker — eliminiamo e ricominciamo, tutto bene. Ottimo! E lo state già utilizzando a pieno?

DS: Da un po'.

NS: Ci occupiamo di cose molto simili. Solo che noi non usiamo il copy-on-write di Docker, ma un altro tipo.

DS: Non è generico. Ma quello di Docker funziona ovunque.

NS: In teoria, sì. Ma anche noi abbiamo dei moduli, possiamo creare vari moduli e lavorare con vari file system. Qui c'è un punto. Noi guardiamo tutto questo da un'altra prospettiva, quella di Postgres. Ora ho guardato dalla prospettiva di Docker e ho visto che tutto funziona. Ma se il database è enorme, ad esempio 1 TB, allora diventa tutto lungo: sia le operazioni notturne, sia il caricamento in Docker... E se dobbiamo caricare 5 TB in Docker... O va bene tutto?

DS: Che differenza fa: sono solo blob, semplicemente bit e byte.

NS: La differenza è: lo fate tramite dump e restore?

DS: Assolutamente no. I metodi di generazione di questa immagine possono essere diversi.

NS: Per alcuni clienti abbiamo fatto in modo che invece di generare regolarmente l'immagine di base, la manteniamo sempre aggiornata. Essa in sostanza è una replica, ma i dati non vengono ottenuti direttamente dal master, ma tramite un archivio. Un archivio binario, dove i WAL vengono applicati ogni giorno, lì vengono anche creati i backup... Questi WAL poi arrivano — con un piccolo ritardo (giusto 1-2 secondi) — fino all'immagine di base. Da essa cloniamo in qualsiasi modo — adesso per default abbiamo ZFS.

DS: Ma con ZFS sei limitato a un singolo nodo.

NS: Sì. Ma ZFS ha anche un magico send: con cui puoi inviare uno snapshot e anche (questo non l'ho ancora testato molto, ma...) puoi inviare una delta tra due PGDATA. In realtà, abbiamo anche un altro strumento che non abbiamo considerato molto per tali attività. In PostgreSQL c'è pg_rewind, che funge da «smart» rsync, saltando gran parte di ciò che non vale la pena vedere, perché non è cambiato. Possiamo effettuare una rapida sincronizzazione tra due server e tornare indietro allo stesso modo.

Stiamo cercando di creare uno strumento da questa prospettiva più DBA per fare esattamente ciò di cui parlavi: abbiamo un database, ma vogliamo testare qualcosa 50 volte, quasi contemporaneamente.

DS: 50 volte significa che hai bisogno di ordinare 50 istanze Spot.

NS: No, facciamo tutto su un'unica macchina.

DS: Ma come puoi distribuire 50 volte, se questo unico database è, diciamo, di un terabyte? Probabilmente ha bisogno di circa 256 GB di RAM?

NS: Sì, a volte occorre molta memoria — è normale. Ma ecco un esempio dalla vita reale. Su una macchina di produzione ci sono 96 core e 600 GB. Di questi, 32 core vengono utilizzati per il DB (anche se a volte bastano 16 core) e la memoria è di 100-120 GB.

DS: E ci stanno 50 copie?

NS: Ma la copia è una, poi si utilizza copy-on-write (ZFS)… Ti spiego meglio.

Abbiamo, ad esempio, un database di 10 TB. Abbiamo creato un disco per esso e ZFS ha già ridotto le dimensioni del 30-40%. Poiché non facciamo test di carico, il tempo di risposta esatto non è importante: può essere fino a 2 volte più lento — va bene.

Diamo la possibilità a programmatori, QA, DBA, ecc. di effettuare test in 1-2 thread. Ad esempio, possono avviare una migrazione. Non richiede immediatamente 10 core — ha bisogno di 1 backend di Postgres, 1 core. La migrazione può avviarsi — magari autovacuum può anche avviarsi di nuovo, a quel punto sarà attivato il secondo core. Abbiamo dedicato 16-32 core, così 10 persone possono lavorare contemporaneamente, senza problemi.

Poiché fisicamente PGDATA è identica, si finisce per ingannare Postgres in realtà. La questione è che, ad esempio, vengono avviati 10 Postgres contemporaneamente. Qual è il problema in genere? Si impostano shared_buffers, diciamo, al 25%. Di conseguenza, si tratta di 200 GB. Non puoi avviare più di tre di questi, perché la memoria finisce.

Ma a un certo punto abbiamo capito che non era necessario: impostiamo shared_buffers a 2 GB. PostgreSQL ha effective_cache_size, e in realtà è solo lui a influenzare i piani. Lo impostiamo a 0,5 TB. E non importa nemmeno che in realtà non ci siano: costruisce piani come se ci fossero.

Pertanto, quando testiamo una migrzione, possiamo raccogliere tutti i piani: vedremo come si comporterà in produzione. I tempi saranno diversi (più lenti), ma i dati che leggiamo realmente e i piani stessi (quali JOIN ci sono, ecc.) resteranno esattamente gli stessi di in produzione. In parallelo, possiamo eseguire molteplici controlli su una sola macchina.

DS: Non pensi che ci siano alcuni problemi? Il primo è che questa soluzione funziona solo con PostgreSQL. Questo approccio è molto specifico e non generico. Il secondo è che Kubernetes (e tutto ciò su cui si basano ora le tecnologie cloud) prevede numerosi nodi, e questi nodi sono effimeri. Nel tuo caso, invece, si tratta di un nodo stateful e persistente. Questi aspetti suscitano delle contraddizioni in me.

NS: Prima di tutto, concordo, si tratta di una questione puramente legata a Postgres. Penso che se abbiamo un certo direct IO e un buffer pool quasi per tutta la memoria, questo approccio non sia valido: i piani saranno diversi. Ma per ora stiamo solo lavorando con Postgres e non pensiamo agli altri.

Riguardo a Kubernetes. Dici sempre che il nostro database è persistente. Se un'istanza si guasta, l'importante è salvare il disco. Anche la nostra piattaforma è in Kubernetes, con il componente PostgreSQL separato (anche se un giorno sarà integrato). Pertanto, è così: l'istanza è caduta, ma abbiamo salvato il suo PV e semplicemente lo abbiamo collegato a un'altra (nuova) istanza, come se non fosse successo nulla.

DS: Dal mio punto di vista, creiamo pod in Kubernetes. K8s è elastico: i nodi vengono richiesti da soli secondo le necessità. Il compito è semplicemente creare un pod e dire che ha bisogno di X risorse, e K8s si occuperà del resto. Tuttavia, il supporto per i storage in Kubernetes rimane instabile: in 1.16, in 1.17 (questa versione è stata rilasciata settimane fa) queste funzionalità diventano solo una beta.

Passerà mezzo anno o un anno, e diventerà più o meno stabile, o almeno annunciato come tale. Allora la possibilità di snapshot e resize risolverà completamente il tuo problema. Perché hai un database. Sì, potrebbe non essere molto veloce, ma la velocità dipende da cosa c'è 'sotto il cofano', poiché alcune implementazioni sanno gestire la copia e il copy-on-write a livello di sistema di memorizzazione.

NS: Qui ci vuole anche che tutti i motori (Amazon, Google...) inizino a supportare questa versione — anche questo richiede tempo.

DS: Al momento non li usiamo. Usiamo il nostro.

Sviluppo locale su Kubernetes

NS: Ti è mai capitato di avere un desiderio del genere, quando devi avviare tutti i pod su una sola macchina e fare un piccolo test. Per ottenere rapidamente una prova di concetto, vedere se l'applicazione funziona in Kubernetes, senza dover dedicare un mucchio di macchine per questo. C'è Minikube, giusto?

DS: Mi sembra che questo caso — l'esecuzione su un nodo — riguardi esclusivamente lo sviluppo locale. O qualche manifestazione di un tale schema. C'è Minikube, c'è k3s, (Kubernetes IN Docker) e. Stiamo andando verso l'utilizzo di Kubernetes IN Docker. Abbiamo appena iniziato a lavorare su di esso per i test.

NS: Pensavo in precedenza che fosse un tentativo di imballare tutti i pod in un'unica immagine Docker. Ma si è rivelato essere tutt'altro. Ci sono comunque contenitori separati, pod separati — solo in Docker.

DS: Sì. E lì è stata realizzata un'imitazione piuttosto divertente, ma il senso è questo... Abbiamo uno strumento per il deployment — werf. Vogliamo fare una modalità in essa — diciamo werf up: «Alzami un Kubernetes locale». E poi avviare lì un werf follow. Allora lo sviluppatore potrà modificare nell'IDE, mentre nel sistema è in esecuzione un processo che rileva le modifiche e ricompila le immagini, ridistribuendole nel K8s locale. In questo modo vogliamo cercare di risolvere il problema dello sviluppo locale.

Snapshot e clonazione del DB nella realtà K8s

NS: Se torniamo al copy-on-write. Ho notato che anche nei cloud ci sono snapshot. Funzionano in modo diverso. Ad esempio, in GCP: hai un'istanza multi-terabyte sulla costa orientale degli Stati Uniti. Fai snapshot periodici. Sollevi una copia del disco dallo snapshot sulla costa occidentale — dopo pochi minuti è già tutto pronto, funziona molto rapidamente, solo che la cache deve essere riempita in memoria. Ma questi cloni (snapshot) servono per ‘provisionare’ un nuovo volume. È fantastico quando hai bisogno di creare molte istanze.

Tuttavia, per i test, mi sembra che gli snapshot di cui parli in Docker o di cui parlo io in ZFS, btrfs e anche LVM… — permettono proprio di non generare realmente nuovi dati su una sola macchina. Nel cloud dovresti anche pagare per essi ogni volta e aspettare non più secondi, ma minuti (e nel caso del lazy loading, forse, anche ore).

Invece, puoi ottenere questi dati in un secondo o due, eseguire il test e scartare. Questi snapshot risolvono diverse esigenze. Nel primo caso — per scalare e ottenere nuove repliche, mentre nel secondo — per i test.

DS: Non sono d'accordo. Eseguire un clone corretto dei volumi è compito del cloud. Non ho visto la loro implementazione, ma so come lo facciamo noi sull'hardware. Abbiamo Ceph, in cui si può dire a qualsiasi volume fisico (RBD) clone e ottenere, in pochi millisecondi, un secondo volume con le stesse caratteristiche, IOPSe così via. Bisogna capire che all'interno c'è un ingegnoso copy-on-write. Perché il cloud non dovrebbe fare lo stesso? Sono certo che stiano cercando di farlo, in un modo o nell'altro.

NS: Ma avranno comunque bisogno di secondi, decine di secondi, per avviare l'istanza, portare lì Docker, ecc.

DS: Perché è necessario avviare un'intera istanza? Abbiamo già un'istanza con 32 core, 16... e in essa entra un certo numero di volumi - ad esempio, quattro. Quando richiediamo il quinto, si avvia un'istanza, che poi verrà eliminata.

NS: Già, interessante, in Kubernetes si ha una storia diversa. La nostra Borsa dati non è in K8s, e c'è un'unica istanza. Tuttavia, ci vogliono non più di due secondi per clonare un database di diversi terabyte.

DS: È fantastico. Ma la mia idea originaria è che questa non è una soluzione generica. Sì, è fantastica, ma è adatta solo per Postgres e solo su un nodo.

NS: Non è adatta solo per Postgres: questi piani, come ho descritto, funzioneranno solo in esso. Ma se non ci si preoccupa dei piani e abbiamo solo bisogno di tutti i dati per test funzionali, allora andrà bene per qualsiasi DBMS.

DS: Molti anni fa abbiamo realizzato qualcosa di simile con gli snapshot LVM. È un classico. Questo approccio è stato utilizzato molto attivamente. Solo che i nodi stateful sono un dolore. Perché non si possono far cadere, bisogna sempre tenerli a mente...

NS: Non vedi qui una certa possibilità di un ibrido? Supponiamo che lo stateful sia un pod, e opera con più persone (molti tester). Abbiamo un solo volume, ma grazie al file system i cloni sono locali. Se il pod cade, il disco rimane - il pod si riavvierà, recupererà informazioni su tutti i cloni, riavvierà tutto e dirà: «Ecco i vostri cloni su queste porte, continuate a lavorare con loro».

DS: Tecnicamente significa che all'interno di Kubernetes è un pod, all'interno del quale facciamo partire più Postgres.

NS: Già. Ha un limite: supponiamo che simultaneamente non ci lavorino più di 10 persone. Se ne servono 20, avviamo un secondo pod di questo tipo. Possiamo clonarlo completamente, ottenendo un secondo volume completo, e avrà altre 10 «clone snelli». Non vedi questa possibilità?

DS: È necessario aggiungere qui domande sulla sicurezza. Questo tipo di organizzazione implica che questo pod abbia privilegi elevati (capabilities), poiché può eseguire operazioni non standard sul filesystem… Ma ripeto: ritengo che a medio termine Kubernetes risolverà i problemi dello storage, e nei cloud risolveranno l'intera questione dei volumi - tutto funzionerà «normalmente». Ci sarà il resize, il cloning… C'è un volume - diciamo: «Crea un nuovo volume basato su quello», - e dopo un secondo e mezzo otteniamo ciò di cui abbiamo bisogno.

NS: Non credo che ci vogliano un secondo e mezzo per molti terabyte. Su Ceph lo fai tu, ma parli dei cloud. Vai sul cloud, su EC2 clona un volume EBS di diversi terabyte e guarda quale sarà la performance. Non ci vorranno pochi secondi. Sono molto curioso di sapere quando arriveranno a tale valore. Capisco di cosa stai parlando, ma mi permetto di dissentire.

DS: Va bene, ma ho detto che a medio termine, non a breve termine. Nel giro di alcuni anni.

Riguardo all'operatore per PostgreSQL di Zalando

A metà di questo incontro si è unito anche Alexey Klyukin, ex sviluppatore di Zalando, che ha raccontato la storia dell'operatore PostgreSQL:

È fantastico che si parli di questo argomento: sia Postgres che Kubernetes. Quando abbiamo iniziato a lavorare su di esso in Zalando nel 2017, era un argomento che tutti volevano trattare, ma nessuno lo faceva. Tutti avevano già Kubernetes, ma quando si chiedeva come gestire i database, anche persone come Kelsey Hightower, che predicavano K8s, dicevano più o meno quanto segue:

«Andate verso i servizi gestiti e utilizzateli, non avviate database in Kubernetes. Altrimenti, il vostro K8s deciderà, per esempio, di fare un aggiornamento, spegnerà tutti i nodi e i vostri dati voleranno lontano lontano».

Abbiamo deciso di creare un operatore che, contrario a questo consiglio, avviasse il database Postgres in Kubernetes. E avevamo una buona base - Patroni. Questo è un failover automatico per PostgreSQL, realizzato correttamente, cioè utilizzando etcd, consul o ZooKeeper come archivio delle informazioni sul cluster. Un archivio che fornisce a tutti gli utenti che richiedono, ad esempio, chi è attualmente il leader, le stesse informazioni - nonostante tutto sia distribuito - per evitare il fenomeno del split brain. Inoltre, avevamo un Docker image per esso.

In generale, la necessità di un auto failover è emersa dopo la migrazione da un data center fisico interno al cloud. Il cloud era basato su una soluzione PaaS (Platform-as-a-Service) proprietaria. Era Open Source, ma per implementarlo era necessaria una notevole quantità di lavoro. Si chiamava STUPS.

All'inizio non c'era alcun Kubernetes. Anzi, quando è stata implementata la soluzione proprietaria, K8s era già presente, ma era così grezzo che non era adatto per la produzione. Era, credo, il 2015 o il 2016. Nel 2017, Kubernetes era diventato relativamente maturo, ed era emersa la necessità di migrare lì.

E avevamo già un container Docker. C'era PaaS che utilizzava Docker. Perché non provare K8s? Perché non scrivere il proprio operatore? Murat Kabilov, che è arrivato da noi da Avito, ha iniziato questo come progetto di iniziativa personale - “giocare”, - e il progetto ha “decollato”.

Ma in realtà volevo parlare di AWS. Perché storicamente c'era codice legato ad AWS...

Quando si avvia qualcosa in Kubernetes, bisogna capire che K8s è un work in progress. Si evolve continuamente, si migliora e a volte si rompe. È necessario prestare attenzione a tutte le modifiche in Kubernetes e essere pronti, se necessario, a immergersi in esso e capire come funziona nei dettagli - probabilmente più di quanto si vorrebbe. Questo è un aspetto comune a qualsiasi piattaforma su cui si eseguono i propri database...

Quindi, quando abbiamo creato l'operatore, avevamo Postgres che lavorava con un volume esterno (in questo caso - EBS, poiché lavoravamo in AWS). Il database cresceva e, a un certo punto, si è reso necessario un resize: ad esempio, la dimensione iniziale di EBS era di 100 TB, il database ha raggiunto quella dimensione, ora vogliamo aumentare EBS a 200 TB. Come? Supponiamo di poter fare un dump/restore su una nuova istanza, ma è lungo e comporta un downtime.

Pertanto, volevamo un resize che aumentasse la partizione dell'EBS e poi dicesse al file system di utilizzare il nuovo spazio. E ci siamo riusciti, ma in quel momento Kubernetes non aveva alcuna API per l'operazione di resize. Poiché lavoravamo su AWS, abbiamo scritto il codice per la sua API.

Nessuno impedisce di fare lo stesso per altre piattaforme. Nell'operatore non c'è alcun vincolo che possa essere eseguito solo su AWS; funzionerà anche su altre piattaforme. In fin dei conti, questo è un progetto Open Source: se qualcuno desidera accelerare l'uso di una nuova API - è il benvenuto. C'è GitHub, pull-request — il team di Zalando cerca di rispondere abbastanza rapidamente e supportare l'operatore. Per quanto ne so, il progetto ha partecipato a Google Summer of Code e ad altre iniziative simili. Zalando sta lavorando attivamente su di esso.

P.S. Bonus!

Se siete interessati all'argomento PostgreSQL e Kubernetes, vi informiamo anche che la settimana scorsa si è svolto il seguente Postgres-Martedì, durante il quale Nicola ha parlato con Alexander Kukushkin di Zalando. Il video è disponibile qui.

P.P.S.

Leggi anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster