Резервное копирование по SSH
Сервер резервного копирования
Генерируем на системе, которая будет осуществлять резервное копирование, пару SSH-ключей:
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/stupin/.ssh/id_rsa):
Created directory '/home/stupin/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/stupin/.ssh/id_rsa.
Your public key has been saved in /home/stupin/.ssh/id_rsa.pub.
The key fingerprint is:
97:98:ec:fd:76:f7:ff:a7:e7:e1:39:ad:34:e8:86:8c stupin@fstu
The key's randomart image is:
+--[ RSA 2048]----+
| |
| |
| |
| . o . |
| S o |
| . o . |
| .o... o..|
| E ooo.ooB|
| oo.oO@|
+-----------------+
В домашнем каталоге пользователя, в подкаталоге .ssh будут созданы файлы ключей id_rsa и id_rsa.pub.
Первый ключ - приватный, с его помощью будет осуществляться аутентификация сервера резервного копирования на резервируемых системах. Не следует хранить этот ключ где-бы то ни было, кроме компьютера, занятого резервным копированием. Сам этот компьютер желательно выделить только для целей резервного копирования и не запускать на нём никаких сервисов, потому что взломав уязвимый сервис взломщик получит доступ к приватному ключу, к резервируемым системам и к резервным копиям этих систем. Думаю, что не стоит объяснять, чем это может быть чревато.
Второй ключ можно свободно размещать в публично, т.к. с его помощью нельзя попасть на компьютер, а можно лишь разрешить подключаться компьютеру, обладающему приватным ключом.
Резервируемые системы
Создаём на удалённой системе пользователя, от имени которого будет производиться резервное копирование:
# useradd -c "User for backup purposes" -d /home/rbackup -U -m -s /bin/sh rbackup
# mkdir /home/rbackup/.ssh
# chown rbackup:rbackup /home/rbackup/.ssh
# cat <<END > /home/rbackup/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwsITVgCQrwuSC0cNA8c/TCIkJ0U0vT3bf8d1hoVzTOP8WtdRfGdPqGoo5+f8iudtSZN+8EokEk+ZfvE4fs020jG3Y86dL7roVGx+fuDcxCdpIlI/PVJOAK/o/V7z9xOjqbP0iFkqp6YYojH+b7ixqw1mUC5zksXqdXsW7RF6PDZ5dlSyqW5/55J3+UZ8Gl5isGEAdcLfT3PF6OcYbyLLsWzlKTKTRobuS01I1h1FuMl1IA0MLXlGCY+yWJk71cQV+kaePhSCXyOIiSAxvMsQpME+Z3quW9h8p5H9I9jXz2I9Ybms/tTTCAg6kvnbGxkzU26yNV7seIdUwiN3/tssh rbackup@srv.domain.tld
END
# chown rbackup:rbackup /home/rbackup/.ssh/authorized_keys
Текст от ssh-rsa и до rbackup@srv.domain.tld следует взять из файл сгенерированного публичного ключа ~/.ssh/id_rsa.pub
.
Теперь установим на резервируемой системе sudo:
# apt-get install sudo
И разрешим при помощи команды visudo пользователю rbackup выполнять несколько команд:
rbackup ALL=(ALL) NOPASSWD:/usr/bin/rsync --server --sender -vlogDtpre.iLsf . /mnt/, \
/usr/bin/rsync --server --sender -logDtpre.iLsf . /mnt/, \
/sbin/lvdisplay --noheadings -Co lv_size /dev/vg0/*, \
/sbin/lvcreate -L1G -n /dev/vg0/copy -s /dev/vg0/*, \
/sbin/lvremove -f /dev/vg0/copy, \
/bin/mount /dev/vg0/copy /mnt, \
/bin/umount -f /mnt
Команды позволяют сделать снимок LVM-раздела, смонтировать его, скопировать его содержимое, а затем демонтировать и удалить его. В примере предполагается, что на удалённой системе есть только одна группа томов - vg0, снимок всегда будет иметь название copy, а для хранения изменяющихся экстентов основного том LVM будет выделен 1 гигабайт. Если раздел на удалённой системе в процессе резервного копирования будет интенсивно изменяться, выделенного гигабайта может не хватить. В этом случае снимок может досрочно удалиться и резервное копирование завершится ошибкой. При необходимости измените это значение, если разделы на ваших удалённых системах большие и интенсивно меняются.
Не забудем также добавить при помощи visudo опцию, разрешающую запускать команды через sudo скриптам, работающим без виртуального терминала:
Defaults !requiretty
Скрипт резервного копирования разделов
Скрипт удалённого резервного копирования LVM-томов с удалённой системы виртуализации Xen будет иметь следующий вид:
#!/bin/sh
backup()
{
# Удалённых сервер виртуализации и хост на нём
XEN=$1
HOST=$2
# Исходный LVM-раздел и его снимок
SDISK=/dev/vg0/$HOST-disk
SSNAP=/dev/vg0/copy
# Целевой LVM-раздел и его снимок
TDISK=/dev/vg0/$HOST-disk
TSNAP=/dev/vg0/$HOST-disk-new
printf "%-20s %-15s " $XEN $HOST
# Готовим снимок на удалённой системе, заодно узнавая его раздел
size=`/usr/bin/ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa_backup rbackup@$XEN " \
/usr/bin/sudo /bin/umount -f /mnt >/dev/null 2>/dev/null ; \
/usr/bin/sudo /sbin/lvremove -f $SSNAP >/dev/null 2>/dev/null ; \
/usr/bin/sudo /sbin/lvdisplay --noheadings -Co lv_size $SDISK 2>/dev/null && \
/usr/bin/sudo /sbin/lvcreate -L1G -n $SSNAP -s $SDISK >/dev/null 2>/dev/null && \
/usr/bin/sudo /bin/mount $SSNAP /mnt >/dev/null 2>/dev/null"`
if [ $? -ne 0 ]
then
echo "Cannot prepare snapshot"
/usr/bin/ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa_backup rbackup@$XEN " \
/usr/bin/sudo /bin/umount -f /mnt >/dev/null 2>/dev/null ; \
/usr/bin/sudo /sbin/lvremove -f $SSNAP >/dev/null 2>/dev/null"
return 1
fi
# Готовим локальный раздел
/bin/umount -f /mnt >/dev/null 2>/dev/null
/sbin/lvremove -f $TSNAP >/dev/null 2>/dev/null
if [ -e $TDISK ]
then
/sbin/lvcreate -L1G -n $TSNAP -s /dev/vg0/$2-disk >/dev/null 2>/dev/null && \
/bin/mount $TSNAP /mnt >/dev/null 2>/dev/null
else
/sbin/lvcreate -L$size -n $TSNAP >/dev/null 2>/dev/null && \
/sbin/mkfs.ext4 $TSNAP >/dev/null 2>/dev/null && \
/bin/mount $TSNAP /mnt >/dev/null 2>/dev/null
fi
if [ $? -ne 0 ]
then
echo "Cannot prepare target partition"
/bin/umount -f /mnt >/dev/null 2>/dev/null
/sbin/lvremove -f $TSNAP >/dev/null 2>/dev/null
return 1
fi
# Копируем снимок с удалённой системы на локальный раздел
/usr/bin/rsync -e '/usr/bin/ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa_backup' \
--rsync-path="/usr/bin/sudo /usr/bin/rsync" \
-a rbackup@$XEN:/mnt/ /mnt/
if [ $? -ne 0 ]
then
echo "Cannot copy snapshot"
/sbin/lvremove -f $TSNAP >/dev/null 2>/dev/null
return 1
fi
/usr/bin/rsync -e '/usr/bin/ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa_backup' \
rbackup@$XEN:/etc/xen/$HOST.cfg /etc/xen/$HOST.cfg
if [ $? -ne 0 ]
then
echo "Cannot copy config"
return 1
fi
# Подчищаем всё за собой на удалённой системе
/usr/bin/ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa_backup rbackup@$XEN " \
/usr/bin/sudo /bin/umount -f /mnt >/dev/null 2>/dev/null ; \
/usr/bin/sudo /sbin/lvremove -f $SSNAP >/dev/null 2>/dev/null"
# Подчищаем всё за собой на локальной системе
/bin/umount -f /mnt >/dev/null 2>/dev/null
if [ -e $TDISK ]
then
/sbin/lvconvert --merge $TSNAP >/dev/null 2>/dev/null
else
/sbin/lvrename $TSNAP $TDISK >/dev/null 2>/dev/null
fi
echo "OK"
return 0
}
date "+%Y-%m-%d %H:%M:%S"
backup xen1.domain.tld mon1
backup xen1.domain.tld db1-mon
backup xen1.domain.tld configs
backup xen1.domain.tld info-db
backup xen2.domain.tld mon2
backup xen2.domain.tld db2-mon
backup xen2.domain.tld mgw
backup xen2.domain.tld info
date "+%Y-%m-%d %H:%M:%S"
Этот скрипт копирует разделы и конфигурацию восьми виртуальных машин с двух серверов виртуализации Xen. При необходимости можно переделать скрипт под другие нужды. При первом запуске скрипт копирует снимок в новый раздел, а при последующих запусках копирует снимок в снимок при помощи rsync, поэтому время резервного копирования должно быть минимальным.