2015. november 8., vasárnap

Scripting LVM Snapshot Backups

In this article I will show you how you can simply backup an LV.
In this example we are going to script a mail server's mailbox store LVM backup.

The LVM backup script


#!/bin/bash
SIZE=1G            # Size of a snapshor. Make sure, there is space for all 7 snapshot
VGNAME=/dev/vg00    # /dev/VGNAME
LVTOBACKUP=www        # only the name of LV
DAY=`date +%a`
SNAPSHOTNAME="$LVTOBACKUP-$DAY"

# ---------------------- Do not edit under this line  -------------------

SCRIPTNAME=$0
SENDMONITORINGDATA=true
FAILOCCURED=0
# Detailed log to syslog
#exec > >(logger -t "$SCRIPTNAME" -p local3.info ) 2> >(logger -t "$SCRIPTNAME" -p local3.info)
set -x
ZBXSENDER=`which zabbix_sender`
if [ $? -ne 0 ]
then
    SENDMONITORINGDATA=false
    echo "Not sending data to Zabbix"
fi
ZBXCONFIG=`find /etc/zabbix/ -maxdepth 1  -name '*.conf' | tail -n 1`
sendMonitoringData(){
    if [ "$SENDMONITORINGDATA" = true ]
    then
        echo "Sending monitoring data: $SCRIPTNAME - $1"
        $ZBXSENDER --config $ZBXCONFIG --key scripterror --value $1
        $ZBXSENDER --config $ZBXCONFIG --key scriptname --value $SCRIPTNAME
    fi
}
checkResult(){
    EXITSTATUS="$1"
    shift
    MSG="$*"
    if [ $EXITSTATUS -eq 0 ]
    then
        echo "$MSG - OK"
    else
        echo "$MSG - FAIL"
        sendMonitoringData $EXITSTATUS
        FAILOCCURED=1
    fi
}
lvs "$VGNAME/$SNAPSHOTNAME" 2>&1 > /dev/null
RETCODE=$?
checkResult $RETCODE "Failed to check $VGNAME/$SNAPSHOTNAME"
if [ $RETCODE -eq 0 ]
then
    lvremove -f "$VGNAME/$SNAPSHOTNAME"
    checkResult $? "Failed to remove $VGNAME/$SNAPSHOTNAME"
fi
sync
lvcreate -L "$SIZE" -s -n "$SNAPSHOTNAME" "$VGNAME/$LVTOBACKUP"
checkResult $?  "Failed to create $VGNAME/$SNAPSHOTNAME"
if [ $FAILOCCURED -eq 0 ]
then
    sendMonitoringData 0
else
    echo "Due to failure no more alert to monitoring"
fi


Explanation


It seems a bit complicated script, let me explain:

LVM part

The basic backup script looks like this
 #!/bin/bash
SIZE=1G            # Size of a snapshot. Make sure, there is space for all 7 snapshot
VGNAME=/dev/vg00    # /dev/VGNAME
LVTOBACKUP=mail        # only the name of LV
DAY=`date +%a`
SNAPSHOTNAME="$LVTOBACKUP-$DAY"

# ---- 
lvs "$VGNAME/$SNAPSHOTNAME" 2>&1 > /dev/null
RETCODE=$?
if [ $RETCODE -eq 0 ]
then
    lvremove -f "$VGNAME/$SNAPSHOTNAME"
fi
sync
lvcreate -L "$SIZE" -s -n "$SNAPSHOTNAME" "$VGNAME/$LVTOBACKUP"


For LVM snapshot you need to define the snapshot Logical Volume size.
It depends on the application witch data you are backing up.
After the initialization period you can check the used amount of Snapshot space like this:
# lvs
  LV       VG   Attr   LSize  Origin Snap%  Move Log Copy%  Convert
  mysql    vg00 -wi-ao  5,00g                                     
  swap     vg00 -wi-ao  4,00g                                     
  mail     vg00 owi-ao 30,00g                                     
  mail-Sun vg00 swi-a-  1,00g mail    0,70

You can see that, it uses the 0.7% of the configured size. I could configure smaller size...

I'm using daily backup, it creates a new LV snapshot every day. The name is came from the original Logical Volume's name and the sort version of day of week.

The script first check whether the last weeks LVM snapshot is available. If exist, then first it removes that.
Then the last lines are coming:
sync
lvcreate -L "$SIZE" -s -n "$SNAPSHOTNAME" "$VGNAME/$LVTOBACKUP"

Sync is important, because we need the data on disk, not in cache ;-)

Monitoring

You can see that, there are more lines connecting to monitoring than for the backup.
To make sure, this script can be used on different distributions and different versions, the path are not burned into the code.
Every step of the backup process is monitored and reported to Zabbix and of course to syslog.

Please feel free to use it.

All feedback are welcome.