Moro med backup!

I noen år nå har jeg kjørt duplicity backup både på servesystemer og klienter. Dette har virket bra, men har det samme problemet som all annen inkrementell filbackup: Før eller siden må du ta ny full backup for at det ikke skal bli for tungt å kjøre restore. Med mye data trenger du da relativt mye lagringsplass, og en del av skyleverandørene operer med «retention time», dvs. at du må betale for brukt diskplass i et minimum antall dager.

Med overgang til ny server som nevnt i forrige blogg-innlegg, begynte jeg å se på nye backupsystemer også – spesielt siden zfs har mye innebygget snacks som snapshots, zfs send etc, og kan sende inkrementell backup av volumene f.eks. til https://rsync.net/. Dette var fristende – men jeg ville ha en backupløsning som virket både på klienter og servere, og ikke var helt avhengig av zfs.

Her forleden dag fant jeg Borg backup.

Jeg ble litt frelst, bl.a fordi:

  • Enhver backup er likeverdig, alle backuper er fulle backuper.
  • Deduplisering med checksummer på klientsiden gjør at diskforbruk og båndbreddebehov etter den første backupen blir minimalt.
  • Klienter fantes til mine relevante klientplattformer, som alle er unix-baserte. Windows er litt mer komplisert, men det er ikke en aktuell problemstilling for meg.

På min Mac var saken grei: En backup av data-disken var alt som holdt. En av Borg sine kule features: At du kan montere backupen som et remote filsystem, var litt mer komplisert fordi det krever en custom kjernemodul for FUSE. Sikkerhetsinnstillingene på iallefall nyere MacOS gjør at du ikke uten videre kan installere slikt selv som root, og du må boote i sikker modus for å tillate kjernemodulene. Det kan høres skummelt ut, men det gikk ganske greit.

Jeg valgte å bruke borgmatic som rammeverk rundt borg, fordi det forenkler en del operasjoner. Det finnes også en GUI-klient som heter Vorta – men den har jeg ikke prøvd, da jeg er mer kommandolinjemenneske enn gui-menneske.

En av ulempene med Borg er dog at du må bruke ssh for kommunikasjonen, og det begrenser antall leverandører. Du kan bruke rsync.net, men med mitt plassbehov (mer enn 1 TB og økende), ble det ganske kostbart.

En annen leverandør jeg fant heter https://www.borgbase.com/ -her har jeg valgt en plan som gir meg 1TB for $80 i året, og $0.007 per GB per måned for overskytende data. Neste plan er 2TB til $150 i året, og $0.005 per overskytende GB per måned. Det er fremdeles litt data igjen før denne vil lønne seg for meg, og man kan oppgradere når som helst.

Jeg har valgt å lage et repository for hver klientmaskin. Borgbase har en utmerket guide for å lage/sette opp repositories, og gir deg tilogme en borgmatic-template for hvert repository slik at du har et utmerket startpunkt å bygge videre på.

For Macen ser borgmatic-config slik ut (hemmelige data skjult). Som alle andre løsninger sliter man litt med at hemmeligheter må hardkodes et eller annet sted, men på min personlige Mac valgte jeg å se vekk fra dette:

location:
    source_directories:
        - /System/Volumes/Data

    repositories:
        - *******@********.repo.borgbase.com:repo 

    exclude_patterns:
        - /System/Volumes/Data/Volumes/
        - /System/Volumes/Data/private

    exclude_if_present: .nobackup

storage:
    compression: auto,lz4
    encryption_passphrase: *******
    ssh_command: ssh -i /path/to/ssh-key
    archive_name_format: 'Mac-{now:%Y-%m-%d-%H%M%S}'

retention:
    keep_daily: 3
    keep_weekly: 4
    keep_monthly: 12
    keep_yearly: 2
    prefix: 'Mac-'

consistency:
    checks:
        # Uncomment to always do integrity checks.
        # (takes long time for larger repos)
        #- repository
        - disabled

    check_last: 3
    prefix: 'Mac-'

hooks:
    # Shell commands to execute before or after a backup
    before_backup:
        - echo "`date` - Starting backup"

    after_backup:
        - echo "`date` - Finished backup"

Med dette oppsettet (etter at repoer er laget), blir en backup kun en enkel kommando, borgmatic, som kan kjøres i cron. Andre operasjoner gjøres med enkle kommandor som f.eks. borgmatic list, borgmatic prune, etc.

En borgmatic info på Macen gir meg i skrivende stund:

------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:                1.28 TB            907.06 GB            254.45 GB
                       Unique chunks         Total chunks
Chunk index:                  945385              4257703

Dette er fordelt på 3 backup-runs, så jeg har ca 400 GB med data å ta backup av – som vist over utgjør det per nå 254 GB lagringsplass hos leverandøren. Den første backupen tok ca. 8 timer – de neste er unnagjort på ikke fryktelig mange minuttene, men selvsagt mye lenger tid hvis det er mye endringer.

På serveren i skyen har jeg et tilsvarende ukomplisert oppsett. Det var på NAS/server-boksen at det ble moro.

I et tidligere innlegg har jeg skrevet om hvordan boksen ble til, og at jeg har valgt ZFS som filsystem. Dette gjør at det etterhvert blir noen logiske volumer, fordi de er dynamiske og lever sammen i samme pool, og er utrolig enkle å håndtere.

En av tingene zfs gjør bra er f.eks. snapshots. Det å opprette, lage, montere og slette snapshots er noe du knapt tenker over, det er lurt å gjøre det til en ryggmargsrefleks å lage et snapshot før du skal gjøre noe seriøst. Et snapshot har også den fordelen at det er atomisk, og det er en seriøs fordel når man skal ta backup. Mye filer hører jo egentlig logisk sammen, og at de er tatt backup av på forskjellig tidspunkt kan være svært uheldig. Dette unngår du hvis du tar backup fra et snapshot.

Jeg har også et rot-volum som ikke er ZFS men LVM, og LVM har også snapshots – så jeg gjør det samme med rotfilsystemet.

location:
            source_directories:
                            - /backup/*/
                            - /backup_lvm/*/
                            - /boot/

            repositories:
                            - ******@******.repo.borgbase.com:repo

            exclude_patterns:
                            - /proc/
                            - /sys/
                            - /tmp/
                            - /var/tmp/
                            - /run/
                            - /backup_lvm/*/tmp/
                            - /backup_lvm/*/var/tmp/
                            - /backup_lvm/*/run/
                            - /backup_lvm/*/root/.cache/
                            - /backup_lvm/*/var/lib/docker/overlay2/

            exclude_if_present: .nobackup

storage:
            compression: auto,lz4
            encryption_passphrase: *******
            ssh_command: ssh -t -i /path/to/ssh-key
            archive_name_format: 'hassio-{now:%Y-%m-%d-%H%M%S}'

retention:
            keep_daily: 7
            keep_weekly: 4
            keep_monthly: 12
            keep_yearly: 2
            prefix: 'hassio-'

consistency:
            checks:
                   # Uncomment to always do integrity checks.
                   # (takes long time for larger repos)
                   # - repository
                   - disabled
                   #
            check_last: 3
            prefix: 'hassio-'

hooks:
            # Shell commands to execute before or after a backup
            before_backup:
                    - echo "`date` - Starting backup" ;snapname='backup'-`date +%Y-%-m-%d-%H%M`;zfs snapshot -r nasdisk@$snapname;zfs snapshot -r znvm@$snapname;for i in `zfs list -t snapshot|grep $snapname|awk '{print $1}'`;do backup=`zfs get -H borg:backup $i|awk '{print $3}'`; if [ "$backup" = "yes" ]; then fs=`echo $i|sed -e "s/\@$snapname//"`;mp=`zfs get -H mountpoint $fs|awk '{print $3}'`;linkname=`echo $fs|sed -e "s/\//_/g"`;mkdir /backup/$linkname;mount -t zfs $i /backup/$linkname;else zfs destroy $i;fi;done
                    - lvs --noheadings --select 'lv_tags=backup'| while read -r lv vg rest; do which lvcreate;echo lvcreate -L1G --snapshot -n ${lv}_snap /dev/$vg/$lv;lvcreate -L10G --snapshot -n ${lv}_snap /dev/$vg/$lv;mkdir -p /backup_lvm/${lv}_snap;mount /dev/$vg/${lv}_snap /backup_lvm/${lv}_snap/;mount | grep backup_lvm;done

            after_backup:
                    - for i in /backup/*;do umount $i;rmdir $i;done
                    - echo $snapname
                    - for i in `zfs list -t snapshot|grep @backup-20|awk '{print $1}'`; do zfs destroy $i;done
                    - for i in /backup_lvm/*; do umount $i;rmdir $i;done
                    - lvs --noheadings --select 'lv_tags=backup'| while read -r lv vg rest; do lvremove -f /dev/$vg/${lv}_snap;done
                    - echo "`date` - Finished backup"

Den virkelige moroa ligger i before_backup og after_backup.

Jeg har to zpools, nasdisk og znvm. nasdisk er redundant, znvm er ikke, det er den interne SSDen. Jeg bruker det for data som skal aksesseres hyppig, og hvor hastighet spiller stor rolle. Men manglende redundans er jo litt nedtur. Nå er ikke serveren min kritisk, men likevel er jeg paranoid. Derfor satte jeg opp en jobb med sanoid som syncer dem hver time til et tilsvarende volum på nasdisken som har redundans. Det er likevel unødvendig å ta backup av begge – selv om dedupliseringen . I tillegg har jeg noen andre volumer som kanskje ikke er interessant å ta backup av – selv om dedupliseringen gjør at det ikke er kritisk, tids- eller plassmesig.

Jeg har valgt å lage en property, borg:backup=yes, på zfs-filsystemene det skal taes backup av. Denne har jeg lagt på zpoolen slik at nye filsystemer automatisk vil taes backup av, og så overstyrer jeg det med borg:backup=no på de filsystemene jeg ikke vil ta backup av. En zfs -r snapshot nasdisk@<navn> lager et snapshot med samme navn på alle volumene i poolen, og så løper jeg igjennom filsystemene i en loop og monterer de jeg vil ta backup av under /backup/ – og sletter de andre snapshotene.

For LVM blir det tilsvarende, jeg setter en tag backup og tar snapshot og monterer alle volumer med denne tagen under /backup_lvm/.

Selve backupen tar jeg av filsystemene /backup, /backup_lvm og /boot. Da får jeg automatisk bort en del irrelevante ting som /proc og /sys, og andre ting man ikke ønsker å ta backup av.

Etter endt backup avmonterer jeg og sletter alle snapshoter.

NAS-boksens initielle backup, med litt over 1 TB data, tok 12 timer. Nattens backup? 4 minutter og 7 sekunder!

For ordens skyld – her er informasjonen fra NAS-boksen sitt repo:

------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:                3.37 TB              3.20 TB              1.04 TB
                       Unique chunks         Total chunks
Chunk index:                 1008300              3913748

Nå har jeg snakket om backup. Et gammelt ordtak sier at backup er lett, det er restore som er vanskelig. Borg-backuper kan monteres, så kan jeg se på innholdet som jeg vil, og kopiere ut det jeg trenger. Du kan også restore med en borgmatic extract.

root@hassio:~# borgmatic mount --mount-point=/mnt
root@hassio:~# cd /mnt
root@hassio:/mnt# ls
hassio-2021-11-23-225804  hassio-2021-11-24-221404  hassio-2021-11-25-010037
root@hassio:/mnt# ls hassio-2021-11-25-010037
backup  backup_lvm  boot
root@hassio:/mnt# ls hassio-2021-11-25-010037/*
hassio-2021-11-25-010037/backup:
nasdisk                                   nasdisk_docker_volumes_nextcloud_nextcloud        nasdisk_home     znvm_nextcloud_db
nasdisk_anita                             nasdisk_docker_volumes_wordpress_database         nasdisk_photos   znvm_plex_database
nasdisk_cecilie                           nasdisk_docker_volumes_wordpress_database_vegard  nasdisk_storage
nasdisk_docker_volumes                    nasdisk_docker_volumes_wordpress_html             nasdisk_vegard
nasdisk_docker_volumes_calibreweb_config  nasdisk_docker_volumes_wordpress_html_vegard      znvm

hassio-2021-11-25-010037/backup_lvm:
ubuntu-lv_snap

hassio-2021-11-25-010037/boot:
System.map-5.4.0-88-generic  config-5.4.0-89-generic  initrd.img                   initrd.img.old            vmlinuz-5.4.0-89-generic
System.map-5.4.0-89-generic  config-5.4.0-90-generic  initrd.img-5.4.0-88-generic  lost+found                vmlinuz-5.4.0-90-generic
System.map-5.4.0-90-generic  efi                      initrd.img-5.4.0-89-generic  vmlinuz                   vmlinuz.old
config-5.4.0-88-generic      grub                     initrd.img-5.4.0-90-generic  vmlinuz-5.4.0-88-generic

Det er lett å bli glad i Borg. Det finnes et ganske likt system, som heter restic. Dette har fordelen at det kan kjøre mot flere typer backends. Jeg har ikke sett på og sammenlignet dette.

Så, hva har jeg oppnådd med alt dette?

  • Fulle backuper gir lettere restores.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.

Dette nettstedet bruker Akismet for å redusere spam. Lær om hvordan dine kommentar-data prosesseres.