Benutzer-Werkzeuge

Action disabled: source

Backup LVM Volumes

LVM (Logical Volume Manager) bietet unter Linux die einfache Möglichkeit flexibel Speicherplatz zur Verfügung zu stellen. Dabei kann LVM sowohl ganze Platten oder auch nur Partitionen verwalten. Diese werden zu sogeannten Volume Groups (VG) zusammengefasst. In diesen VG kann man dann Logical Volume(s) (LV) erstellen, welche dann die Daten aufnehmen können. Diese LV werden als Block Devices zur Verfügung gestellt, damit kann man ihnen alles machen was man sonst mit Block Devices macht z.B. Partitionieren.

LVM Snapshot

Hier soll es um das Backup von LVs gehen, denn dieses kann je nach Anforderung etwas komplizierter werden. Trotzdem wird das Backup durch ein sehr nettes Feature von LVM etwas erleichtert. LVM bietet die Möglichkeit sogeannte Snapshots zu machen, dabei wird ein LV in einem konsistenten Zustand gehalten, damit man davon ein Backup machen kann.

Ein Snapshot des LV meinSystem in der VG vg_system kann man so erstellen

lvcreate -s -L5G -nbackup /dev/vg_system/meinSystem

Das erstellt einen maximal 5GByte grossen Snapshot d.h. wenn sich mehr als 5GByte Daten am Dateisystem des LV verändern wird dieser Snapshot ungültig. Je nachdem wie schnell und wieviel sich Daten im LV verändern muss man diese Grösse anpassen. Wenn man den Snapshot gleich gross setzt wie die Grösse des LV, dann geht der Platz im Snapshot nie aus.

Image vom Snapshot

Nun hat man unter /dev/vg_system/backup bzw /dev/mapper/vg_system-backup ein Block Device mit dem Snapshot. Dieses könnte man jetzt z.B. mit einem Tool wie dd in ein Image File kopieren

dd if=/dev/mapper/vg_system-backup of=/pfad/zum/image.img bs=10M
lvremove /dev/vg_system/backup

es ist wichtig den Snapshot nach Gebrauch immer zu entsorgen!

Partitionen aus dem Image mounten

Dieses Image kann man leider meist nicht so ohne weiteres mounten v.a. wenn sich darin verschiedene Partitonen befinden. Dazu muss man sich eines Programms wie z.B. kpartx bedienen. Dieses kann aus Image Files die Partitionstabellen rauslesen und die Partitionen einbinden.

kpartx -av /pfad/zum/image.img

. Anhand der Ausgabe von kpartx kann man sehen wo die Devices erstellt wurden z.B. /dev/mapper/vg_system-image1 für die erste Partition. Wenn man das Dateisystem kennt kann man das Ganze dann so mounten

mount -t ext3 /dev/mapper/vg_system-image1 /mnt

Dann kann man in /mnt die Daten z.B. mit rsync oder rdiff-backup sichern.

Partitionen direkt aus dem Snapshot mounten

Alternativ kann man sich den Weg über das Image auch sparen und den Snapshot direkt an kpartx übergeben

kpartx -av /dev/mapper/vg_system-backup

kpartx bindet die gefundenen Partitionen so ein, dass man die nachher mounten kann. Dabei ist die erste Partition des LV im obigen Beispiel /dev/mapper/vg_system-backup1 und die zweite logischerweise vg_system-backup2. kpartx -av gibt genau an welche Partitionen und wie sie erkannt wurden. Um jetzt also die zweite Partition von oben auf /mnt zu mounten, muss man erst wissen welches Dateisystem sich darin befindet. Ich habe bei mir ext3

mount -t ext3 /dev/mapper/vg_system-backup2 /mnt

Jetzt kann man von /mnt z.B. ein Backup mit rsync machen.

Es ist wichtig, dass man zum Schluss (nach dem Backup) folgendes macht:

umount /mnt
kpartx -dv /dev/mapper/vg_system-backup
lvremove /dev/vg_system/backup

Backup Script

Für das Backup der LVs meiner virtuellen Maschinen habe ich mir folgendes Script geschrieben. Allerdings ist es stark an meine Umgebung angepasst, von daher sollte man das nur als Idee sehen und entsprechend selber anpassen. Das Script erstellt bei mir zuverlässig rdiff-backups aller Partitionen der VMs. Das Script mountet dazu die Partitionen direkt aus dem Snapshot-Device, es wird also kein Image erstellt, sondern es erfolgt ein Filebackup auf Filesystembasis

#!/bin/bash
 
# export path for use the script in cron
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 
# "hosts" to backup. These are patterns for matching of lv-volumes
# it specifies the beginning pattern of the lvm to backup
VIRT_HOSTS='
	ns3.brain-force.ch
        mail2.brain-force.ch
'
# volume group where $VIRT_HOSTS are situated
VG='vg_vms'
 
# basedir for backups
BKP_DIR='/backup/backups/filesystems'
 
# enable output to shell by setting to 1
# otherwise it will only be logged to the file
VERB=0
 
# defines the logfile
BKP_LOG=/var/log/lvm_bkp.log && touch $BKP_LOG
 
log() {
 echo "$(date +%d.%m.%y\ %H:%M:%S) "$* >> $BKP_LOG 
 [ $VERB -eq 1 ] && echo "$(date +%d.%m.%y\ %H:%M:%S) "$*
}
 
getVolumes() {
 [ "x$*" = 'x' ] && exit
 host="$*"
 disk=''
 for i in $(lvdisplay | grep \/$host | awk '{print $3}' | grep -v swap) ; do
  [ "$i" = 'status' ] && continue
  disk=$disk" "$i
 done
 log "Fetched $disk for $host"
}
createSnapshot() {
 [ "x$*" = 'x' ] && exit
 disk="$*"
 UUID=$(uuid)
 log "Creating snapshot of volume $disk" && lvcreate -L5G -s -n $UUID $disk >/dev/null && log "Created snapshot volume for $disk of $host as $UUID"
}
removeSnapshot() {
 [ "x$UUID" = 'x' ] && exit
 lvremove -f /dev/$VG/$UUID >/dev/null && log "Snapshot $UUID removed"
}
runBackup() {
 log "Getting devices from $UUID for $(basename $i)"
 kpartx -av /dev/$VG/$UUID > /tmp/part.tmp || exit
 while read line ; do
   PART="$(echo $line | awk '{print $3}' | grep -v 2$)"
   [ "x$PART" = 'x' ] && continue
   count=${PART: -1}
   #echo $count && continue
   FS=$(blkid /dev/mapper/$PART | awk '{print $3}' | awk -F'"' '{print $2}') 
   [ "$FS" = 'swap' ] && continue
   [ "x$FS" = 'x' ] && continue
#   echo "/backup/backups/filesystems/$(basename $i)/partition-${count}/" && continue
#   echo "$PART $FS" && continue
   log "Mount /dev/mapper/$PART on /mnt"
   mount -t $FS /dev/mapper/$PART /mnt/ && log "/dev/mapper/$PART sucessfully mounted on /mnt"
   sleep 1
   log "Create backupdir for $(basename $i)"
   mkdir -p $BKP_DIR/$(basename $i) >/dev/null 2>&1
   log "Starting backup for partition $count on $(basename $i)" 
   [ $VERB -eq 1 ] && rdiff-backup -v0 --print-statistics /mnt/ $BKP_DIR/$(basename $i)/partition-${count}/ | tee -a $BKP_LOG
   [ $VERB -ne 1 ] && rdiff-backup -v0 --print-statistics /mnt/ $BKP_DIR/$(basename $i)/partition-${count}/ >> $BKP_LOG
   log "Backup finished for partition $count on $(basename $i)"
   log "Umount /mnt" && umount /mnt && log "Sucessfully umounted /mnt"
 done </tmp/part.tmp
 sleep 2
 log "Remove partitions from kpartx"
 kpartx -dv /dev/$VG/$UUID >/dev/null && log "Partitions removed successfully"
}
 
log "Backup started" && START=$(date +%s)
for host in $VIRT_HOSTS ; do
 getVolumes $host
 for i in $disk ; do
  createSnapshot $i
  runBackup
  removeSnapshot
 done
done
END=$(date +%s)
END=$(($END - $START))
log "Backup finished in "$END" seconds"
Melden Sie sich an, um einen Kommentar zu erstellen.

Seiten-Werkzeuge