Статья
Версия для печати
Обсудить на форуме (1)
Использование LVM snapshot для уменьшения простоя при бекапе OpenVZ.


Автор: RXL
Написано: 22.08.2010


Введение.

В настоящее время все шире применяться различные средства виртуализации серверов. Это существенно упрощает создание новых хостов, управление ими, распределение нагрузки между физическими серверами и как следствие — снижает суммарную стоимость «железа», занимаемое физическими серверами место и энергопотребление, удешевляет обслуживание.
Одним из средств виртуализации является OpenVZ — открытый проект на базе коммерческой системы Virtuozzo. Это система виртуализации операционной системы для Linux. Для всех виртуальных контейнеров используется одно общее ядро ОС, что существенно снижает, по сравнению с полной и паравиртуализацией, расход оперативной памяти и отклик системы. Для виртуальных контейнеров в OpenVZ есть другой термин — виртуальное окружение (virtual environment — VE), что точнее отражает суть, но по-русски менее понятно на слух. Физический сервер в терминах OpenVZ называется аппаратным узлом (hardware node — HN).
В статье пойдет речь о создании резервных копий виртуальных контейнеров.

Резервное копирование контейнеров OpenVZ.

Физически файлы контейнера просто находятся в некоторой директории на HN. При запуске VE эта директория монтируются в другую, посредством механизмов, напоминающих mount --bind и последующий chroot. Т.е. для резервного копирования достаточно скопировать или съархивировать эту директорию. Т.к. контейнер может быть запущен либо остановлен, то и резервное копирование может быть выполнено «горячее», либо «холодное».
При горячем копировании может произойти порча структуры файлов, которые не были закрыты запущенными в контейнере программами. Особенно это чревато для баз данных. По этому этот метод нужно использовать очень осторожно. Этих недостатков лишено холодное копирование, но для него необходимо остановить контейнер, что не всегда приемлемо, да и вообще не хорошо вмешиваться в работу VE.
Для осуществление живой миграции контейнеров между HN у OpenVZ есть специальное состояние — checkpoint. При входе в это состояние все процессы контейнера замораживаются и содержимое памяти сбрасывается в дамп. Сохраняется также ядерная информация (например, о состоянии открытых сокетов). После перемещения файлов и дампа памяти VE на другой HN можно его там «оживить». Если промежуток времени от заморозки до оживления составляет единицы-десятки секунд, то приложения могут даже не заметить перемещения контейнера, а сетевые клиенты могут не отключиться.
Этот режим тоже можно использовать для резервного копирования контейнера OpenVZ. Конечно, через некоторое время, при восстановлении из этой копии, подключенных клиентов уже не будет, но зато целостность системы сохранится и можно будет остановить сервисы для получения полноценной «холодной» системы и запустить вновь.
Т.к. объем файлов контейнера может составлять от сотен мегабайт, до десятков гигабайт (считаю, что, когда счет идет на сотни гигабайт, нужно использовать иную стратегию резервного копирования, минимизирующую копируемый объем), то время копирования или архивации будет очень долгим и контейнер может долго пробыть в замороженном состоянии и, соответственно, его сервисы не будут доступны клиентам.

Использование LVM.

Решением проблемы будет использовать LVM и встроенный в эту него механизм создания снимков (snapshot) логических томов.
Для этого директория VE должна находиться на одном из логических томов и на его группе томов должно быть свободное место для создания снимка. После создания снимок не занимает места, т.к. полностью соответствует своему оригиналу, но только до тех пор, пока оригинал не начинает изменяться (или изменяется сам снимок). В случае изменения блока в томе оригинала в область снимка копируется не измененная версия блока. В случае изменения самого снимка в его область помещаются его собственные измененные данные. Т.е. расход дискового пространства у снимка минимальный. С точки зрения LVM от выглядит как логический том, а с точки зрения ОС — является блочным устройством и может быть смонтирован.
Данный факт позволяет создать снимок виртуального тома, на котором расположены контейнеры и выполнить долгое резервное копирование. Для этого сперва выполним остановку или заморозку контейнеров (второе предпочтительнее), создадим снимок и вновь запустим контейнеры. После чего смонтируем снимок, выполним архивацию контейнеров, отмонтируем снимок и уничтожим его.
Примером реализации такого подхода на практике может быть следующий скрипт.

Код: (Bash)
#!/bin/sh

BACKUPROOT=/mnt/backup
BACKUPSUBDIR=`date '+/%F (%H%M)'`
BACKUPDIR=$BACKUPROOT$BACKUPSUBDIR

OVZLV=vg0/ovz
OVZSUBDIR=/vz

SNAPLV=vg0/ovz_snap
SNAPPV=/dev/md5
SNAPDEV=/dev/$SNAPLV
SNAPMOUNT=/mnt/ovz_snap

modprobe vzcpt
modprobe vzrst
sync

mkdir -p "$BACKUPDIR"

declare -a VEID
N=0

for IN in `vzlist -o ctid|tail -n +2|sed 's/ //g'`
do
    VEID[$N]=$IN
    N=$(($N+1))
done

for IN in ${VEID[*]}
do
    echo "*** Create checkpoint for VE $IN."
    vzctl chkpnt $IN
done

echo "*** Create snapshot."
lvm lvcreate -s $OVZLV -L 1G -n $SNAPLV $SNAPPV

for IN in ${VEID[*]}
do
    echo "*** Restore checkpoint for VE $IN."
    vzctl restore $IN
done

echo "*** Mount snapshot."
mount -o ro $SNAPDEV "$SNAPMOUNT"
cd "$SNAPMOUNT$OVZSUBDIR/private"

for IN in ${VEID[*]}
do
    echo "*** Make tar for VE $IN."
    cp /etc/vz/conf/$IN.conf "$BACKUPDIR/"
    cp $SNAPMOUNT/vz/dump/Dump.$IN "$BACKUPDIR/"
    tar -cf "$BACKUPDIR/$IN.tar" $IN
done

echo "*** Unount snapshot."
cd /
umount "$SNAPMOUNT"

echo "*** Remove snapshot."
lvm lvremove -f $SNAPLV

for IN in "$BACKUPDIR"/*.conf "$BACKUPDIR"/Dump.* "$BACKUPDIR"/*.tar
do
    echo "*** Run background compression for $IN."
    bzip2 -9 "$IN" &
done

echo "*** Wait for child processes..."
wait

echo "*** Backup completed."

Т.к. современные процессоры содержат в себе по нескольку физических ядер, то архивацию можно запустить параллельно. Для того, чтобы скрипт завершился только после окончания всех фоновых процессов я использовал команду wait.
На сервере с тремя не сильно нагруженными контейнерами время с момента заморозки и до восстановления контейнеров составило считанные секунды, что с точки зрения web-клиента выглядело как маленькая задержка в загрузке страницы. Для систем со множеством контейнеров такой подход может вызвать более долгую остановку. В этом случае можно применить последовательное индивидуальное копирование для каждого контейнера: остановить очередной контейнер, создать снимок виртуального тома, запустить контейнер, смонтировать снимок, выполнить предварительную архивацию (создание tar-архива), освободить снимок и запустить сжатие tar-архива на фоне. Дабы избежать перегрузки сервера стоит ограничить количество одновременных фоновых процессов, например, половиной доступных ядер процессора.
Версия для печати
Обсудить на форуме (1)