Storicamente, l'industria IT si è divisa in due campi condizionati: quelli "a favore" e quelli "contro". E la questione può riguardare qualsiasi argomento. Qual è il miglior sistema operativo: Win o Linux? Smartphone Android o iOS? Conservare tutto nel cloud o caricare su freddi sistemi RAID e mettere i dischi in cassaforte? Gli sviluppatori PHP possono definirsi programmatori? Questi dibattiti sono, a volte, esclusivamente di natura esistenziale e non hanno alcuna base valida, se non un interesse puramente sportivo.
È successo che con l'arrivo dei container e di tutta questa nostra amata tecnologia con Docker e il noto k8s, sono iniziati anche i dibattiti "a favore" e "contro" l'uso delle nuove possibilità in vari ambiti del back-end. (Per chiarezza, va detto che anche se nella discussione il termine orchestratore solitamente designa Kubernetes, la scelta di questo strumento in particolare non ha importanza fondamentale. Al suo posto si può utilizzare qualsiasi altro strumento che riteniate più comodo e familiare.)
E, a prima vista, potrebbe sembrare un semplice dibattito tra due lati della stessa medaglia. Una contrapposizione altrettanto insensata e spietata come il conflitto eterno tra Win e Linux, dove persone ragionevoli possono trovarsi a metà strada. Tuttavia, nel caso della containerizzazione, le cose non sono così semplici. Di solito, in tali dispute non esiste un lato giusto, ma nel caso di "utilizzare" o "non utilizzare" i container per l'archiviazione dei database, la situazione si capovolge. Perché, in un certo senso, sia i sostenitori che gli oppositori di tale approccio hanno ragione.
Lato Chiaro
Riassumere l'argomentazione del Lato Chiaro in una frase è semplice: “Ciao, è il 2k19 fuori!” Suona un po' come populismo, indubbiamente, ma se si approfondisce la situazione, ci sono dei vantaggi. Ed è di questi che parleremo ora.
Supponiamo che tu abbia un grande progetto web. Potrebbe essere stato inizialmente costruito sulla base di un approccio a microservizi, oppure potrebbe essere arrivato a questo punto in modo evolutivo — in realtà non è molto importante. Hai suddiviso il nostro progetto in singoli microservizi, hai configurato l'orchestrazione, il bilanciamento del carico e la scalabilità. E ora, con la coscienza tranquilla, ti godi un mojito nell'amaca durante gli effetti di Habr invece di sollevare i server caduti. Ma in tutte le azioni bisogna essere coerenti. Molto spesso si containerizza solo direttamente l'applicazione stessa — il codice. E cos'altro abbiamo oltre al codice?
Esatto, i dati. Il cuore di qualsiasi progetto sono i suoi dati: possono essere un tipico DBMS come MySQL, Postgre, MongoDB, così come archivi utilizzati per la ricerca (ElasticSearch), archivi key-value per la memorizzazione nella cache — ad esempio, Redis, ecc. Oggi non parleremo delle implementazioni problematiche del backend, quando il DB cade a causa di query mal scritte, ma invece parleremo di garantire la resilienza di questo stesso DB sotto il carico dei client. Infatti, quando containerizziamo la nostra applicazione e le permettiamo di scalare liberamente per elaborare qualsiasi numero di richieste in ingresso, questo aumenta inevitabilmente il carico sul database.
In effetti, il canale di accesso al database e il server su cui è in esecuzione diventano un collo di bottiglia nel nostro fantastico backend containerizzato. In questo modo, il principale obiettivo della virtualizzazione a contenitori è la mobilità e la flessibilità della struttura, che permette di organizzare la distribuzione del carico picco al meglio possibile su tutta l'infrastruttura disponibile. Cioè, se non containerizziamo e non distribuiamo nel cluster tutti gli elementi del sistema — commettiamo un errore molto grave.
È molto più logico clusterizzare non solo l'applicazione stessa, ma anche i servizi responsabili della memorizzazione dei dati. Quando si clusterizzano e si distribuiscono server web che operano in modo indipendente e si distribuiscono il carico tra di loro in k8s, risolviamo già il problema della sincronizzazione dei dati — come i commenti ai post, per esempio, se prendiamo in considerazione un media o una piattaforma di blog. In ogni caso, abbiamo una rappresentazione interna del cluster, anche se virtuale, del database come ExternalService. Il problema è che il database stesso non è ancora clusterizzato — i server web distribuiti nel cluster prelevano informazioni sulle modifiche dalla nostra base dati statica in produzione, che gira separatamente.
Senti un tranello? Utilizziamo k8s o Swarm per distribuire il carico ed evitare il fallimento del principale web, ma non facciamo lo stesso per il database. Se il database crolla, non ha senso per tutta la nostra infrastruttura clusterizzata — a cosa ci servono pagine web vuote che restituiscono un errore di accesso al database?
È proprio per questo che bisogna clusterizzare non solo i server web, come di solito si fa, ma anche l'infrastruttura del database. Solo in questo modo possiamo garantire una struttura che funzioni in modo autonomo ma che sia pur sempre interconnessa. Anche se metà del nostro backend dovesse 'crollare' sotto carico, l'altra metà sopravviverebbe, e il sistema di sincronizzazione del database all'interno del cluster e la possibilità di scalabilità infinita e di distribuzione di nuovi cluster aiuterà a raggiungere rapidamente la potenza necessaria — purché ci siano rack nel data center.
Inoltre, il modello di database distribuito nei cluster consente di portare il database stesso dove è necessario; se parliamo di un servizio globale, è piuttosto illogico avere un cluster web da qualche parte vicino a San Francisco e inviare pacchetti per accedere al database a Podmoskov'e e ritorno.
Inoltre, la containerizzazione del database consente di costruire tutti gli elementi del sistema su un unico livello di astrazione. Ciò, a sua volta, rende possibile gestire il sistema direttamente dal codice, dagli sviluppatori, senza il coinvolgimento attivo degli amministratori. Gli sviluppatori hanno pensato che fosse necessaria una nuova base di dati per un nuovo sottoprogetto — facile! Hanno scritto un file yaml, lo hanno caricato nel cluster ed è pronto.
E, naturalmente, l'utilizzo interno diventa notevolmente più semplice. Dite, quante volte avete chiuso gli occhi nei momenti in cui un nuovo membro del team si è intromesso nel database di produzione? Che in effetti è l'unico che avete e che sta girando proprio adesso? Certo, siamo tutti adulti qui, e da qualche parte avremo un backup fresco, e ancora più in là, dietro uno scaffale di cetrioli della nonna e vecchi sci, un altro backup, forse anche su un'archiviazione a freddo, perché un giorno il vostro ufficio ha già preso fuoco. Ma comunque, ogni introduzione di un nuovo membro del team che ha accesso all'infrastruttura di produzione e, naturalmente, al database di produzione è un calice di valium per tutti intorno. Chi può sapere, il novellino, forse è maldestro? Fa paura, ammettetelo.
La containerizzazione e, in sostanza, la topologia fisica distribuita del database del vostro progetto aiutano a evitare momenti del genere. Non vi fidate del nuovo arrivato? Va bene! Gli creeremo un cluster personale per lavorare e lo disconnetteremo dagli altri cluster del database: la sincronizzazione avverrà solo tramite push manuale e la rotazione sincrona di due chiavi (una per il team leader, l'altra per l'amministratore). E tutti saranno felici.
E ora è tempo di passare a quelli che si oppongono alla clusterizzazione del database.
Lato Oscuro
Ragionando su perché non dovremmo containerizzare il database e continuare a farlo girare su un'unica centrale server, non scenderemo a retoriche ortodosse e affermazioni del tipo «i nonni facevano girare i database sull'hardware, e noi lo faremo!» Invece, proviamo a immaginare una situazione in cui la containerizzazione porterebbe davvero benefici tangibili.
Ammettetelo, i progetti che hanno davvero bisogno di un database in container si possono contare sulle dita di una mano di un fresatore non proprio sopraffino. Nella maggior parte dei casi, persino l'uso di k8s o Docker Swarm è eccessivo: molto spesso si ricorre a questi strumenti a causa dell'hype generale delle tecnologie e delle imposizioni «divine» da parte dei capi di spingere tutto verso il cloud e i container. Beh, perché ora è di moda e tutti così fanno.
In almeno la metà dei casi, l'uso di Kubernetes o semplicemente di Docker nel progetto è eccessivo. Il problema è che non tutti i team o le aziende esterne assunte per gestire l'infrastruttura del cliente se ne rendono conto. Ancora peggio è quando i container sono imposti, perché questo comporta un certo costo monetario per il cliente.
In generale, c'è un'opinione secondo cui la mafia di Docker/Kubernetes sta semplicemente controllando i clienti che delegano queste questioni infrastrutturali a terzi. Infatti, per lavorare con i cluster, sono necessari ingegneri capaci e che comprendano l'architettura della soluzione implementata. Abbiamo già descritto il nostro caso con la pubblicazione di Republic — lì abbiamo addestrato il team del cliente a lavorare con Kubernetes, e tutti sono stati soddisfatti. Ed è stata una cosa ragionevole. Spesso, però, gli 'implementatori' di k8s prendono in ostaggio l'infrastruttura del cliente — perché ora solo loro sanno come funziona tutto, non ci sono specialisti dalla parte del cliente.
E ora immaginate che in questo modo non stiamo delegando solo la parte del server web a terzi, ma anche la gestione del database. Abbiamo detto che il database è il cuore, e la perdita del cuore è fatale per qualsiasi organismo vivente. Insomma, le prospettive non sono delle migliori. Quindi, invece di affidarci a Kubernetes da un lato di moda, molti progetti dovrebbero semplicemente non essere avari su una tariffa normale di AWS, che risolverebbe tutti i problemi di carico sul loro sito/progetto. Ma AWS non è più di moda, e i bling costano più dei soldi — purtroppo, anche nel settore IT.
Ok. Forse la clusterizzazione è veramente necessaria per il progetto, ma se con le applicazioni stateless è tutto chiaro, come possiamo allora organizzare una connessione di rete adeguata per un database clusterizzato?
Se parliamo di una soluzione ingegneristica senza interruzioni, che è ciò che implica la transizione a k8s, il nostro principale mal di testa è la replica dei dati in un database clusterizzato. Alcuni DBMS tendono ad essere piuttosto indulgenti nella distribuzione dei dati tra le loro istanze. Molti altri, invece, non sono altrettanto accoglienti. E abbastanza spesso, l'argomento principale nella scelta del DBMS per il nostro progetto non è affatto la capacità di replicarsi con costi minimi in termini di risorse e ingegneria. Soprattutto se il progetto non era inizialmente previsto come un servizio micro, ma è semplicemente evoluto in quella direzione.
Pensiamo che non sia necessario spiegare la velocità dei dischi di rete: sono lenti. Cioè, non abbiamo davvero la possibilità, in caso di necessità, di riavviare un'istanza del DBMS da qualche parte, dove ci sono più, ad esempio, potenza di calcolo o memoria RAM libera. Ci impegneremo molto rapidamente nelle prestazioni del sistema di storage virtualizzato. Di conseguenza, il DBMS deve essere collegato al proprio set personale di macchine che si trovano in prossimità. Oppure dobbiamo in qualche modo predisporre una sincronizzazione dei dati sufficientemente rapida per risorse previste.
Continuando il tema dei file system virtuali: i Docker Volumes, sfortunatamente, non sono privi di problemi. In generale, in un campo come la conservazione a lungo termine dei dati, vorremmo utilizzare schemi tecnici il più semplici possibile. L'aggiunta di un nuovo strato di astrazione da un file system del contenitore a quello dell'host padre è già di per sé un rischio. Ma quando ci sono anche delle difficoltà nel lavoro del sistema di containerizzazione nella trasmissione dei dati tra questi strati, allora è davvero un disastro. Al momento, la maggior parte dei noti problemi affrontati dall'umanità sembra essere stata estirpata. Ma come sapete, più complesso è il meccanismo, più è facile che si rompa.
Alla luce di tutte queste «avventure», è molto più vantaggioso e semplice tenere un DB in un unico posto, e anche se hai bisogno di containerizzare l'applicazione — lascia che funzioni da sola e attraverso un gateway distribuito ottenga una connessione simultanea al DB, che sarà letta e scritta solo una volta e in un unico posto. Questo approccio riduce la probabilità di errori e desincronizzazioni ai minimi termini.
Dove vogliamo arrivare? Al fatto che la containerizzazione del DB è opportuna dove c'è una reale necessità. Non si può infilare un database di un'app completa e farlo girare come se avessi due dozzine di microservizi — non funziona in questo modo. E questo va chiaramente compreso.
Invece di un'uscita
Se stai aspettando una risposta chiara sul «virtualizzare o meno il DB», purtroppo siamo costretti a deluderti: qui non ci sarà. Perché nella creazione di qualsiasi soluzione infrastrutturale bisogna guidarsi non dalla moda e dal progresso, ma prima di tutto dal buon senso.
Ci sono progetti sui quali i principi e gli strumenti che vengono con Kubernetes si adattano perfettamente, e in tali progetti si raggiunge la pace almeno nell'area del backend. Ci sono però progetti che hanno bisogno non di containerizzazione, ma di una normale infrastruttura server, perché non possono fondamentalmente essere ridimensionati a un modello di cluster microservizi, altrimenti semplicemente crollano.
Fonte: habr.com
