Sauvegarde LVM simple (partie 2)

March 2018

Suite de l’article sur LVM thin provisioning, avec un script de sauvegarde simple.

Le script que je vais présenter ne fait que réaliser un snapshot puis le chiffre avec OpenSSL et enfin le transmet sur un serveur distant.

Le script bash utilise les cgroups linux afin de limiter la bande passante sur les disques et perturber le moins possible la production.

Il y a aussi une limitation du nombre de parts CPU maximum à utiliser si le CPU est utilisé par d’autre processus.

Les valeurs sont a ajuster en fonction du serveur de destination.

#!/bin/bash

################################################################################
# Simple Encrypted LVM(-thin) Backup
# Author: Laurent Coustet (c) 2011-2016
# http://ed.zehome.com/
################################################################################

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# CGROUP Bandwidth limits
CGROUP_ROOT="/sys/fs/cgroup"
CGROUP_NAME="backup"
# cpu.shares 1024 = 100% (of all cpus in group)
CGROUP_CPUSHARES="512" # 50% of all cpus maximum (only matters if machine is very busy)
# blkio.throttle.read_bps_device
# 100MiB/s on /dev/sda and /dev/sdb (minor:major bandwidth) (SSD and iSCSI)
CGROUP_BLKIO_THROTTLE_READ_BPS="8:0 $((100*1024*1024)),8:16 $((100*1024*1024))"

# You should modify this
DEST="/backup"
VG=rootvg
LV="lvol1 lvol2"
BACKUP_ONLY_AT=""
SSH_SERVER="myremote@server.com"
AES_PASSPHRASE="pleasechangemeoryourdumb"
OPENSSL_COMMAND="openssl enc -e -salt -aes-256-ctr -pass env:AES_PASSPHRASE"
LOG=/var/log/backup.log
declare -g CLEANUP_LV=""

umask 0077

cleanup()
{
  [ ! -z "$CLEANUP_LV" ] && lvremove -f "$CLEANUP_LV"
}

cgroup_init()
{
    [ -z "${CGROUP_NAME}" ] && return
    CGROUP_BLK_PATH="$CGROUP_ROOT/blkio/$CGROUP_NAME"
    CGROUP_CPU_PATH="$CGROUP_ROOT/cpu/$CGROUP_NAME"
    # We assume /cgroup is already mounter obviously ;)
    # Create cgroup if not already created
    [ -d "$CGROUP_BLK_PATH" ] || mkdir "$CGROUP_BLK_PATH"
    [ -d "$CGROUP_CPU_PATH" ] || mkdir "$CGROUP_CPU_PATH"

    [ ! -f "${CGROUP_BLK_PATH}/tasks" ] && (echo "No cgroup blkio support."; return 1)
    [ ! -f "${CGROUP_CPU_PATH}/tasks" ] && (echo "No cgroup cpu support."; return 1)

    # Setup limits
    if [ ! -z "$CGROUP_CPU_SHARES" ]; then
        echo $CGROUP_CPU_SHARES > ${CGROUP_CPU_PATH}/cpu.shares
    fi
    if [ ! -z "$CGROUP_BLKIO_THROTTLE_READ_BPS" ]; then
        OIFS="$IFS"; IFS=","; for i in $CGROUP_BLKIO_THROTTLE_READ_BPS; do
            echo $i > ${CGROUP_BLKIO_PATH}/blkio.throttle.read_bps_device
        done; IFS=$OIFS
    fi

    # Move us in the cgroup!
    echo $$ > $CGROUP_CPU_PATH/tasks
    echo $$ > $CGROUP_BLK_PATH/tasks
    return 0
}

lvm_backup()
{
    errors=0
    for volume in ${LV}; do
        if check_only_at ${volume}; then
            output="${HOSTNAME}_${volume}.lzop.aes256ctr"
            # LVM thin snapshot
            lvcreate -kn --name "backup_${volume}" -s "/dev/${VG}/${volume}"
            CLEANUP_LV="/dev/${VG}/backup_${volume}"
            pv -fper -i 1 "/dev/${VG}/backup_${volume}" | lzop -1 -c | AES_PASSPHRASE=$AES_PASSPHRASE $OPENSSL_COMMAND | ssh ${SSH_SERVER} "dd of=zehome/$output bs=1M"
            lvremove -f "/dev/${VG}/backup_${volume}"
            CLEANUP_LV=""
            if [ "$?" != "0" ]; then
                echo failed backup ${volume}: $?
                errors=$(($errors + 1))
                continue
            fi
        fi
    done
    return $errors
}

check_only_at()
{
    lv_to_dump="$1"
    day_now=$(date +%a)
    for tmp in ${BACKUP_ONLY_AT}; do
        lv=$(echo ${tmp} | cut -f1 -d':')
        day=$(echo ${tmp} | cut -f2 -d':')
        if [ "$lv" = "$lv_to_dump" ]; then
            if [ "$day" = "${day_now}" ]; then
                return 0
            else
                return 1
            fi
        fi
    done
    return 0
}

[ -x $(which lzop) ] || (echo please install lzop; exit 1)

echo "Starting backup $(date -R)" >&2
echo "Setting up CGROUP limits..." >&2
cgroup_init
(
    trap cleanup EXIT
    echo "Starting backup $(date -R)"
    echo "Launch LVM backup..."
    lvm_backup
    echo "Done backup $(date -R)"
) | tee -a $LOG

exit 0