Ciao, Habr!
Oggi vorrei condividere la nostra esperienza nella automazione del backup di grandi volumi di dati archiviati in Nextcloud in diverse configurazioni. Lavoro come CTO presso 'Molniya AK', dove ci occupiamo di gestione della configurazione dei sistemi IT, utilizzando Nextcloud per lo storage dei dati, compresa una struttura distribuita con backup.
Le problematiche derivanti dalle peculiarità delle installazioni sono dovute all'abbondanza dei dati. La versioning offerta da Nextcloud, il backup, le ragioni soggettive e altro ancora creano molte duplicazioni.
Contesto
Nell'amministrazione di Nextcloud, si presenta acutamente il problema di organizzare backup efficaci che devono essere necessariamente crittografati, poiché i dati hanno un grande valore.
Offriamo opzioni di archiviazione dei backup sia presso di noi che presso il cliente su macchine separate da Nextcloud, il che richiede un approccio automatizzato e flessibile all'amministrazione.
Ci sono molti clienti, ognuno con configurazioni diverse, tutti nelle proprie sedi e con le proprie peculiarità. Qui la metodologia standard, in cui l'intero ambiente appartiene a te e i backup sono eseguiti tramite cron, si adatta male.
Innanzitutto, diamo un'occhiata ai dati di input. Abbiamo bisogno di:
- Scalabilità in termini di un nodo o più. Per grandi installazioni utilizziamo minio come storage.
- Essere informati sui problemi durante l'esecuzione del backup.
- È necessario conservare il backup presso i clienti e/o presso di noi.
- Essere in grado di risolvere rapidamente e facilmente i problemi.
- I clienti e le installazioni differiscono notevolmente l'uno dall'altro — non riusciamo a ottenere uniformità.
- La velocità di ripristino deve essere minima in due scenari: ripristino completo (disastro), una cartella — cancellata per errore.
- È fondamentale avere la funzione di deduplicazione.

Per affrontare la gestione dei backup, abbiamo integrato GitLab. Maggiori dettagli nella sezione successiva.
Sicuramente non siamo i primi a risolvere un compito del genere, ma riteniamo che la nostra esperienza pratico-testata possa essere interessante e siamo pronti a condividerla.
Poiché nella nostra azienda è adottata una politica di open source, abbiamo cercato una soluzione con codice sorgente aperto. A nostra volta, condividiamo i nostri progetti e li pubblichiamo. Ad esempio, su GitHub c'è , che forniamo ai clienti, potenziando la protezione dei dati in caso di eliminazione accidentale o volontaria.
Strumenti di backup
La ricerca di soluzioni è iniziata con la scelta di uno strumento per la creazione del backup.
Il classico tar + gzip funziona male: i dati sono duplicati. L'incremento contiene spesso pochissime modifiche e gran parte dei dati all'interno di un file si ripete.
C'è anche un altro problema: la ridondanza dello storage distribuito. Utilizziamo MinIO e i suoi dati sono in genere ridondanti. O avremmo dovuto effettuare il backup direttamente tramite MinIO – sovraccaricandolo e utilizzando tutti gli strati tra il file system, con il rischio non trascurabile di dimenticare parte dei bucket e delle informazioni sui metadati. Oppure utilizzare la deduplicazione.
Esistono strumenti di backup con deduplicazione nel mondo open source (ne abbiamo parlato su Habr) ) e i nostri finalisti sono stati e . Di seguito la nostra comparazione tra le due applicazioni, ma prima parleremo di come abbiamo organizzato l'intero schema.
Gestione della creazione di backup
Borg e Restic sono buoni, ma nessuno dei due prodotti ha un meccanismo di gestione centralizzato. Per gestire e controllare, abbiamo scelto uno strumento che abbiamo già implementato, senza il quale non concepiamo il nostro lavoro, compresa l'automazione: il celebre CI/CD – GitLab.
L'idea è la seguente: su ogni nodo che memorizza dati Nextcloud viene installato gitlab-runner. Il runner esegue secondo un programma uno script che monitora il processo di backup, avviando Borg o Restic.
Cosa abbiamo ottenuto? Feedback sull'esecuzione, controllo conveniente delle modifiche, dettagli in caso di errore.
Ecco abbiamo pubblicato esempi di script per diverse attività, e alla fine l'abbiamo integrato nel backup non solo di Nextcloud, ma anche di molti altri servizi. Lì si trova anche il pianificatore, se non vuoi configurarlo manualmente (e noi non vogliamo) e .gitlab-ci.yml
Nell'API di GitLab attualmente non è possibile modificare il timeout di CI/CD, che è piuttosto breve. Deve essere aumentato, ad esempio a 1d.
Fortunatamente, GitLab può essere avviato non solo tramite commit, ma anche secondo un programma, esattamente ciò di cui abbiamo bisogno.
Ora riguardo allo script avvolgente.
Abbiamo stabilito queste condizioni per questo script:
- Deve essere eseguito sia come runner che a mano dalla console con la stessa funzionalità.
- Devono essere presenti gestori degli errori:
- codice di ritorno.
- ricerca di una stringa nel log. Ad esempio, per noi un errore può essere un messaggio che il programma considera non fatale.
- Gestione del timeout. Il tempo di esecuzione deve essere ragionevole.
- Abbiamo bisogno di un log molto dettagliato. Ma solo in caso di errore.
- Viene inoltre eseguita una serie di test prima dell'inizio.
- Piccole funzionalità per la comodità che abbiamo trovato utili durante il supporto:
- L'avvio e la conclusione vengono registrati nel syslog della macchina locale. Questo aiuta a collegare gli errori di sistema e il funzionamento del backup.
- Parte del log degli errori, quando presente, viene emessa in stdout, l'intero log viene scritto in un file separato. È comodo dare un'occhiata direttamente in CI e valutare l'errore se è triviale.
- Modalità per il debug.
Il log completo è conservato come artefatto in GitLab, se non ci sono errori il log viene eliminato. Scriviamo lo script in bash.
Accogliamo con favore qualsiasi suggerimento e osservazione sul software open source.
Come funziona
Sulla node di backup viene avviato un runner con un esecutore bash. In base al pianificatore, viene avviato un job CI/CD in un repository speciale. Il runner esegue uno script wrapper universale per tali attività, in cui vengono effettuati controlli di validità del repository di backup, dei punti di montaggio e di tutto ciò che vogliamo, quindi viene eseguito il backup e la pulizia di quello vecchio. Il backup finale viene inviato su S3.
Operiamo secondo questo schema: un provider esterno come AWS o un analogo russo (questo è più veloce e i dati non escono dalla Russia). Oppure installiamo un cluster minio dedicato presso il cliente per questi scopi. Di solito procediamo in questo modo per motivi di sicurezza, quando il cliente non vuole assolutamente che i dati lascino il loro perimetro.
Non abbiamo utilizzato la funzionalità di invio del backup tramite ssh. Ciò non aumenta la sicurezza e le capacità di rete del provider S3 sono nettamente superiori a quelle della nostra singola macchina ssh.
Per proteggere i dati da un hacker sulla macchina locale - potrebbe cancellare i dati su S3 - è assolutamente necessario abilitare la versioning.
Il backup viene sempre cifrato.
Borg ha una modalità senza cifratura. none, ma sconsigliamo vivamente di attivarlo. In questo modo non ci sarà solo mancanza di crittografia, ma non verrà nemmeno calcolato il checksum di ciò che viene registrato, il che significa che l'integrità può essere verificata solo indirettamente, tramite gli indici.
Un controllo dei backup sull'integrità degli indici e del contenuto è effettuato tramite uno scheduler separato. Il controllo avviene lentamente e richiede tempo, quindi lo eseguiamo separatamente una volta al mese. Può richiedere diversi giorni.
Readme in russo
Funzioni principali
preparepreparazionetestcheckverifica di prontezzamaincommandcomando principaleforcepostscriptfunzione eseguita alla fine o in caso di errore. Utilizziamo per smontare la partizione.
Funzioni di servizio
cleanupregistriamo errori o cancelliamo il file di log.checkloganalizziamo il log per la presenza di una stringa di errore.retgestore di uscita.checktimeoutcontrollo del timeout.
Ambiente
VERBOSE=1mostriamo gli errori a video immediatamente (stdout).SAVELOGSONSUCCES=1salviamo il log in caso di successo.INIT_REPO_IF_NOT_EXIST=1Creiamo il repository, se non esiste. Di default è disattivato.TIMEOUTtempo massimo per l'operazione principale. Puoi impostarlo come ‘m’, ‘h’ o ‘d’ alla fine.
Modalità di conservazione delle vecchie copie. Di default:
KEEP_DAILY=7KEEP_WEEKLY=4KEEP_MONTHLY=6
Variabili all'interno dello script
ERROR_STRING— string per il controllo nel log per errori.EXTRACT_ERROR_STRING— espressione per mostrare la stringa in caso di errore.KILL_TIMEOUT_SIGNAL— segnale per terminare in caso di timeout.TAIL— numero di stringhe con errori visualizzate sullo schermo.COLORMSG— colore del messaggio (giallo per impostazione predefinita).
Lo script chiamato WordPress è condizionatamente nominato tale; la sua caratteristica è che esegue anche il backup del database MySQL. Ciò significa che può essere utilizzato per installazioni monocomponenti di Nextcloud, dove è possibile effettuare anche il backup del database. Il vantaggio sta non solo nel fatto che tutto è in un unico posto, ma anche che il contenuto del database è vicino al contenuto dei file, con una differenza di tempo minima.
Restic vs Borg
Le comparazioni tra Borg e Restic sono disponibili anche , e non avevamo l'obiettivo di creare semplicemente un altro confronto, ma il nostro. Ci interessava vedere come apparisse sui nostri dati, con la nostra specificità. Li confrontiamo.
I nostri criteri di selezione, oltre a quelli già menzionati (deduplicazione, ripristino veloce, ecc.):
- Resilienza a operazioni incomplete. Controllo su kill -9.
- Dimensione su disco.
- Richiesta di risorse (CPU, memoria).
- Dimensione dei blob memorizzati.
- Compatibilità con S3.
- Controllo dell'integrità.
Per il test abbiamo scelto un cliente con dati reali e una dimensione totale di 1,6 TB.
Condizioni.
Borg non può lavorare direttamente con S3, quindi abbiamo montato come disco fuse, tramite . Restic inviava a S3 direttamente.
Goofys funziona molto velocemente e bene, e ha a disposizione , il che accelera ulteriormente le prestazioni. Si trova in fase beta e, ammettiamolo, è capitato che fallisse con perdita di dati nei test (altri test). Ma la comodità è che la procedura di backup non richiede molta lettura, ma principalmente scrittura, quindi utilizziamo la cache solo durante il controllo dell'integrità.
Per ridurre l'impatto della rete, abbiamo usato un provider locale — Yandex Cloud.
Risultati dei test di confronto.
- Kill -9 con un successivo riavvio, entrambi sono andati a buon fine.
- Dimensione su disco. Borg può comprimere, quindi i risultati sono previsti.
Backuper
Dimension
Borg
562Gb
Restic
628Gb
- Per CPU
Di per sé, borg consuma poco, con compressione predefinita, ma va valutato insieme al processo goofys. In totale, sono comparabili e utilizzano circa 1,2 core su una stessa virtual machine di test. - Memoria. Restic circa 0,5Gb, Borg circa 200Mb. Ma tutto ciò è trascurabile rispetto alla cache di file del sistema. Quindi è preferibile allocare più memoria.
- La differenza nelle dimensioni dei blob si è rivelata sorprendente.
Backuper
Dimension
Borg
circa 500Mb
Restic
circa 5Mb
- Il lavoro con S3 di Restic è eccellente. Il funzionamento di Borg tramite goofys non presenta problemi, ma è stato notato che è preferibile fare umount alla fine del backup per azzerare completamente la cache. Una caratteristica del funzionamento di S3 è che i chunk non completamente scaricati non verranno mai inviati nel bucket, il che significa che dati non completamente caricati possono portare a gravi danni.
- Il controllo dell'integrità funziona bene in entrambi i casi, ma la velocità differisce significativamente.
Restic – 3,5 ore.
Borg, con una cache file di 100GB SSD – 5 ore. Un risultato simile in termini di velocità se i dati sono memorizzati su un disco locale.
Borg legge direttamente da S3 senza cache 33 ore. Incredibilmente lungo.
In sintesi, Borg è in grado di comprimere e ha blob più grandi—il che rende più economico lo storage e le operazioni GET/PUT in S3. Tuttavia, si deve pagare con un controllo più complesso e lento. Per quanto riguarda la velocità di ripristino—non abbiamo notato differenze. I backup successivi (dopo il primo) restic richiede un po' più di tempo, ma non in modo significativo.
Non da ultimo, la dimensione della community ha avuto un peso nella scelta.
E abbiamo scelto Borg.
Due parole sulla compressione
Borg ha un eccellente nuovo algoritmo di compressione nel suo arsenale: zstd. La qualità della compressione è pari a gzip, ma è significativamente più veloce. È comparabile in velocità con il predefinito lz4.
Ad esempio, un dump di un database MySQL si comprime due volte meglio di lz4 alla stessa velocità. Tuttavia, l'esperienza con dati reali mostra una differenza molto piccola nel livello di compressione per i nodi di Nextcloud.
In Borg c'è una modalità bonus di compressione: se un file ha alta entropia, la compressione non viene applicata affatto, il che aumenta la velocità di esecuzione. Si attiva tramite un'opzione durante la creazione.
-C auto,zstd
per l'algoritmo zstd.
Con questa opzione, rispetto alla compressione predefinita, abbiamo ottenuto
560Gb e 562Gb rispettivamente. I dati dell'esempio sopra, ricordo, senza compressione risultano 628Gb. Il risultato di 2Gb di differenza ci ha sorpreso un po', ma abbiamo deciso di scegliere comunque auto,zstd.
Metodologia di verifica del backup.
Attraverso il pianificatore, viene avviata una macchina virtuale direttamente dal fornitore o dal cliente, il che riduce notevolmente il carico di rete. Almeno è più economico rispetto a farlo localmente e gestire il traffico.
goofys --cache "--free:5%:/mnt/cache" -o allow_other --endpoint https://storage.yandexcloud.net --file-mode=0666 --dir-mode=0777 xxxxxxx.com /mnt/goofys
export BORG_PASSCOMMAND="cat /home/borg/.borg-passphrase"
borg list /mnt/goofys/borg1/
borg check --debug -p --verify-data /mnt/goofys/borg1/Allo stesso modo, controlliamo i file con l'antivirus (post-fatto). Gli utenti caricano vari file su Nextcloud e non tutti hanno un antivirus. Effettuare il controllo al momento del caricamento richiede troppo tempo e interferisce con le attività aziendali.
La scalabilità si ottiene avviando runner su nodi diversi con tag diversi.
Nel nostro monitoraggio vengono raccolti gli stati dei backup tramite API GitLab in un'unica finestra, e in caso di necessità, i problemi possono essere facilmente individuati e localizzati.
Conclusione
Di conseguenza, sappiamo esattamente che stiamo effettuando backup, che i nostri backup sono validi, e i problemi che si presentano con essi richiedono poco tempo e vengono risolti a livello di amministratore di turno. I backup occupano realmente poco spazio rispetto a tar.gz o Bacula.
Fonte: habr.com
