Tämä kirjoitus on päivitysversio 9.3.2012 julkaistusta Paranoidin backup-reseptistä. Sen julkaisun jälkeen olen tehnyt skripteihin pieniä muutoksia, joista suurin on ollut järjestelmälevyn kopioiden pitäminen paikallisessa RAID-pakassa vain 7 päivän ajan. Alunperin säilytysaika oli 30 päivää, mutta kun niin pitkää aikaa ei kokonaisuuden kannalta ollut tarpeellista pitää ja aloin epäillä, että liian suuri tiedostomäärä olisi ainakin myötävaikuttanut tiedostojärjestelmän vioittumiseen, josta toipuminen oli aika työlästä.

Tuota tiedostomäärää pitänee hieman avata. Linuxissa ja yleensäkin *nixeissa järjestelmälevyllä on varsin suuri määrä keskimäärin hyvin pieniä tiedostoja. Jos siitä tehdään kopioita, nousee tiedostomäärä helposti miljooniin, jopa kymmeniin miljooniin. Siihen tiedostojärjestelmät eivät ole tottuneet. Tällä hetkellä paikallisen RAID-pakan varmistushakemistossa tuorein järjestelmälevyn kopio pitää sisällään yli 600 000 tavallista tiedostoa ja kaikkiaan siellä on ainakin näennäisesti lähes viisi miljoonaa tiedostoa. Kun tallennusaika oli 30 päivää, niitä saattoi olla jopa 20 miljoonaa.

[root@rk7 bk]# ls
1  2  3  4  5  6  7  current
[root@rk7 bk]# find current -type f | wc -l
614125
[root@rk7 bk]# find . -type f | wc -l
4905924

Ja sitten järjestelmälevyn varmistustallennusskripti

#!/bin/bash
# /mirrors on suuri data-tiedostojärjestelmä
# muuta se järjestelmääsi sopivaksi
if [ ! `mount | grep /mirrors >/dev/null` ]
then
# vaikutusta vain 1. ajokerralla
  mkdir -p /mirrors/bk/current > /dev/null
  cd /mirrors/bk
  rm -rf 7
  for i in `seq 7`
  do
    mv $((7-$i)) $((8-$i)) > /dev/null
  done
  cp -al current 1
# cp-komento ei muuta kohdehakemiston päiväystä, joten
  touch 1/bktimestamp
# muuta lähde- ja kohdehakemistoja tarpeen mukaan
  rsync -axH --delete /      current/sda3
  rsync -aH --delete  /boot  current/sda1
  echo Systemdisk backup done at `date`
fi

Kerrataan vielä tuon skriptin fiksuin ominaisuus. Näennäisesti järjestemälevyn sisältö on kopioituna kahdeksaan kertaan, mutta todellisuudessa vain yhden kerran. Sisällöltään toisistaan poikkeavat tiedostot ovat kuitenkin kaikki tallessa ja esimerkiksi lokitiedostoista, jotka päivittyvät useammin kuin kerran päivässä, on kahdeksan erilaista versiota. Asia selittyy kovien linkkien käytöllä ja cp-käskyn l-vivulla. Tiedostoihin tehdään vain uusi viittaus eikä niiden varsinaista sisältöä kopioida. Käytännössä tämän vaikutuksen näkee du-käskyn tulostamana:

[root@rk7 bk]# du -sh *
65G     1
2,8G    2
2,5G    3
2,4G    4
2,7G    5
3,0G    6
5,5G    7
2,7G    current
[root@rk7 bk]# du -sh
86G
[root@rk7 bk]# du -sh --count-links *
65G     1
65G     2
65G     3
65G     4
65G     5
65G     6
68G     7
65G     current
[root@rk7 bk]# du -sh --count-links
521G

65 gigaa tallennettuna kahdeksaan kertaan viekin levytilaa vain 86 gigaa eikä 521 gigaa. Kovat linkit voivat olla todella käteviä!

Toinen suuri muutos liittyy OpenIndiana-koneen päivitykseen, jota kuvasin kirjoituksessa Backupkone ja jatkamme sen vaikutuksella skripteihin.

Verkkovarmistustallennusskriptin testiversio

Jo ennen skriptin muuttamista olin huomannut uuden koneen varmistusosiota täyttäessä, että oli parempi, että työn teki backupkone, jolloin työasemana käyttämäni ei rasittuisi. Backupkoneessa on sitä paitsi nyt enemmän muistiakin. Skripti oli kuitenkin käynnistettävä työasemasta, joten työt käynnistetään ssh:n avulla. Virheentarkistuksien toiminta on tällä hetkellä varsin alkeellista. Jos ei onnistu, lopetetaan kertomatta syytä ( usean rivin lopussa oleva ” || exit”, poistu, jos epäonnistui).

#!/bin/bash
# herätetään rk4
if  [ "$1" = "-v" ]
 then
   wol 00:1C:C4:16:6E:6E
 else
   wol 00:1C:C4:16:6E:6E > /dev/null
fi
# Koneen ja sen levyadapterien BIOS:it vievät lähes pari minuuttia
# käynnistymisajasta. Scientific Linux käynnistyy komentokehotteeseen
# reilussa puolessa minuutissa, joten kokonaisaika on noin 2 min 30 s
# mutta odotetaan varmuuden vuoksi vielä 15 sekuntia
sleep 165
if  [ "$1" = "-v" ]
 then
  ping -c 3 rk4 || exit
 else
  ping -c 3 rk4 > /dev/null || exit
fi
ssh rk4 "mount rk7:/mirrors /rk7/mirrors"  || exit
cd /mirrors || exit
echo "ls -lR > ls_-lR"
if [ "$1" = "-v" ]
 then
  ssh rk4 "cd /tank ; \
           echo rsync --progress -aH --delete --exclude=bk/ /rk7/mirrors . ; \
           echo rsync --progress -aH --delete  /rk7/mirrors/bk/current mirrors/bk"    
 else
  ssh rk4 "cd /tank ; \
           echo rsync -aH --delete --exclude=bk/ /rk7/mirrors . ; \
           echo rsync -aH --delete  /rk7/mirrors/bk/current mirrors/bk"
fi
echo Mirror backup done at `date`
ssh rk4 "shutdown -h now"
exit

Skriptissä on hyvin paljon kohtia, jotka pitää mukauttaa, jos haluat käyttää sitä omiin tarkoituksiisi.

Ensinnäkin wol-käskylle pitää antaa sen koneen MAC-osoite, joka halutaan herättää. Sen saa selville esimerkiksi antamalla käskyn ifconfig:

[root@rk4 ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:1C:C4:16:6E:6E  
          inet addr:192.168.0.4  Bcast:192.168.0.255  Mask:255.255.255.0
...

Konenimi on tietysti toinen muokattava, vaihda se etsi-korvaa-toiminnolla. Joudut sitä paitsi kellottamaan koneesi käynnistysnopeuden sleep-käskylle. Sitten jäljellä onkin vain polut.

Skripti luottaa hyvin useisiin oletuksiin. Koneessa, jonka levy varmistetaan se on liitetty aina hakemistoon /mirrors, backupkoneessa on /tank vastaava ja ssh-avaimen käytöllä vältytään salasanan käytöltä. WOL voitaisiin myös suojata salasanalla, mutta niin ei ole tehty. Lisäksi /etc/hosts-tiedostossa on molemmissa koneissa myös verkon koneiden lyhyet nimet, kuten rk4 ja rk7.

Kun olet tehnyt tarvittavat muutokset ja testannut ne yllä olevalla varsin nopealla versiolla, voidaan siirtyä skriptin versioon, joka jo tekee varsinaista työtäkin ja lisätä siihen myös snapshotin luonti ja liian vanhojen poisto.

Verkkovarmistustallennusskriptin testiversio 2

Tässä versiossa jo tehdään varsinainen varmistustallennus, mutta testataan vielä snapshottien toimivuutta. Snapshottien käsittelyn automatisointiin on valmis skripti, joka ladataan ensin, annetaan sille suoritusoikeus ja testataan:

[root@rk4 ~]# wget -O /usr/local/sbin/zfs-auto-snapshot.sh https://raw.github.com/zfsonlinux/zfs-auto-snapshot/master/src/zfs-auto-snapshot.sh
[root@rk4 ~]# chmod u+x /usr/local/sbin/zfs-auto-snapshot.sh
[root@rk4 ~]# /usr/local/sbin/zfs-auto-snapshot.sh --label=hourly --keep=24 tank
[root@rk4 ~]# zfs list -t snapshot
NAME                                        USED  AVAIL  REFER  MOUNTPOINT
tank@zfs-auto-snap_hourly-2013-12-07-0527      0      -  10,2T  -

Tässä vaiheessa snapshotteja oli vasta yksi ja sen tallentaminen ei ole käyttänyt lainkaan levytilaa. Katsotaan vielä listaus myöhäisemmältä ajalta, jolloin snapshotteja on enemmän. Ne eivät vieläkään vie juuri yhtään tilaa.

[root@rk4 ~]# zfs list -t snapshot
NAME                                       USED  AVAIL  REFER  MOUNTPOINT
tank@zfs-auto-snap_daily-2013-12-12-0438  3,16G      -  10,2T  -
tank@zfs-auto-snap_daily-2013-12-13-0432  2,72G      -  10,2T  -
tank@zfs-auto-snap_daily-2013-12-14-0431  2,43G      -  10,2T  -
tank@zfs-auto-snap_daily-2013-12-15-0434  2,51G      -  10,3T  -
tank@zfs-auto-snap_daily-2013-12-16-0432  2,53G      -  10,3T  -
tank@zfs-auto-snap_daily-2013-12-17-0433  2,72G      -  10,3T  -
tank@zfs-auto-snap_daily-2013-12-18-0433  88,9M      -  10,3T  -

Jälleen sama etu kuin kovilla linkeillä saavutettin.

Sitten uusi skriptiversio

#!/bin/bash
# herätetään rk4
if  [ "$1" = "-v" ]
 then
   wol 00:1C:C4:16:6E:6E
 else
   wol 00:1C:C4:16:6E:6E > /dev/null
fi
# Koneen ja sen levyadapterien BIOS:it vievät lähes pari minuuttia
# käynnistymisajasta. Scientific Linux käynnistyy komentokehotteeseen
# reilussa puolessa minuutissa, joten kokonaisaika on noin 2 min 30 s
# mutta odotetaan varmuuden vuoksi vielä 15 sekuntia
sleep 165
if  [ "$1" = "-v" ]
 then
   ping -c 3 rk4 || exit
 else
   ping -c 3 rk4 > /dev/null || exit
fi
ssh rk4 "mount rk7:/mirrors /rk7/mirrors"  || exit
cd /mirrors || exit
ls -lR > ls_-lR
if [ "$1" = "-v" ]
 then
  ssh rk4 "cd /tank ; \
           rsync --progress -aH --delete --exclude=bk/ /rk7/mirrors . ; \
           rsync --progress -aH --delete  /rk7/mirrors/bk/current mirrors/bk"    
 else
  ssh rk4 "cd /tank ; \
           rsync -aH --delete --exclude=bk/ /rk7/mirrors . ; \
           rsync -aH --delete  /rk7/mirrors/bk/current mirrors/bk"
fi
ssh rk4 "/usr/local/sbin/zfs-auto-snapshot.sh --label=hourly --keep=24 tank"
echo Mirror backup done at `date`
ssh rk4 "shutdown -h now"
exit

Aja skripti ainakin kerran käsin, jotta backup olisi ajantasainen eikä kopiointiin kuluisi tuntia pidempään. Ja sitten uusi rivi tiedostoon /etc/crontab:

05 * * * * root  /usr/local/bin/mirrorbackupnew

Nyt vain sitten odotellaan reilu vuorokausi ja jos todetaan, että toimii, vaihdetaan suoritusväliksi esimerkiksi viikko ja säädetään säilytettävien snapshottien määrää.

Ensimmäinen ajastettu ajo kesti 25 minuuttia, varmistettavalla tiedostojärjestelmällä on yli 7 miljoonaa tiedostoa, jotka vievät 11 Tt tilaa. Skriptissä ls:n rekursiivisen listauksen ajo kestää 13 minuuttia.

Verkkovarmistustallennusskriptin lopullinen versio

Koska joka tunti tehtävät snapshotit toimivat yli vuorokauden ja vanhojen poisto toimi, oli looginen seuraava askel muuttaa ajastusta jokapäiväiseksi. Yhtä hyvin olisi voinut kyllä siirtyä suoraan lopulliseen eli viikottaiseen ajastukseen.

Välivaiheen skripti- ja crontab-rivit:

ssh rk4 "/usr/local/sbin/zfs-auto-snapshot.sh --label=daily --keep=7 tank"

05 6 * * * root  /usr/local/bin/mirrorbackupnew

Huomasit ehkä, että ensimmäisessä snapshottien luontikäskyssä label oli hourly. Kun se vaihdettiin dailyksi, ei zfs-auto-snapshot.sh enää poistakaan snapshotteja ,joiden label on hourly. Ne voi poistaa “yksirivisellä”:

for i in `zfs list -H -t snapshot | cut -f 1 | grep hourly` ; do zfs destroy $i ; done

Täydentyy… tai niin ajattelin. Nyt varmistukset menevät jo viikottain verkon yli ja alkaa pitkä tarkkailuvaihe. Tällä hetkellä snapshottien luontirivi on:

ssh rk4 "/usr/local/sbin/zfs-auto-snapshot.sh --label=weekly --keep=26 tank"

Snapshotteja siis säilytetään aluksi 26 viikkoa eli puoli vuotta. Levytilan käyttö tietysti kasvaa ja sitä täytyy seurata. Lisäksi backupkoneen ajastetut huoltotoimenpiteet pitää miettiä. Jos se on tunnin tai pari kerran viikossa päällä, niin kovin paljon huoltoa se ei tarvitse. ZFS:n scrub suositellaan yleensä ajamaan kerran kuukaudessa tai viikossa. Se voi kuitenkin olla aika pitkällinen operaatio. Se käy läpi kaiken tallennetun tiedon ja sen tarkistussummat. Käyttämätöntä levypintaa se ei käsittele. Olen jo kerran ajanut sen koneessani ja reilu puoli vuorokautta 11 teraa kesti lukea ja tarkistaa noin nopeudella 360 Mt/s. Taitaa mennä siihen kuukausittaiseen tai ehkä vieläkin harvempaan. Ja kuten sanoin, muutkin cronin kautta käynnistyvät hommat pitäisi hoitaa. Palvelimet on suunniteltu olemaan koko ajan päällä.

Melkein kaikki vanhasta backup-koneesta poistetut levyt ovat myynnissä huuto.netissä. Kaksi kuitenkin jätän itselleni ja kasvatan työasemakoneen RAID-6-pakkaa tarpeen tullen. Linuxsin softa-RAID:lla sen voi tehdä levy kerrallaan ja tiedostojärjestelmätkin venyy. Alkaa vain olemaan kotelossa aika monta levyä. Jossain vaiheessa sielläkin pitää vaihtaa levyt isompiin. Muuten alkaa tulla vastaan myös se ongelma, että RAID-6 ei pahimmissa tapauksissa riitä. Sen takia ZFS:ssä on myös raidz3 eli kolme levyä pariteetille.

Snapshottien käyttö vanhassa backup-koneessa tökki ensin vanhemman ZFS:n ongelmien vuoksi, mutta nyt ei pitäisi enää olla vastaavia ongelmia ja uuden koneen kolminkertainen keskusmuistimäärä antaa paljon turvallisuuden tunnetta. Alkakoon siis kestotestaus ja hienoviilaus.