Организация бэкапов с помощью LVM


Вдруг осознал, что я тут двигаю всякие классные технологии, а сам пребываю в каменном веке. Перенёс /home в LVM. Сразу захотелось использовать моментальные инкрементальные бэкапы LVM. Как это сделать в сети написано (точнее, раскопировано и переведено) уже не один десяток раз. Но я пока не встретил ни одной статьи, где простые примеры создания снимка эволюционировали до полноценного скрипта. Восполню этот пробел quick programming’ом.

Но сначала немного технических деталей. В снапшотах ZFS есть неоспоримые преимущества перед снапшотами LVM:

  1. В LVM надо заранее выделять место под снапшот (по сути, создавать ещё один logical volume). Если размер изменений в основном разделе превысили это место, снапшот становится неактивным. Его нельзя ни подмонтировать, ни растянуть. Только удалить. Но место под снапшоты можно налету увеличивать, это сомнительный, но плюс.
  2. В LVM в каждом снапшоте хранится разница с основным разделом, а не с предыдущим разделом. В итоге, если мы сделали снапшот backup1, затем залили в FS файлик 30MB, затем сделали снапшот backup2, затем залили ещё один файлик на 30MB, то в backup1 будет занято 60MB, а в backup2 30MB. Логично было бы делать снапшот от снапшота, тогда разница накапливалась по-человечьи. Но LVM такое извращение не поддерживается.

Но есть и преимущества:

  1. Снапшот является RW. Честно говоря, так и не придумал, зачем оно может понадобиться.
  2. LVM живёт в kernel space, в отличие от порта ZFS на Linux zfs-fuse.
  3. ZFS предоставляет и не нужный мне слой навороченной FS.

Итак, надо периодически делать снапшот раздела, хранить определённое количество часовых и суточных копий. Для этого написал shell-скриптик lvm-home-snapshot. Вот он:

#!/bin/sh
 
name=$1
size=$2
vgname=$3
lvname=$4
copies=$5
 
time=`date +'%Y-%m-%d--%H-%M-%S'`
sname="backup-$time-$name"
 
/sbin/lvcreate -p r -L$size -s -n $sname /dev/$vgname/$lvname
 
lst=`/sbin/lvdisplay | egrep '^ +LV Name' | egrep "/dev/$vgname/backup-.*-$name"|awk '{print $3}'`
snapshots_cnt=`echo $lst|wc -w`
if [ $snapshots_cnt -gt $copies ]; then
	to_delete=`(for i in $lst; do echo $i; done) | head $(($copies-$snapshots_cnt))`
	for i in $to_delete; do /sbin/lvremove -f $i; done
fi

Как хорошо видно, принимает 5 параметров: имя снапшота, размер, имя группы разделов, имя раздела, количество хранимых копий. Пример использования:

lvm-home-snapshot hourly 768M home john 3

Создаст снапшот “/dev/home/backup-2009-06-19–14-45-01-hourly” раздела /dev/home/john размером 768MB. Если накопилось более трёх снапшотов с именем hourly — наиболее старые будут удалены. Итого, в крон написал:

0 14        * * *    /root/bin/lvm-home-snapshot day 2G home john 4
0 0-4,15-23    * * *    /root/bin/lvm-home-snapshot hour 256M home john 8
15,30,45 *    * * *    /root/bin/lvm-home-snapshot hourquot 128M home john 3

Итак снапшоты создаются, всё чудно. Но надо как-то минимизировать вероятность перезаполнения снапшотов. Для этого был написан ещё один скрипт, который заодно удаляет INACTIVE (переполнившиеся) снапшоты:

#!/usr/bin/perl
 
use warnings;
use strict;
 
my ($name, $vgname, $maxpct, $addpct) = @ARGV;
 
open my $proc, "/sbin/lvdisplay|";
 
my ($d, $s, $u);
while (<$proc>) {
	chomp;
	if (/^ +LV Name +(.*)/) { $d=$1 }
	elsif (/^ +COW-table size +(\d+)\S* +(.*)/) { $s=int $1; $u=$2 }
	elsif (/^ +Allocated to snapshot +(\d+)/) {
		my $pct = $1;
		next if $d !~ m|^/dev/$vgname/backup-.*-$name$| || $pct<$maxpct;
 
		my $newsize = int $s*($addpct/100+1);
		`/sbin/lvextend -L$newsize$u $d`;
	}
	elsif (m|^ +(/dev/$vgname/backup-.*-$name) \[INACTIVE\]|) {
		`/sbin/lvremove -f $1`;
	}
}
close $proc

Принимает параметры: имя снапшота, имя группы разделов, максимальный процент занятости (при превышении снапшот увеличивается), на сколько процентов от текущего увеличить. Пример использования:

lvm-home-snapshot-extend hourly home 15 30

Все снапшоты с именем hourly в группе разделов home, занятые более чем на 15%, будут увеличены на 30%. В крон добавил строчки:

* *        * * *    /root/bin/lvm-home-snapshot-extend hourquot home 15 30
* *        * * *    /root/bin/lvm-home-snapshot-extend hour home 25 30
* *        * * *    /root/bin/lvm-home-snapshot-extend day home 35 20

Не слишком эффективно, но меня устраивает. Да и лень как-то дальше развивать.

, , , , ,

  1. No comments yet.
(will not be published)

  1. No trackbacks yet.