Differences between revisions 2 and 3
Revision 2 as of 2021-09-03 16:31:21
Size: 8055
Editor: Kurgan
Comment:
Revision 3 as of 2022-01-20 12:37:32
Size: 8196
Editor: Kurgan
Comment: modificato per pve 7
Deletions are marked like this. Additions are marked like this.
Line 10: Line 10:
'''NOTA BENE: PVE6 e 7 usano variabili diverse. Per PVE6 usare $TARFILE al posto di $TARGET nello script'''
Line 49: Line 50:
   echo $TARFILE >> $listfile    echo $TARGET >> $listfile
   #
echo $TARFILE >> $listfile

Backup su storage remoto dei dump

Normalmente io preferisco che la macchina con PVE esegua i backup su un disco locale piuttosto che su uno storage montato da remoto. Il motivo di questa scelta è presto detto: il disco locale di solito è più veloce e meno prono ad avere problemi di disconnessioni. Usando backup diretto su storage remoti in NFS mi è capitato di avere dei piantamenti (morte del server NFS sotto carico) durante il backup che provocano il piantamento della VM che sto backuppando e questo non mi piace. So bene che il server NFS non dovrebbe morire, ma siccome lo fa, ho imparato ad adattarmi al problema e girarci intorno, installando un disco interno per i backup. Una volta terminato il backup (con vzdump, ovvero con il sistema di backup presente dentro PVE) sul disco interno, questo script permette di fare una seconda copia su un disco esterno, senza che questa operazione impatti sulle VM in esecuzione anche in caso di problemi al disco esterno.

Questo script si "aggancia" al sistema di backup interno di PVE (non parliamo di PBS, parliamo della funzione di dump contenuta in PVE), allo scopo di fare una seconda copia dei dump delle VM su uno storage esterno (smb, nfs, usb, qualsiasi cosa si possa montare). Questo script cosi` come e` fatto tiene 6 backup giornalieri e 4 settimanali, quindi sono 10 backup. Tenete bene conto dello spazio necessario! Ad ogni esecuzione di un job di backup, una volta eseguiti i dump di tutte le VM, questo script copia tutti i dump sullo storage remoto, dopo aver archiviato quelli precedenti dentro le directory "daily" e "weekly".

Nella nuova versione (che trovate qui sotto) ho aggiunto una funzione che crea un hard link dell'ultimo file creato nel backup su un file con un nome fissato. In altri termini, impostando la variabile "hardlink" a un path (che deve esistere e deve trovarsi sullo stesso disco fisico che contiene i backup) lo script crea un hard link (che non consuma spazio ulteriore) dal file backuppato da PVE (che ha un nome non prevedibile in quanto contiene data e ora) dentro alla directory definita nella variabile "hardlink" con un nome fisso, sovrascrivendo, se c'e`, il file con il medesimo nome. Questo "trucco" permette di eseguire un backup remoto in un secondo tempo in modalità "pull", usando backuppc o rsnapshot o altri sw di backup che fanno storicizzazione e deduplica, potendosi così proteggere meglio dai ransomware o da un attacco al server PVE, usando dei backup storicizzati non accessibili a meno che non venga compromesso anche il server di backup.

NOTA BENE: PVE6 e 7 usano variabili diverse. Per PVE6 usare $TARFILE al posto di $TARGET nello script

  • Prima di tutto, creare lo script e renderlo eseguibile. Io lo chiamo /root/pve-remote-backup.sh.

     #!/bin/bash
    
    # Impostazioni varie:
    
    # dove salvo il file con l'elenco dei files da backuppare
    listfile="/tmp/pve-remote-backup-filelist.txt"
    
    # dove monto il disco dello storage remoto o removibile
    mountpoint="/usbdisk"
    
    # dove vengono creati gli hard link che verranno poi usati
    # da un sistema di backup pull remoto (backuppc / rsnapshot)
    # NOTA BENE: il path deve essere nello stesso disco fisico dove si trovano 
    # i backup di PVE, deve esistere, ed e` meglio che sia diverso da quello
    # che contiene i backup (che di solito e` "dumps")
    # Se non voglio usare questa funzione lo imposto a "NONE" o commento via la riga
    hardlink="/backupdisk/hardlinks"
    
    
    # all'inizio del job, mi assicuro di cancellare
    # la lista dei files
    
    if [ "$1" == "job-start" ]; then
       echo "JOB-START: cancello la lista dei files"
       [ -f $listfile ] && rm $listfile
       exit 0
    fi
    
    
    # alla fine del singolo backup mi segno il nome
    # del file che e` stato creato, mi servirà dopo per
    # sapere cosa devo copiare.
    
    if [ "$1" == "backup-end" ]; then
       echo "BACKUP-END: salvo il nome del file"
       echo $TARGET >> $listfile
       # echo $TARFILE >> $listfile
    fi
    
    # alla fine del job,
    # se la funzione hardlink è richiesta, la eseguo, poi
    # monto lo storage remoto, ruoto i vecchi backup se necessario,
    # e copio tutti i files del backup attuale sullo storage remoto
    
    if [ "$1" == "job-end" ]; then
      # se la variabile hardlink non e` vuota, non contiene la stringa "NONE" 
      # ed e` una directory che esiste, allora procediamo a creare gli hard link 
      if [ ! -z $hardlink ] && [ "$hardlink" != "NONE" ] && [ -d $hardlink ] ; then
                    echo "JOB-END: Creo i link per il backup a mezzo di rsnapshot"
                    while IFS= read -r line
                    do
                            nopath=`echo $line |  awk 'END{ n=split ($NF,a,"/"); print a[n]}'`
                            destination=`echo $nopath | awk -F[-.] '{ print $1 "-" $2 "-" $3 "." $6 "." $7}'`
                            if [[ -z "${line// }" ]] ; then
                                    echo "JOB-END: ERRORE, trovata una linea vuota nell'elenco di input - la ignoro"
                            else
                                    echo "JOB-END: creo hardlink da  $line su $hardlink/$destination"
                                    ln -f $line $hardlink/$destination
                            fi
                    done <"$listfile"
      fi
    
      #  fine della procedura degli hard link, procediamo con le copie sullo storage remoto
      echo "JOB-END: Monto lo storage remoto"
      # MODIFICARE QUI PER IL MOUNT
      mount -L usbbackup  $mountpoint
    
      if mountpoint -q $mountpoint; then
            echo "JOB-END: Storage remoto montato"
    
            # Leggo la lista dei files da copiare e li copio rinominandoli
            # in modo da togliere il timestamp.
            while IFS= read -r line
            do
                    nopath=`echo $line |  awk 'END{ n=split ($NF,a,"/"); print a[n]}'`
                    destination=`echo $nopath | awk -F[-.] '{ print $1 "-" $2 "-" $3 "." $6 "." $7}'`
                    if [[ -z "${line// }" ]] ; then
                            echo "JOB-END: ERRORE, trovata una linea vuota nell'elenco di input - la ignoro"
                    else
                            echo "JOB-END: Salvo lo storico per $mountpoint/$destination"
                            if [[ $(date +%u) -eq 7 ]] ; then
                                    # se e` domenica salvo in weekly e ne tengo 4
                                    savelog -c4 -l -r weekly $mountpoint/$destination
                            else
                                    # se e` un altro giorno salvo in daily e ne tengo 6
                                    savelog -c6 -l -r daily $mountpoint/$destination
                            fi
                            echo "JOB-END: Copio $line su $mountpoint/$destination"
                            cp $line $mountpoint/$destination
                    fi
            done <"$listfile"
    
    
            # Fine della copia, smonto e ho finito.
            echo "JOB-END: Smonto lo storage remoto"
            umount $mountpoint
            exit 0
      else
            echo "JOB-END: ERRORE, storage remoto non accessibile"
            exit 1
      fi
    fi
  • modificare lo script in modo da fare il mount del vostro storage remoto preferito
  • impostare il path per gli hardlink (se volete) oppure impostarlo a "NONE" per disattivare la funzione relativa
  • Per finire, modificare il file /etc/vzdump.conf inserendo una riga che dice di usare lo script durante i job di backup. In questo modo il nostro script casalingo verrà richiamato dalla procedura di backup interna di PVE. Questa seconda versione dello script non si incasina se viene richiamato due volte in due procedure di backup diverse che eseguono i backup di VM diverse, in quanto ogni invocazione dello script va a modificare SOLO i files relativi alle VM che vengono incluse nel backup in esecuzione. In altri termini, se ho 4 VM e ne backuppo due alla mattina e due al pomeriggio, lo script non va ad archiviare sul disco di backup esterno le VM che non sono parte del backup in corso. Tuttavia, se decido di backuppare la stess VM tre volte in un giorno, allora occorre rivedere le logiche di archiviazione "daily" e "weekly" perchè queste logiche sono pensate per UN SOLO BACKUP al giorno di ogni VM.

    script: /root/pve-remote-backup.sh

PVE/BackupScript (last edited 2022-01-20 12:37:32 by Kurgan)