Backup efficienti di container LXC in Proxmox (e non solo)

Proxmox

NOTA: Il seguente post è la traduzione dell'equivalente sul blog it-notes. L'originale sarà sempre più aggiornato.

A volte un container lxc può essere un'alternativa più valida rispetto ad ad una macchina virtuale KVM. Ha un overhead inferiore, una gestione delle risorse più semplice ed efficiente e un minore impatto sulla macchina fisica.

Si ottiene (potenzialmente) meno isolamento dalla macchina fisica e si è costretti ad usare il kernel dell’host. Inoltre, non è possibile eseguire un sistema operativo diverso.

Proxmox supporta in maniera nativa i container lxc ed essi sono spesso una buona scelta. Ho recentemente convertito alcune VM in container lxc e sono più veloci, più leggeri e l'occupazione della ram è abbastanza bassa.

Ci sono due grossi svantaggi: non è possibile migrare un container lxc in esecuzione (deve essere spento, spostato e riavviato - se si usa uno storage condiviso, spesso è una questione di secondi) e i backup su Proxmox Backup Server sono più lenti rispetto al backup di una VM.

Questo perché una VM può monitorare, grazie alle dirty bitmap di KVM, le sue operazioni su disco per sapere in anticipo quali blocchi devono essere controllati e copiati. Quando si ha a che fare con i container lxc non è possibile farlo, quindi ogni operazione di backup dovrà controllare ogni singolo file - questo si è dimostrato efficiente in termini di spazio e deduplicazione, ma piuttosto lento in termini di tempo. Una delle mie VM (750 GB memorizzati ma con sporadico accesso al disco) ha richiesto solo alcuni minuti per il backup con dirty bitmap, ma più o meno 2 ore per il backup da quando è stata trasformata in un contenitore lxc.

Il backup con borg si è dimostrato abbastanza efficiente, così ho cercato di trovare un modo per eseguire il backup di quei contenitori eseguendo una snapshot, eseguendo il backup e, poi, rilasciandola.

Non possiamo usare dattobd sul container, quindi dobbiamo fare una snapshot e fare il backup direttamente dall'host. Questo ha un grande vantaggio: non abbiamo bisogno che il container conosca la sua posizione di backup in quanto ogni operazione sarà fatta dall'host Proxmox.

I miei container sono generalmente memorizzati in volumi rbd di Ceph o in thin pool di LVM.

Ho creato uno script per affrontare entrambe queste situazioni - e non dipende da Proxmox, quindi funziona anche se non lo si usa.

Prima di tutto, si dovrebbe creare un utente e un repository borg su una macchina remota e permettere all'host Proxmox di effettuare il login via ssh usando una chiave. Poi, creare una directory (/tobackup nei seguenti script, sull'host) dove verranno montate le snapshot.

Nell'esempio/script seguente, non verrà utilizzata alcuna crittografia per la memorizzazione di backup. Se si desidera crittografare il backup, sarà necessario eseguire piccole modifiche.

Ecco il mio rbd_borg_bck.sh :

#!/bin/bash
set -e
export SOURCE_DISK=$1
export USERNAME=$2
export HOST=$3
PATH="/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/pkg/bin:/usr/pkg/sbin"
export PATH
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes;
echo "Creating and mapping snapshot..."
rbd snap create $SOURCE_DISK@tobackup && DDISK=`rbd map $SOURCE_DISK@tobackup`
echo "Creating backup directory..."
mkdir -p /tobackup/$DDISK
echo "Mounting snapshot..."
mount -o noload $DDISK /tobackup/$DDISK
echo "DOING BACKUP..."
REPOSITORY=$USERNAME@$HOST:$USERNAME/
TAG=daily
borg create -v --stats --progress --compression zlib,9                           \
    $REPOSITORY::$TAG'-{now:%Y-%m-%dT%H:%M:%S}'          \
    /tobackup/$DDISK/                                       \
    --exclude '*/home/*/.cache*'                  \
    --exclude '*/home/*/.local*'                  \
    --exclude '*/home/*/.pki*'                    \
    --exclude '*/home/*/Virtualbox VMs*'          \
    --exclude '*/home/*/.vagrant.d*'              \
    --exclude '*/root/.cache*'                    \
    --exclude '*/var/swap*'
sleep 3s;
echo "Unmounting snapshot..."
umount /tobackup/$DDISK
sleep 3s;
echo "Unmapping snapshot..."
rbd unmap $DDISK
echo "Remove snapshot..."
rbd snap remove $SOURCE_DISK@tobackup
echo "Pruning..."
borg prune -v $REPOSITORY --stats --prefix $TAG'-' \
    --keep-daily=14 --keep-weekly=8 --keep-monthly=12
echo "Done!"

Per esempio, per eseguire il backup di un disco memorizzato nel pool "vmrbdpool" denominato vm-101-disk-0 tramite ssh sul server backupserver.mydomain.org, nome utente sul server (e nome del repository, all'interno della directory home di quell'utente, chiamato server01), si può lanciare lo script in questo modo:

/usr/local/bin/rbd_borg_bck.sh vmrbdpool/vm-101-disk-0 server01 backupserver.mydomain.org

Questo può anche essere programmato e lanciato da cron (sull'host Proxmox) o in qualsiasi altro modo.

Per i thin pool di LVM, lo script è un po' diverso. Ecco il mio lvm_thin_borg_bck.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/bin/bash
set -e

export SOURCE_DISK=$1
export USERNAME=$2
export HOST=$3
export LVM=$4
export DDISK=$4/$2-borgsnap

PATH="/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/pkg/bin:/usr/pkg/sbin"
export PATH

export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes;

echo "Creating and mapping snapshot..."
lvcreate -n $2-borgsnap -s $1
lvchange -ay -Ky $DDISK


echo "Creating backup directory..."
mkdir -p /tobackup/$DDISK

echo "Mounting snapshot..."
mount -o ro /dev/$DDISK /tobackup/$DDISK

echo "DOING BACKUP..."

REPOSITORY=$USERNAME@$HOST:$USERNAME/
TAG=daily

borg create -v --stats --progress --compression zlib,9                           \
    $REPOSITORY::$TAG'-{now:%Y-%m-%dT%H:%M:%S}'          \
    /tobackup/$DDISK/                                       \
    --exclude '*/home/*/.cache*'                  \
    --exclude '*/home/*/.local*'                  \
    --exclude '*/home/*/.pki*'                    \
    --exclude '*/home/*/Virtualbox VMs*'          \
    --exclude '*/home/*/.vagrant.d*'              \
    --exclude '*/root/.cache*'                    

sleep 3s;

echo "Unmounting snapshot..."
umount /tobackup/$DDISK

sleep 3s;

echo "Remove snapshot..."
yes | lvremove $DDISK

echo "Pruning..."
borg prune -v $REPOSITORY --stats --prefix $TAG'-' \
    --keep-daily=14 --keep-weekly=8 --keep-monthly=12

echo "Done!"

In questo esempio, vogliamo fare il backup di un disco "/dev/prox1/vm-120-disk-0", il nome utente sul server è server01 (stesso nome del repository), il server è backupserver.mydomain.org e, come ultimo argomento, "prox1" che è il pool lvm.

/usr/local/bin/lvm_thin_borg_bck.sh /dev/prox1/vm-120-disk-0 server01 backupserver.mydomain.org prox1

Borg è efficiente e veloce e, grazie a questo tipo di configurazione, posso creare un backup del container da 750 GB in 2 minuti.

Grazie a questo tipo di configurazione, i backup possono essere effettuati in modo coerente ed efficiente.

Proxmox Backup Server - Consigli per una buona implementazione

Proxmox

NOTA: Il seguente post è la traduzione dell'equivalente sul blog it-notes. L'originale sarà sempre più aggiornato.

Proxmox Backup Server (PBS) è stato rilasciato. È ancora in beta ma è già perfettamente utilizzabile. Dopo molti anni, è ora possibile eseguire backup incrementali delle VM e grazie alle dirty bitmap di qemu, i backup sono anche veloci.

La documentazione è ben fatta e chiara, quindi suggerisco di darle un'occhiata per tutte le opzioni disponibili.

In breve, permette di eseguire il backup di qualsiasi VM o Container Proxmox su uno specifico server PBS (che può anche eseguire Proxmox o meno - non è indicato eseguire il backup sullo stesso server dove sono in esecuzione le VM). Non richiede alcun file system o impostazione speciale in quanto divide i file in blocchi (quindi la deduplicazione è possibile ed efficiente) e lo storage può essere effettuato in qualsiasi FS supportato.

Lo uso sin dal primo giorno ed è abbastanza efficiente e affidabile, ho fatto il backup di centinaia di server e ne ho ripristinati molti senza problemi.

Ecco alcuni suggerimenti (questo post sarà aggiornato in base alle novità):

  • Il primo backup sarà lento - almeno quanto un backup tradizionale Proxmox. Non preoccupatevi, è perfettamente normale.
  • NON EFFETTUARE IL TRIM DELLE VM, ma usare l'opzione "discard" come opzione di mount (se Linux): il trim passerà tutti i blocchi "sporchi" e li azzererà, riempiendo il database delle dirty bitmap da considerare per il backup e rallentando il backup successivo (anche se non sarà più grande).
  • Per lo stesso motivo, se volete mantenere più server di backup, ricordate di fare il backup su UN SOLO server PBS e poi di sincronizzarlo su un altro. Il backup delle stesse VM su più server "confonderà" le dirty bitmap e ogni backup sarà più lento (non più grande).
  • A volte la sincronizzazione su un altro server può fallire e rimanere bloccata. Al momento (0.8.11-1), ho scoperto che lo stop non risolve il problema e bisogna riavviare la PBS, altrimenti il task sembrerebbe essere ancora in esecuzione.

Il PBS ha risolto un problema di lungo corso: eseguire backup efficienti, deduplicati e incrementali di Proxmox VM.

BTRFS: effettuare automaticamente snapshot e backup remoti

BTRFS

Utilizzo con soddisfazione BTRFS (ne ho parlato nel 2014 e, più recentemente, nel blog IT-Notes). Non lo considero ottimale per tutti i tipi di carico, ma risolve molti problemi in moltissime situazioni. Una delle cose che utilizzo con più soddisfazione è la funzione di generazione dinamica di snapshot, che garantisce la possibilità di avere una copia perfetta e immediata di uno specifico volume (o subvolume). Quando è necessario un backup, ad esempio, l'utilizzo delle snapshot è fondamentale e averle a livello di file system è senza dubbio un buon ausilio.

Quando si tratta di volumi BTRFS, però, abbiamo ulteriori opzioni. Ci sono strumenti nativi che sono in grado di inviare e ricevere dati da e verso volumi BTRFS in maniera ottimizzata, sfruttando le caratteristiche intrinseche del file system stesso. Ecco dunque un metodo per fare automaticamente delle snapshot e trasferirle, in maniera ottimale, su un altro volume BTRFS (locale o remoto).

Da un po' di tempo mi avvalgo di due script interessanti. In passato ho utilizzato snapper ma non l'ho trovato ottimale per il mio utilizzo. Ho dunque continuato ad effettuare ricerche e trovato delle valide alternative, ovvero l'accoppiata di btrfs-snp e btrfs-sync

btrfs-snp

btrfs-snp permette di essere lanciato con un path, un prefisso legato alla snapshot effettuata, il numero massimo di snapshot con quel prefisso da tenere e un tempo minimo tra una snapshot e l'altra.

Ad esempio:

root@foobar:~# /usr/local/sbin/btrfs-snp / hourly  10 3600

Effettuerà una snapshot di /, mettendo come prefisso il termine hourly (ma può essere qualsiasi prefisso), ne terrà massimo 10 e non ne effettuerà altri (ovvero il programma uscirà senza fare azioni) a meno di 3600 secondi dal precedente.

Si possono ovviamente combinare in questo modo, per avere più snapshot di tipo diverso:

/usr/local/sbin/btrfs-snp / hourly  10 3600
/usr/local/sbin/btrfs-snp / daily    3 86400
/usr/local/sbin/btrfs-snp / weekly   1 604800

Può essere lanciato da un cron ogni ora (o ogni quarto d'ora, tanto non effettuerà snapshot a meno di 3600 secondi dal precedente).

btrfs-sync

A questo punto, possiamo copiare su altro file system (locale o remoto) tutte le snapshot grazie a btrfs-sync.

Il comando può essere di questo tipo:

root@foobar:~# /usr/local/sbin/btrfs-sync -d -v /.snapshots btrfs@host:/backups/host01/

Ovviamente il file system di destinazione deve essere un volume BTRFS.

Di solito lancio il comando attraverso uno script nel cron.daily, per avere una copia giornaliera delle snapshot fuori.

Questo tipo di setup mi ha già tolto dai guai più volte e sembra essere efficiente.

Docker: come limitare la crescita incontrollata dei log dei container

(English version, Rotating Docker log files available on IT-Notes blog)

Ho già scritto in merito al fatto che io apprezzi Docker come soluzione per il deploy di specifici servizi. Invece che "sporcare" le singole distribuzioni e dover tenere tutto aggiornato alle versioni delle stesse, si può avere un sistema pulito, replicabile, aggiornabile rapidamente.

Uno dei problemi che ho riscontrato è però questo: quando si hanno dei container che non vengono aggiornati spesso (o, meglio, ricreati spesso), il loro output continua ad accumularsi in un file di log legato al container stesso. Alla fine si rischia di trovarsi con un log enorme e nessuna cognizione di come ridurne le dimensioni.

In un caso specifico, ho avuto un riempimento di disco proprio a causa di uno di questi container (gitlab) che, producendo molto output, aveva creato un json di log di svariate decine di giga in pochi mesi. Facendo una breve ricerca ho trovato la soluzione. E' semplice e Docker supporta, tramite parametri di creazione dei singoli container, la gestione dei log.

Basta dunque passare questi parametri:

--log-opt max-size=50m --log-opt max-file=5

Il container, a quel punto, limiterà il log a 50 mega (limite da definirsi in base alle proprie necessità) ed effettuerà una rotazione dei log stessi (nell'esempio, terrà al massimo 5 log).

In questo modo l'occupazione disco sarà sotto controllo. Perché, dunque, non hanno impostato un limite sano di default? Perché si parte dal presupposto che i container siano usa e getta e che, dunque, vengano spesso buttati e ricreati. La cosa ha una sua logica, ma non è certamente adatta a tutti gli innumerevoli utilizzi.

Nuova disavventura con Tiscali

Arrabbiato

Circa dodici anni fa ho avuto una brutta esperienza con Tiscali. Ne ho parlato e la cosa ha avuto addirittura un seguito, tanto da farmi pensare che non avrei più voluto avere nulla a che fare col gestore in oggetto.

Col passare degli anni, però, ho avuto informazioni da alcuni clienti su come le cose fossero cambiate e la loro soddisfazione mi ha spinto, circa un anno fa, a riflettere. Avendo una linea TIM Business da soli 7 Mbit/sec pagata a peso d'oro, la loro offerta non sembrava così male.

Spinto dunque dalla speranza che fossero davvero migliorati, ho chiesto l'attivazione di una loro linea, subentrando a Telecom. Avendo già Eolo come gestore principale, infatti, la linea ADSL sarebbe servita solo come backup o per gli utilizzi (tipo il Voip) che sopportano male le latenze irregolari e imprevedibili di un ponte radio del genere.

Tutta la procedura, effettuata online, procede correttamente. L'indirizzo risulta attivabile e mi confermano che a breve avrei avuto loro notizie.

Dopo pochi giorni, mi contatta un loro operatore che mi chiede conferma dell'indirizzo per la spedizione del router. Tempo due giorni arriva il router.

E qui inizia il bello

Pochi giorni e arriva una telefonata. C'è un problema e la centrale da il KO al subentro. Dicono che, tecnicamente, l'offerta non sembra essere attivabile in quanto la centrale è satura. Ma come fa ad essere satura se si rimpiazza una connessione esistente? . L'operatore concorda e mi rassicura che sono cose che accadono e che, alla fine, si risolvono.

Nessuna fretta, connessione Telecom lenta e costosa ma stabile.

Passa qualche altro giorno e mi avvisano che poiché Tiscali non ha interessi specifici nelle forniture business, avrebbero passato il contratto a Fastweb che, di fatto, è loro partner. O almeno così dicono. Mi mandano uno stralcio di contratto incompleto con già i miei dati inseriti e chiedono una firma.

Con gentilezza faccio notare che non posso firmare qualcosa che non mi è stato neanche inviato integralmente. Concordano e mi mandano il contratto completo.

Pochi giorni e Fastweb mi manda tutti i dati, compresi username e password di connessione, comunicando che sarebbe a breve stato attivato tutto. Passano settimane... nulla.

Telefono per informazioni, mi dicono che la centrale ha dato KO tecnico e che avrebbero riprovato. Dopo circa un mese, mi comunicano che il servizio non è attivabile e si scusano per avermi fatto perdere tempo.

Ok, penso, "resto coi miei problemi nella speranza che la FTTC arrivi presto" (Ed è accaduto, Telecom ha attivato il 31/12/18).

Dopo un paio di mesi, suonano alla porta. "Sono il Corriere, devo ritirare per conto di Tiscali il router". Senza preavviso, senza appuntamento. Memore di ciò che era accaduto anni fa, avevo tenuto il router ancora chiuso, sigillato, imballato e pronto. Consegno dunque il router al corriere, prendo la ricevuta e, penso, tutto a posto.

Povero illuso...

Arriva Giugno dello scorso anno e vedo un prelievo da conto corrente. Un addebito da parte di Tiscali. Nel frattempo arriva anche la fattura: non hai restituito il router, te lo facciamo pagare.

Telefono subito, inviperito, al loro servizio clienti. Non si meravigliano (succede spesso, quando avviene un ko tecnico) e mi spiegano che devo mandare via fax (!!!) o via messaggio Facebook (!!!) copia della fattura, copia della ricevuta del corriere e una richiesta di rimborso. Contrariato, eseguo, pur chiedendomi se al giorno d'oggi sia il fax lo strumento di comunicazione oppure un "messaggio Facebook".

Passa circa un mese, telefono. Non hanno ricevuto nulla e mi suggeriscono di mandare di nuovo tutto. Incredulo (della mia idiozia nel dare di nuovo fiducia a questa Compagnia) mando tutto di nuovo e chiedo conferma. Stavolta hanno ricevuto la documentazione.

Chiedo dunque il tempo di rimborso. La risposta è esilarante: "Più di un anno, forse un anno e mezzo in quanto abbiamo molte pratiche"

Rido. Rido per non piangere. Inutile dire che ad oggi, dopo più di un anno, non è ancora arrivato un singolo euro di rimborso.

Tutto questo mi fa venire in mente un vecchio proverbio arabo:

La prima volta che m’inganni la colpa è tua, ma la seconda volta la colpa è mia.