Torna al blog Migration Architecture

Dove dovrebbe archiviare i file un’applicazione self-hosted? Un quadro decisionale per volumi persistenti e object storage

Un backup del database spesso non è sufficiente per ripristinare un’applicazione self-hosted. Usa questo quadro per censire upload, allegati, esportazioni, contenuti multimediali e dati temporanei, quindi scegli volumi persistenti, object storage o un’altra architettura di archiviazione supportata tenendo presenti ripristino e migrazione.

Diagramma che mostra un’applicazione self-hosted, database, volume persistente, object storage e flusso di backup

L’archiviazione dei file è una decisione architetturale

Un’applicazione self-hosted memorizza comunemente il proprio stato durevole in più di un luogo. Il database può contenere record, autorizzazioni e metadati, mentre file quali upload, documenti, immagini e report generati risiedono su disco o in un object store. Ripristinare soltanto il database può quindi generare record che puntano a file che non esistono più.

Nelle distribuzioni Docker, i dati scritti esclusivamente nel layer scrivibile di un container scompaiono quando tale container viene eliminato. I file durevoli dell’applicazione devono essere collocati in una posizione esplicitamente persistente supportata dall’applicazione. La scelta corretta non è automaticamente l’object storage: è il modello di archiviazione che corrisponde al modello di accesso ai file dell’applicazione, ai requisiti di ripristino e alla capacità operativa del team.

  • Considera ogni posizione dei file come parte del modello dati dell’applicazione.
  • Progetta backup e ripristini considerando insieme il database e i file a cui fa riferimento.
  • Documenta la posizione di archiviazione prevista invece di fare affidamento su un’immagine container o su un percorso host non documentato.
L’archiviazione dei file è una decisione architetturale

Inizia con un inventario dei file

Prima di scegliere lo storage, identifica ogni categoria di dati che l’applicazione crea o utilizza. Leggi la documentazione ufficiale dell’applicazione su distribuzione e backup, esamina i percorsi e le impostazioni configurati, ed esegui un upload o un’esportazione di prova in un ambiente non di produzione. L’obiettivo è capire cosa è autorevole, cosa può essere rigenerato e cosa deve essere conservato.

Non presumere che una directory chiamata uploads sia l’unica risposta. Un’applicazione può conservare file originali, miniature, allegati privati, risorse di plugin, indici di ricerca, payload di processi in coda o archivi di esportazione in posizioni diverse.

  • Upload e allegati degli utenti: originali forniti da utenti o personale.
  • Contenuti multimediali e derivati generati: immagini, anteprime, miniature o documenti trasformati.
  • Esportazioni generate: report, file CSV, fatture o download di archivi.
  • Risorse gestite dall’applicazione: file creati tramite un’interfaccia amministrativa.
  • Cache, sessioni e file di lavoro temporanei: spesso eliminabili, ma confermalo nella documentazione del fornitore.
  • Log e file diagnostici: utili dal punto di vista operativo, ma generalmente gestiti separatamente dal ripristino dell’applicazione.
Inizia con un inventario dei file

Comprendi i tre modelli di archiviazione comuni

I volumi persistenti locali archiviano i file al di fuori del ciclo di vita di un singolo container. I volumi Docker sono gestiti da Docker e restano disponibili quando il container che li utilizza viene rimosso. In Kubernetes, i PersistentVolume hanno analogamente un ciclo di vita indipendente da un singolo Pod. Questo modello è spesso adatto a una singola istanza dell’applicazione il cui software si aspetta un normale accesso al filesystem.

L’object storage memorizza i dati come oggetti in bucket, indirizzati mediante chiavi oggetto. È appropriato solo quando l’applicazione supporta esplicitamente un servizio di object storage o fornisce un’integrazione supportata. Per esempio, Rails Active Storage supporta sia un servizio su disco locale sia servizi di cloud storage, a dimostrazione del fatto che la scelta dello storage è spesso una decisione di configurazione dell’applicazione anziché una sostituzione trasparente dell’infrastruttura.

Un filesystem gestito esternamente può offrire ai carichi di lavoro un accesso a filesystem condiviso. Può essere appropriato quando l’applicazione lo richiede realmente e l’implementazione di storage selezionata supporta il modello di accesso necessario. Aggiunge un ulteriore sistema da gestire, proteggere, sottoporre a backup e testare.

  • Volume persistente: semantica semplice del filesystem per un’architettura supportata a singolo host o singolo nodo.
  • Object storage: accesso agli oggetti gestito dall’applicazione, potenzialmente separato dall’host di calcolo.
  • Filesystem gestito: semantica di filesystem condiviso quando giustificata dai requisiti dell’applicazione.

Usa una matrice decisionale invece di una scelta predefinita

Scegli lo storage per categoria di file, non necessariamente una sola volta per l’intera applicazione. Un carico di lavoro di gestione documentale può richiedere uno storage durevole per gli allegati, mentre la sua directory temporanea per la conversione dovrebbe rimanere non persistente. Un’applicazione di reporting può conservare i documenti di origine ma rigenerare le esportazioni dopo un ripristino.

Un’architettura di storage è difendibile quando offre risposte chiare su durabilità, compatibilità dell’applicazione, ripristino, portabilità, controllo degli accessi e manutenzione ordinaria.

  • Durabilità: cosa accade se il container, l’host o il nodo viene sostituito?
  • Compatibilità: l’applicazione supporta ufficialmente questo backend di storage e la relativa configurazione?
  • Complessità del ripristino: il team può ripristinare file e dati del database a un punto sicuramente compatibile?
  • Portabilità della migrazione: i dati possono essere esportati, copiati e convalidati senza presupposti non documentati?
  • Confini di accesso: quale identità di servizio può leggere, scrivere o eliminare i file?
  • Sovraccarico operativo: chi gestisce credenziali, monitoraggio della capacità, regole di conservazione e test di ripristino?
  • Modello di scalabilità: più di un processo dell’applicazione dovrà scrivere gli stessi file, ed è supportato?

Ripristina database e file come un sistema correlato

La domanda fondamentale è se il database contiene riferimenti ai file oppure se i file sono necessari per interpretare i record del database. Se un record di allegato fa riferimento a un percorso o a una chiave oggetto, lo storage degli allegati e il database devono essere pianificati insieme per il ripristino. Un ripristino che combina un database più recente con file più vecchi, o viceversa, può lasciare allegati mancanti o file privi di riferimenti.

L’ordine esatto e sicuro di ripristino dipende dall’applicazione. Alcuni prodotti offrono una modalità di manutenzione, un comando di backup o una procedura di ripristino documentati; usali quando sono disponibili. Quando l’applicazione non dispone di un meccanismo documentato di coerenza, definisci una breve finestra di manutenzione o un altro metodo controllato per ridurre le scritture mentre vengono eseguiti i backup del database e dei file.

  • Identifica il sistema di registrazione per ogni categoria di file.
  • Registra se il database archivia percorsi, chiavi oggetto, checksum o metadati degli allegati.
  • Definisci un punto di ripristino accettabile sia per il database sia per i file.
  • Verifica ciò che gli utenti dovrebbero vedere dopo il ripristino: upload recenti, allegati meno recenti, autorizzazioni e download.

Quando i volumi persistenti locali sono la scelta giusta

Un volume persistente locale è spesso la scelta più chiara per una piccola distribuzione quando l’applicazione è progettata per lo storage su filesystem locale, viene eseguita come una sola istanza attiva e il team può eseguire backup e ripristino del volume sottostante. Evita di aggiungere un’integrazione di object storage soltanto perché sembra più scalabile.

La semplicità è reale solo se i dettagli operativi sono espliciti. Un volume Docker è gestito dall’host e un nome di volume locale è univoco per il proprio host. Spostare l’applicazione su un altro host richiede un processo intenzionale di trasferimento e verifica dei dati. Docker documenta un metodo per archiviare il contenuto di un volume tramite un container temporaneo e ripristinare tale archivio in un volume, che può supportare un flusso controllato di migrazione o recupero.

  • Monta il volume durevole nel percorso dati documentato dell’applicazione.
  • Non confondere un percorso del filesystem del container con lo storage persistente.
  • Registra nome del volume, destinazione di montaggio, aspettative di proprietà e metodo di backup.
  • Verifica il comportamento dei mount durante la distribuzione: montare un volume non vuoto nasconde i file dell’immagine già esistenti in quella destinazione; un volume vuoto può essere popolato dalla directory dell’immagine, a meno che la copia non sia disabilitata.
  • Mantieni separati i dati temporanei dove possibile; un mount tmpfs è adatto solo a dati destinati a scomparire all’arresto, al riavvio o al riavvio dell’host.

Quando l’object storage è adatto

L’object storage è una valida opzione quando un’applicazione lo supporta nativamente e il carico di lavoro trae vantaggio dal separare gli oggetti file dall’host dell’applicazione. Non dedurre la compatibilità dal fatto che un’applicazione viene eseguita in Docker. Conferma il backend supportato, le credenziali richieste, il layout dei bucket, il comportamento di denominazione degli oggetti, le impostazioni di distribuzione tramite URL e qualsiasi procedura di migrazione nella documentazione dell’applicazione stessa.

L’object storage cambia il modello operativo anziché eliminarlo. Devi comunque decidere chi può accedere al bucket, come viene gestita l’eliminazione accidentale, in che modo le versioni conservate incidono sul ripristino e se le regole del ciclo di vita corrispondono agli obblighi di conservazione dell’organizzazione. In Amazon S3, per esempio, i bucket con versioning e quelli senza versioning hanno comportamenti di eliminazione diversi, e le regole del ciclo di vita possono trasferire o eliminare oggetti.

  • Usa un bucket dedicato o un prefisso chiaramente isolato, quando la progettazione dell’applicazione lo supporta.
  • Concedi all’applicazione solo le autorizzazioni necessarie; mantieni le credenziali di servizio separate dall’amministrazione umana.
  • Documenta come vengono conservati o rimossi originali, derivati e upload abbandonati.
  • Testa il ripristino usando la stessa configurazione del bucket e lo stesso modello di accesso previsti in produzione.
  • Assicurati che una policy del ciclo di vita non possa eliminare dati che l’applicazione o i suoi utenti necessitano ancora.

Non rendere un filesystem di rete condiviso la scelta predefinita

Un filesystem di rete condiviso può sembrare una risposta semplice quando sono coinvolti più container o nodi, ma dovrebbe seguire un requisito dell’applicazione, non precederlo. Più writer introducono questioni di locking, modifiche concorrenti, autorizzazioni e comportamento in caso di guasto che le applicazioni potrebbero non essere progettate per gestire.

Anche le modalità di accesso allo storage di Kubernetes non sostituiscono il coordinamento a livello dell’applicazione. ReadWriteOnce indica il montaggio in lettura-scrittura da parte di un nodo, non necessariamente di un solo Pod. Il supporto ReadWriteMany dipende dal plugin sottostante o dal driver CSI, e le comuni modalità di accesso non applicano di per sé una protezione dalla scrittura dopo il montaggio. Convalida sia il comportamento della piattaforma di storage sia l’architettura multi-istanza documentata dell’applicazione.

  • Usa storage su filesystem condiviso solo quando l’applicazione supporta il modello di accesso richiesto.
  • Conferma se più istanze possono scrivere in sicurezza sugli stessi file.
  • Specifica l’implementazione di storage sottostante, non soltanto un’etichetta della modalità di accesso Kubernetes.
  • Esamina il comportamento di reclaim prima di effettuare il provisioning di storage dinamico; una StorageClass può eliminare lo storage sottostante con una policy di reclaim Delete.

Domande frequenti

Un backup del database è sufficiente per un’applicazione self-hosted?

Solo se l’applicazione conserva tutti i dati recuperabili nel database e nessun file necessario esiste altrove. Molte applicazioni archiviano i metadati degli allegati nel database ma mantengono i file effettivi in un volume o in un object store. Censisci ed esegui il backup di entrambe le parti.

Ogni applicazione self-hosted dovrebbe usare l’object storage?

No. Usa l’object storage quando l’applicazione lo supporta esplicitamente e quando il suo modello di ripristino, accesso e operatività corrisponde alle tue esigenze. Un volume locale persistente può essere l’architettura più semplice e appropriata per un’applicazione supportata a istanza singola.

I volumi Docker vengono sottoposti a backup automaticamente?

Un volume Docker persiste separatamente da un container, ma la persistenza non equivale a un backup. Hai bisogno di un metodo di backup documentato, di una policy di conservazione e di una procedura di ripristino testata per il contenuto del volume.

Più container possono condividere un volume locale Docker?

Non darlo per scontato basandoti soltanto su una configurazione Compose. Docker documenta che i servizi che utilizzano il driver di volume locale non condividono automaticamente i dati con i container di altri servizi. Progetta esplicitamente l’accesso condiviso e verifica i requisiti dell’applicazione.

Cosa dovrebbe includere un test di ripristino?

Ripristina il database e lo storage dei file usando la procedura prevista, quindi verifica l’accesso utente, ove pertinente, gli allegati recenti e meno recenti, i download, le autorizzazioni, i contenuti generati e la capacità dell’applicazione di creare un nuovo file dopo il recupero.

L’hosting gestito delle applicazioni elimina la responsabilità per lo storage dei file?

No. La distribuzione gestita può ridurre il lavoro infrastrutturale, ma il cliente deve comunque comprendere quali dati aziendali esistono, chi può accedervi, quale conservazione è appropriata e se l’architettura di recupero dell’applicazione soddisfa le sue esigenze. Airbip distribuisce le applicazioni del catalogo come carichi di lavoro Docker su server cloud e offre backup giornalieri, settimanali e mensili configurabili; conferma l’ambito di storage e recupero per l’applicazione specifica prima di fare affidamento su un piano di backup.

Fonti e approfondimenti

  1. Docker volumes — Docker
  2. Docker storage — Docker
  3. Persistent Volumes — Kubernetes
  4. Storage Classes — Kubernetes
  5. Amazon S3 objects overview — Amazon Web Services
  6. What is Amazon S3? — Amazon Web Services
  7. Deleting Amazon S3 objects — Amazon Web Services
  8. Managing the lifecycle of objects — Amazon Web Services
  9. Access control in Amazon S3 — Amazon Web Services
  10. Active Storage Overview — Ruby on Rails