KINDLE HOME

Come restic custodisce il tempo

Come restic usa chunk content-addressed e deduplicazione per mantenere snapshot indipendenti con crescita quasi piatta dello storage.

C'è un momento, quando si gestisce infrastruttura da abbastanza tempo, in cui si smette di credere ai backup. Non perché siano inutili — anzi, si sa bene che sono l'unica cosa che conta quando tutto va storto — ma perché si è visto abbastanza volte il backup che "c'era" e poi non c'era, o c'era ma non si poteva restaurare, o si poteva restaurare ma richiedeva una sequenza di operazioni che nessuno ricordava più. La fiducia si erode lentamente, attraverso incidenti piccoli, e alla fine si finisce per avere un sistema di backup che gira di notte e a cui non si pensa più, sperando che non serva mai davvero.

Restic rompe questo schema, ma non perché sia "più affidabile" in senso generico. Lo rompe perché ha un modello mentale diverso — e una volta capito quel modello, i backup smettono di essere una scatola nera e diventano qualcosa che si può ragionare.

Il problema con i backup tradizionali

Il backup tradizionale funziona in due varianti. La prima è il backup completo: ogni notte si copia tutto, ogni volta. Semplice da capire, semplice da restaurare, ma costoso in spazio e in tempo. Se l'app pesa 5GB, dopo un mese hai 150GB occupati su storage, quasi tutti copie identiche degli stessi file. La crescita è lineare e inesorabile.

La seconda variante è il backup incrementale classico: si fa un backup completo una volta (chiamiamolo "base") e poi ogni giorno si salva solo quello che è cambiato rispetto al giorno prima. Lo spazio occupato crolla, ma appare un problema nuovo: per restaurare il giorno 10, devi ricostruire la catena — base, poi delta 1, poi delta 2, poi delta 3, fino al delta 10. Se uno dei pezzi nel mezzo è corrotto o mancante, la catena si spezza e il restore diventa impossibile o parziale. I backup incrementali tradizionali sono fragili esattamente nel punto in cui non dovrebbero esserlo: quando servono davvero.

C'è anche un problema più sottile. Con i delta, ogni snapshot dipende da tutti quelli precedenti. Non puoi eliminare il backup di 15 giorni fa senza spezzare la catena che porta a quelli successivi. La gestione della retention diventa complicata: devi capire quali backup puoi eliminare senza rompere nulla, e di solito lo strumento non te lo dice in modo trasparente.

Chunk, hash, e il content-addressed storage

Restic fa una cosa diversa, concettualmente più semplice anche se tecnicamente più sofisticata. Invece di salvare file interi o diff tra file, taglia ogni file in blocchi — i "chunk" — di circa un megabyte ciascuno. Il taglio non è posizionale (non "dal byte 0 al byte 1048576") ma content-defined: l'algoritmo di chunking trova le divisioni naturali nel contenuto, in modo che se inserisci una riga in cima a un file, i chunk della parte successiva rimangano identici. È come se il file venisse diviso nei punti "giusti" indipendentemente da dove si trovano nel file system.

Ogni chunk viene poi identificato con il suo hash SHA-256. Questo hash è la chiave di storage: restic non salva "il file", salva i chunk che compongono il file, e li indirizza per hash. Se lo stesso blocco di dati appare in dieci file diversi, o in dieci versioni diverse dello stesso file, viene salvato una volta sola su storage. Questo si chiama content-addressed storage, ed è la stessa idea che sta alla base di git, di IPFS, di decine di sistemi distribuiti moderni.

Uno snapshot, in restic, è solo un file di metadati: una struttura ad albero che dice "questo file era composto da questi hash, questa directory conteneva questi file". Non contiene dati reali — solo riferimenti. I dati veri sono i chunk, e i chunk sono immutabili e condivisi tra tutti gli snapshot che li referenziano.

Perché ogni snapshot è indipendente

La conseguenza di questo design è che ogni snapshot è completamente autonomo. Per restaurare lo snapshot di 10 giorni fa, restic legge il suo manifest, ricava la lista di chunk che gli servono, e li scarica da storage. Non deve sapere nulla dello snapshot di 9 giorni fa, né dell'ordine in cui i backup sono stati creati. La catena non esiste.

Questo risolve entrambi i problemi dei backup tradizionali. Lo spazio non cresce linearmente perché i chunk vengono deduplicate: un database da 50MB che cambia leggermente ogni giorno non occupa 50MB × 30 = 1.5GB al mese, ma 50MB + i pochi megabyte di chunk effettivamente nuovi ogni giorno. Sui sistemi reali, la crescita dopo il primo backup è spesso nell'ordine del 5-10% al mese rispetto alla dimensione iniziale, non del 100%.

E ogni snapshot è restaurabile in modo indipendente. Puoi eliminare qualsiasi snapshot intermedio senza toccare gli altri, perché ogni snapshot porta con sé tutto quello che gli serve. Restic gestisce questo automaticamente con il comando "forget": puoi dirgli "tieni solo gli ultimi 7 giornalieri, 4 settimanali e 3 mensili", e lui elimina i snapshot che non rientrano nella policy senza mai toccare i chunk che sono ancora referenziati da altri snapshot.

Un esempio concreto

Sui sistemi che gestiamo con questo approccio — 53 applicazioni, backup giornalieri su OVH S3 — i numeri rendono l'idea. Rankpilot, un'applicazione Laravel con il suo database, dopo 22 snapshot giornalieri occupa 420MB effettivi su storage. Non 420MB × 22. Solo 420MB in totale. Per un'applicazione delle sue dimensioni, questo significa che la deduplicazione sta assorbendo circa il 95% dello spazio che sarebbe stato necessario con backup completi tradizionali.

Budget, un'applicazione quasi statica, è ancora più estremo: 23 snapshot, 245 kilobyte effettivi. L'app non cambia quasi mai, quindi ogni backup è quasi interamente composto da chunk già presenti nel repository. Lo snapshot viene creato, il manifest viene salvato, e i dati già esistono da prima. Il costo marginale di ogni backup è praticamente zero.

Il parallelo con git

Se si lavora con git da abbastanza tempo, tutto questo suona familiare. Git usa esattamente lo stesso principio: ogni commit non è un diff rispetto al commit precedente, ma un snapshot completo dell'albero del repository, implementato come un DAG di oggetti content-addressed. I blob (contenuti dei file) sono condivisi tra commit se il file non è cambiato. Puoi fare checkout di qualsiasi commit senza "riprodurre" la storia.

Restic fa per i backup quello che git fa per il codice. La differenza è che git lo fa per file di testo in repository espliciti, mentre restic lo fa per qualsiasi dato su qualsiasi storage remoto, con crittografia end-to-end integrata e gestione della retention automatica.

Capire restic attraverso git è il modo più veloce per togliersi la sensazione di magia. Non c'è magia. C'è content-addressing, deduplicazione, e snapshot come manifest. Il risultato è che puoi avere 30 punti di ripristino indipendenti in circa la stessa quantità di spazio che occuperebbe un backup completo singolo — e ogni punto di ripristino è accessibile direttamente, senza dipendere dagli altri.

Quello che questo cambia operativamente

Una volta interiorizzato il modello, alcune decisioni operative diventano più semplici. La retention aggressiva non fa paura: tenere 90 snapshot giornalieri non costa 90 volte lo spazio del primo. Si può essere generosi con i punti di ripristino senza preoccuparsi di far esplodere la fattura S3. Il primo backup di una nuova applicazione è l'unico che costa davvero in termini di upload; quelli successivi sono quasi gratuiti a meno di cambiamenti significativi.

Questo cambia anche il modo di pensare ai fire drill — i test di recupero periodici che verificano che il backup funzioni davvero. Con i backup tradizionali a catena, testare un punto di ripristino specifico richiedeva di ricostruire la catena fino a quel punto. Con restic, testare il backup di 10 giorni fa è identico a testare quello di ieri: si chiama lo snapshot per hash, si restaura in un ambiente isolato, si verifica che l'applicazione risponda. La complessità è costante, non dipende dall'anzianità dello snapshot.

E quando qualcosa va storto — perché prima o poi qualcosa va storto — la domanda non è "il backup c'è?" ma "quale snapshot voglio?" La risposta è a portata di mano, con date precise, dimensioni note, e la certezza che restaurare il punto A non richiede di aver tenuto anche i punti B, C e D nel mezzo. Questo, alla fine, è quello che si vuole da un sistema di backup: non solo che esista, ma che si possa fidarsene.

- FINE -
1