Pattern di archiviazione dei dati in Kubernetes

Pattern di archiviazione dei dati in Kubernetes
Ciao, Habr!

Ricordiamo che è uscito un altro articolo estremamente interessante e utile libro sui pattern di Kubernetes. È tutto iniziato con "Pattern" di Brendan Burns, e, in effetti, il lavoro in questo segmento è in pieno svolgimento. Oggi vi proponiamo di leggere un articolo del blog MinIO, che riassume le tendenze e le specificità dei pattern di archiviazione dei dati in Kubernetes.

Kubernetes ha cambiato radicalmente i tradizionali pattern di sviluppo e distribuzione delle applicazioni. Ora un team può impiegare solo pochi giorni per sviluppare, testare e distribuire un'applicazione – in diversi ambienti, il tutto all'interno di cluster Kubernetes. Un lavoro simile con le tecnologie delle generazioni precedenti richiedeva solitamente settimane, se non mesi.

Tale accelerazione è stata possibile grazie all'astrazione fornita da Kubernetes, cioè al fatto che Kubernetes gestisce da solo le interazioni con i dettagli a basso livello delle macchine fisiche o virtuali, permettendo agli utenti di dichiarare tra le altre variabili la CPU necessaria, la quantità di memoria e il numero di istanze di contenitori. Poiché un enorme community si occupa del supporto di Kubernetes e gli ambiti di applicazione continuano ad espandersi, esso guida di gran lunga tutte le piattaforme di orchestrazione dei contenitori.

Con l'aumentare dell'uso di Kubernetes, cresce anche la confusione riguardo ai pattern di archiviazione dei dati utilizzati..

Nella generale concorrenza per una fetta della torta di Kubernetes (cioè, per lo storage dei dati), quando si discute di archiviazione dei dati, il segnale qui è inghiottito da un forte rumore.
Kubernetes incarna il modello moderno di sviluppo e distribuzione delle applicazioni, così come la loro gestione. Questo modello moderno scollega l'archiviazione dei dati dai calcoli. Per comprendere appieno tale scollegamento nel contesto di Kubernetes, è necessario anche capire cosa siano le applicazioni con stato e senza stato, e come si integri l'archiviazione dei dati. È proprio qui che l'approccio REST API, utilizzato da S3, ha chiari vantaggi rispetto all'approccio POSIX/CSI, caratteristico di altre soluzioni.

In questo articolo parleremo dei modelli di archiviazione dei dati in Kubernetes e affronteremo separatamente la questione delle applicazioni che operano con e senza stato, per comprendere appieno qual è la differenza tra di esse e perché sia importante. In seguito, verranno esaminate le applicazioni e i modelli di archiviazione dei dati utilizzati in esse alla luce delle migliori pratiche per lavorare con i contenitori e Kubernetes.

Contenitori senza stato

I contenitori sono, per loro natura, leggeri ed efimeri. Possono essere facilmente fermati, eliminati o distribuiti su un altro nodo - il tutto richiede solo pochi secondi. In un grande sistema di orchestrazione dei contenitori, queste operazioni avvengono continuamente, e gli utenti non notano nemmeno tali cambiamenti. Tuttavia, i trasferimenti sono possibili solo se il contenitore non ha alcuna dipendenza dal nodo su cui si trova. Di tali contenitori si dice che funzionano senza stato.

Contenitori con stato

Se un contenitore conserva dati su dispositivi collegati localmente (o su uno storage a blocchi), il volume di archiviazione su cui si trova dovrà essere trasferito su un nuovo nodo insieme al contenitore stesso - in caso di guasto. Questo è importante, poiché altrimenti l'applicazione in esecuzione nel contenitore non potrà funzionare correttamente, poiché deve accedere ai dati memorizzati sui supporti locali. Di tali contenitori si dice che funzionano con stato.

Da un punto di vista puramente tecnico, anche i contenitori con stato possono essere spostati su altri nodi. Di solito, ciò è garantito attraverso l'uso di file system distribuiti o di archiviazioni di dati a blocchi in rete, attaccate a tutti i nodi su cui funzionano i contenitori. In questo modo, i contenitori ottengono accesso ai volumi per l'archiviazione persistente dei dati, e le informazioni vengono memorizzate su dischi situati in tutta la rete. Questo metodo lo chiamerò "approccio del contenitore con stato" e nel resto dell'articolo mi riferirò a esso in questo modo per coerenza.

Pattern di archiviazione dei dati in Kubernetes

Con un approccio tipico ai contenitori con stato, tutti i pod delle applicazioni sono collegati a un unico sistema di file distribuiti: si crea un tipo di archiviazione condivisa, dove si trovano tutti i dati delle applicazioni. Pur essendo possibili alcune variazioni, questo è un approccio ad alto livello.

Ora vediamo perché l'approccio ai contenitori con stato nel mondo orientato al cloud è considerato un antipattern.

Progettazione di applicazioni orientate al cloud

Tradizionalmente, le applicazioni utilizzavano database per la memorizzazione strutturata delle informazioni e dischi locali o sistemi di file distribuiti, dove venivano scaricati tutti i dati non strutturati o semi-strutturati. Con l'aumento dei volumi di dati non strutturati, gli sviluppatori si resero conto che POSIX era troppo 'chiacchierone', comportava costi significativi e, alla fine, ostacolava il funzionamento dell'applicazione quando si passava a scale veramente grandi.

Questo ha principalmente contribuito alla nascita di un nuovo standard di archiviazione dei dati, ovvero i sistemi di archiviazione orientati al cloud, che operano principalmente basati su REST API e liberano l'applicazione dal gravoso compito della gestione di archiviazioni locali. In questo caso, l'applicazione passa effettivamente a una modalità di funzionamento senza stato (poiché lo stato è in un'archiviazione remota). Le applicazioni moderne vengono costruite fin dall'inizio tenendo conto di questo fattore. Di solito, qualsiasi applicazione moderna che gestisce dati di vario tipo (log, metadati, blob, ecc.) è costruita secondo la paradigamma orientata al cloud, dove lo stato viene trasferito a un sistema software dedicato per la sua archiviazione.

L'approccio ai contenitori con stato costringe l'intera paradigamma a tornare esattamente all'origine da cui era partita!

Utilizzando le interfacce POSIX per l'archiviazione dei dati, le applicazioni funzionano come se stessero conservando lo stato, e per questo si allontanano dai postulati più importanti del design orientato al cloud, ovvero la possibilità di variare le dimensioni dei flussi di lavoro dell'applicazione in base al carico in ingresso, spostarsi su un nuovo nodo non appena quello attuale fallisce, e così via.

Osservando questa situazione più da vicino, scopriamo che nella scelta dello storage dei dati ci troviamo di nuovo di fronte al dilemma 'POSIX contro REST API', MA con un'ulteriore aggravante riguardo ai problemi di POSIX, dovuta alla natura distribuita degli ambienti Kubernetes. In particolare,

  • POSIX è prolisso: la semantica di POSIX richiede di associare a ogni operazione metadati e descrittori di file, che aiutano a mantenere lo stato dell'operazione. Questo porta a costi significativi, privi di reale valore. L'API per l'archiviazione degli oggetti, in particolare l'API S3, ha eliminato questi requisiti, permettendo all'applicazione di eseguire l'operazione e poi 'dimenticarsi' della chiamata. La risposta del sistema di storage indica se l'operazione è stata eseguita con successo o meno. In caso di fallimento, l'applicazione può tentare nuovamente.
  • Limitazioni di rete: in un sistema distribuito si presuppone che possano esistere più applicazioni che cercano di scrivere dati su un unico supporto di memorizzazione attaccato. Pertanto, non solo le applicazioni competiranno tra loro per la larghezza di banda (per inviare dati sul supporto), ma anche il sistema di storage stesso concorrerà per questa larghezza di banda, distribuendo i dati su dischi fisici. A causa della verbosità di POSIX, il numero di chiamate di rete aumenta notevolmente. D'altra parte, l'API S3 fornisce una chiara separazione tra le chiamate di rete che arrivano dal client al server e quelle che avvengono all'interno del server.
  • Sicurezza: Il modello di sicurezza POSIX richiede un attivo coinvolgimento umano: gli amministratori configurano specifici livelli di accesso per ogni utente o gruppo. Questa paradosso è difficile da adattare a un mondo orientato al cloud. Le applicazioni moderne dipendono da modelli di sicurezza legati alle API, dove i diritti di accesso sono definiti come un insieme di politiche, account di servizio, credenziali temporanee, ecc.
  • Gestibilità: I container con stato comportano determinati costi associati alla gestione. Si tratta della sincronizzazione dell'accesso parallelo ai dati, della garanzia di coerenza dei dati, tutto ciò richiede di valutare attentamente quali modelli di accesso ai dati utilizzare. È necessario installare, controllare e configurare programmi aggiuntivi, senza contare gli sforzi aggiuntivi necessari per lo sviluppo.

Interfaccia di storage dei container

Mentre l'interfaccia di storage dei container (CSI) ha aiutato notevolmente a diffondere il livello dei volumi Kubernetes, trasferendolo parzialmente a fornitori terzi di storage, ha anche contribuito accidentalmente alla convinzione che l'approccio dei container con stato sia il metodo raccomandato per la memorizzazione dei dati in Kubernetes.

Il CSI è stato progettato come uno standard per fornire sistemi di storage a blocchi e file arbitrari alle applicazioni legacy utilizzando Kubernetes. Come dimostrato in questo articolo, l'unica situazione in cui l'approccio dei container con stato (e il CSI nella sua forma attuale) è ragionevole è quando l'applicazione stessa è un sistema legacy, in cui non è possibile aggiungere il supporto per le API dell'oggetto di storage dei dati.

È importante comprendere che, utilizzando il CSI nella sua forma attuale, cioè montando i volumi mentre si utilizza applicazioni moderne, ci si imbatterà in problemi simili a quelli riscontrati nei sistemi in cui il storage dei dati è organizzato nello stile POSIX.

Un approccio di maggiore qualità

In questo caso, è importante capire che la maggior parte delle applicazioni in realtà non è progettata per lavorare con la persistenza dello stato o senza. Questo comportamento dipende dall'architettura generale del sistema e dalle scelte specifiche fatte durante la progettazione. Parliamo un po' delle applicazioni che mantengono lo stato.

In linea di principio, tutti i dati delle applicazioni possono essere suddivisi in diversi ampi tipi:

  • Dati di log
  • Dati di timestamp
  • Dati di transazioni
  • Metadati
  • Immagini dei container
  • Dati blob (oggetti binari di grandi dimensioni)

Tutti questi tipi di dati sono ben supportati dalle piattaforme moderne di archiviazione dati, e ci sono diverse piattaforme orientate al cloud adattate per fornire dati in ciascuno di questi specifici formati. Ad esempio, i dati di transazioni e i metadati possono essere conservati in un database moderno orientato al cloud, come CockroachDB, YugaByte, ecc. Le immagini dei container o i dati blob possono essere archiviate in un registro docker basato su MinIO. I dati di timestamp possono essere conservati in un database di serie temporali, ad esempio, InfluxDB, ecc. Non entreremo nei dettagli di ciascun tipo di dato e delle relative applicazioni, ma l'idea generale è di evitare la persistenza dello stato basata su mount locali.

Pattern di archiviazione dei dati in Kubernetes

Inoltre, spesso risulta efficace fornire un livello di caching temporaneo, che funge per le applicazioni da una sorta di archiviazione di file temporanei, ma le applicazioni non dovrebbero fare affidamento su questo livello come sorgente di verità.

Archiviazione per applicazioni con stato

Mentre nella maggior parte dei casi è utile mantenere le applicazioni senza stato, quelle progettate per conservare dati – come database, archivi di oggetti, archivi a chiave-valore – devono mantenere lo stato. Vediamo perché queste applicazioni vengono implementate su Kubernetes. Prendiamo MinIO come esempio, ma principi simili si applicano a qualsiasi altro grande sistema di archiviazione dati orientato al cloud.

Le applicazioni orientate al cloud sono progettate per sfruttare al massimo la flessibilità intrinseca dei contenitori. Ciò significa che non vengono fatte assunzioni riguardo all'ambiente in cui saranno distribuite. Ad esempio, MinIO utilizza un meccanismo interno di codifica per ridondanza (erasure coding) che fornisce al sistema una robustezza sufficiente per rimanere operativo anche in caso di guasto della metà dei dischi. Inoltre, MinIO gestisce l'integrità e la sicurezza dei dati utilizzando un proprio sistema di hashing e crittografia lato server.

Per queste applicazioni orientate al cloud, i volumi persistenti locali (PV) sono la soluzione più comoda per l'archiviazione di backup. Un PV locale consente di memorizzare dati grezzi, mentre le applicazioni che operano sopra questi PV raccolgono autonomamente informazioni che consentono di scalare i dati e gestire le crescenti esigenze di archiviazione.

Questo approccio è molto più semplice e si scalda significativamente meglio rispetto ai PV basati su CSI, i quali introducono nei sistemi i propri livelli di gestione dei dati e ridondanza; il problema è che questi livelli generalmente entrano in conflitto con le applicazioni progettate secondo il principio del salvataggio dello stato.

Una transizione sicura verso il disaccoppiamento dei dati dai calcoli

In questo articolo abbiamo discusso su come le applicazioni si stanno riorientando per funzionare senza mantenere lo stato, in altre parole, l'archiviazione dei dati è separata dai calcoli effettuati su di essi. Concludendo, esamineremo alcuni esempi reali di questa tendenza.

Spark, la famosa piattaforma per l'analisi dei dati, è tradizionalmente utilizzata con una gestione dello stato e con distribuzione nel file system HDFS. Tuttavia, con il passaggio di Spark a un mondo orientato al cloud, questa piattaforma è sempre più utilizzata senza mantenere lo stato utilizzando `s3a`. Spark utilizza s3a per trasferire lo stato ad altri sistemi, mentre i contenitori stessi di Spark funzionano completamente senza mantenere lo stato. Altri grandi attori enterprise nel campo dell'analisi dei big data, in particolare, Vertica, Teradata, Greenplum stanno anche passando a lavorare con la separazione tra archiviazione dei dati e calcolo sui dati.

Pattern simili possono essere riscontrati anche su altre importanti piattaforme analitiche, tra cui Presto, Tensorflow to R, Jupyter. Esportando lo stato nei sistemi di archiviazione cloud remoti, diventa molto più facile gestire e scalare la tua applicazione. Inoltre, ciò favorisce la portabilità dell'applicazione in diversi ambienti.

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