Posted: 2013-08-02 in IT, Software
Метки:

Я давно хотел написать статейку про резервное копирование, да и читатели моих заметок, если мне не изменяет память, хотели услышать моё мнение по этому поводу. Зачем делать бэкапы — красочно описано в предыдущем посте. Я же опишу, как на мой взгляд можно организовать систему резервного копирования и разграничения доступа. …

Я не просто так упомянул про разграничение доступа. Надо чётко понимать, что бэкапная система имеет повышенные привилегии, позволяющие иметь доступ ко всем данным, подлежащим резервированию. Малейшая ошибка в доступе — и вот хакнутая или просто сглючившая бэкап-система пошла крушить ваши файлы и их резервные копии, до которых удастся добраться в rw-режиме. Поэтому данному вопросу будет уделено особое внимание.

Я принципиально не буду касаться организационно-бумажных вопросов. Да, есть куча умных книжек и не менее умных рекомендаций, в которых расписано, какие политики и регламенты должны быть разработаны, сколько заместителей должно быть у «Security Officer» для контроля местечкового хаоса и кто за что отвечает. На практике позволить себе хорошо организованную безопасность и документирование могут лишь очень немногие компании, и если у вас именно так — я очень за вас рад. В большинстве компаний ничего подобного нет, и бэкапы часто не делаются вообще. И если вам досталась такая хаотичная сеть — то сперва надо настроить хоть какое-то резервирование, хотя бы самых критичных данных, а бумаги писать потом. Лучше пожить ещё немного в хаосе, но с бэкапами, чем с детальным бумажным регламентом о бэкапах, но без единой живой копии этих самых данных после какого-нибудь инцидента.

Также я не буду рассматривать сильно экзотические случаи, типа бэкапа прошивок кривых контроллеров, особенностей работы с терабайтными базами, тонкости бэкапов баз данных с репликацией и прочей жути, где общие советы и решения «из коробки» встречаются не всегда и каждый случай часто бывает индивидуален.

Итак, поехали.

Сперва я хотел бы поговорить о том, как организовывать бэкапы в плане софтовой части. Тут есть два подхода — либо упор на встроенные средства (скрипты/средства ОС), либо использование специализированного софта. Спецсофта для бэкапов ОЧЕНЬ много, их сравнение и обзор — тема для отдельных обзоров. Разработчики такого софта часто обещают золотые горы, на на деле все оказывается вовсе не так радужно. Первый, и самый неприятный недостаток — это отдельный софт, то есть отдельная администрируемая единица. Которую надо ставить, обновлять, развертывать и обслуживать. Кроме того, как бы ни были мощны такие системы, охватить все сервисы и платформы все равно невозможно, да и всегда найдется такой сервис, для правильного резервирования которого допустимы только собственные средства или свои особые костыли. Например, MS AD и различные СУБД бэкапить нужно только встроенными, специально предназначенными для этого средствами. Запросто может оказаться, что ваша спецфсофтина для бэкапа не поддерживает тот или иной сервис. Смысл и идея резко теряются. Кроме того, сильно централизованная единая система управления бэкапами легко может стать точкой отказа.

Так что я больше склоняюсь к первому варианту — когда по максимуму используются встроенные средства. То есть сперва бэкапы делаются на локальной системе в обычные файлы. После чего эти файлы вытаскиваются сервером хранения бэкапов по сети. Это позволит нам при организации бэкапов абстрагироваться от того, что именно мы бэкапим. Когда число подконтрольных серверов достигает хотя бы 20 — это становится важным.

Общая идея такая: на каждом сервере есть локально хранящийся бэкап, который делается средствами тех систем, что на сервере установлены. На контроллере домена это будет ntbackup, на сервере СУБД — всякие *sql-дамперы, на сервере ejabberd — jabberctl, на файловом сервере — скрипт архивации, а на сервере виртуальных машин — средства для снятие образов и создания снапшотов. Каждый такой сервер должен обновлять этот бэкап автономно, делать простейшую ротацию и выкладывать для доступа в режиме «тольк чтение» по отдельно обговоренному протоколу и для специального пользователя. Я для этих целей рекомендую использовать SSH. Авторизация, естественно, по ключам, передача файлов там есть, и этот протокол реализован почти под все платформы. Кроме того, вам может потребоваться бэкапить сервер, стоящий на другом континенте, и организация полноценного впн до которого может быть затруднена. Да и мутить полноценный впн только для бэкапов —
перебор и неоправданное усложнение.

Ключевые идеи: 1). Серверу не нужно знать, что за систему бэкапа мы используем. 2). Сервер предоставляет доступ к бэкапам в режиме «только чтение» пользователю backuper только при предъявлении валидного ключа. 3). ротация локального бэкапа делается самим сервером, и с самих бэкап-серверов напрямую не управляется.

Приведу поясняющую схему:
В нашем примере есть два сервиса — файловая помойка и учетная система. И два сервера для бэкапов, которые размещены как минимум в разных зданиях. Это позволяет сохранить данные даже при многих чрезвычайных обстоятельствах. На каждом из бэкапных серверов создается пользователь backuper, который собственно и будет ходить по другим серверам и собирать с них бэкапы в свое хранилище. Для этого на каждом сервере генерируем ключевые пары, естественно без паролей (это ключи для автологина, пароли в 2 часа ночи вводить будет некому). А вот на длине ключа экономить не нужно. Смело ставим RSA в 4096 бит. Если у вас паранойя, и все подконтрольные сервера способны авторизовать ключи большей длины — можно поставить больше. Я делал ключ RSA длиной 8192 бит, работает.

[backuper@Backup1 ~]$ ssh-keygen -b 8192
Generating public/private rsa key pair.
Enter file in which to save the key (/home/backuper/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/backuper/.ssh/id_rsa.
Your public key has been saved in /home/backuper/.ssh/id_rsa.pub.
The key fingerprint is:
84:ed:ef:5a:a5:6f:84:7c:bc:d1:1c:20:48:27:e1:d9 backuper@Backup1
The key's randomart image is:
+--[ RSA 8192]----+
|       .+o.      |
|       +.=. .    |
|      . = E. .   |
|       o      .  |
|        S. o.o . |
|         .oo= o  |
|          +o o   |
|         o .o    |
|        .....    |
+-----------------+

Важный момент — методы доступа. Я рекомендую для всех пользователей, имеющих отношение к бэкапам, оставить только метод доступа по ключам. Важно, чтобы ключи у каждого сервера были свои.

После чего на каждом сервере сбора бэкапов размещаем вот такой несложный скрипт:

[backuper@Backup1 ~]# cat /home/backuper/backup_All.sh
#!/bin/bash

date=`date "+%Y_%m_%d"`;             # current date  [YYYY_mm_dd]
days_store='10';                     # Number of backups (N last days)
dir_open=/Backups/                   # directory for store backups
sftp_bin='/usr/bin/sftp -i /home/backuper/.ssh/id_rsa -r ';

mkdir $dir_open/$date
cd $dir_open/$date && mkdir FileServ1 ERP_Serv1

echo "   ...BackUp All servers ...";
$sftp_bin   FileServ1.local:/usr/BACKUP/$date/*  $dir_open/$date/FileServ1
$sftp_bin   ERP_Serv1.local:/Backups/$date/*     $dir_open/$date/ERP_Serv1

echo '   ... Delete old backups ...';
find $dir_open -mtime +$days_store -delete  # store backups for N last days

cp /home/backuper/backups.log            $dir_open/$date
echo "   ... Complete !nn";

и не забываем прописать его в планировщик:

[backuper@Backup1 ~]# crontab -l
0 5 * * * /home/backuper/backup_All.sh > /home/backuper/backups.log

Обратите внимание: один сервер — одна строчка. Имя или адрес сервера, путь к каталогу, откуда дергать бэкап конкретного сервера, можно опцией указать порт. Что будет в бэкапе от сервера — определяется на самом сервере. Всё. В 5 утра скрипт зайдет на оба сервера и скачает с них бэкапы, после чего сделает ротацию.

Теперь про настройку собственно рабочих серверов.
Ставим туда SSH-сервер, создаем учетную запись backuper и прописываем для неё авторизацию по ключам. В список разрешенных ключей вписываем открытые части ключей, сгенерированных на бэкапных серверах. Можно воспользоваться готовой утилитой ssh-copy-id.
На каждом сервере размещаем скрипт, делающий бэкап локально, например такой:

[root@FileServ1 ~]# cat /root/backup_FileServ1.sh
#!/bin/bash

date=`date "+%Y_%m_%d"`;             # current date
days_store='12';                     # Number of backups (N last days)
dir_open=/usr/BACKUP                 # directory for store backups
tgz_bin='tar --gzip -cf ';           # Tar/GZip binary + options


mkdir $dir_open/$date

cd $dir_open/$date
$tgz_bin home_systems.tgz /root /home/backuper
$tgz_bin home_buh.tgz /home/buh
$tgz_bin home_public.tgz /home/public
$tgz_bin FilseServ1_etc.tgz /etc /var/spool/cron
cd $dir_open/$date && sha256sum * > _FileServ1.sha256

echo 'Delete old backups ...';
find $dir_open/ -mtime +$days_store -delete # store backups for N last days

и такой:

[root@ERP_Serv1 ~]# cat /root/backup_ERP_Serv1.sh
#!/bin/bash

date=`date "+%Y_%m_%d"`;             # current date
days_store='8';                      # Number of backups (N last days)
dir_open=/Backups                    # directory for store backups
tgz_bin='tar --gzip -cf ';           # Tar/GZip binary + options
mysqldump_bin='/usr/bin/mysqldump --defaults-extra-file=/root/mysqlс.cnf';


mkdir $dir_open/$date

cd $dir_open/$date
$tgz_bin home_systems.tgz /root /home/backuper
$tgz_bin www.tgz /var/www/html
$tgz_bin ERP_Serv1_etc.tgz /etc /var/spool/cron

$mysqldump_bin --databases mysql | gzip -c > _mysql_sys.gz
$mysqldump_bin --databases crm | gzip -c > _mysql_crm.gz

cd $dir_open/$date && sha256sum * > _ERP_Serv1.sha256

echo 'Delete old backups ...';
find $dir_open/ -mtime +$days_store -delete # store backups for N last days

Опция defaults-extra-file нужна для того, чтобы пароль пользователя БД не отсвечивал в списке процессов ни секунды. Содержимое mysqlс.cnf :

[root@ERP_Serv1 ~]# cat /root/mysqlс.cnf
[client]
host=localhost
port=3306
user=backuper
password=TutMnogaBuk0FF-dlya-Pa$$W0RD@

После чего на этих самых серверах права доступа к каталогам с бэкапами прописываются таким образом, чтобы пользователь backuper мог только заходить в каталоги и читать файлы.

Для добавления нового сервера достаточно, чтобы там был рабочий локальный бэкап и SSH-сервер. Просто создаем там пользователя backuper, прописываем туда открытые части ключей с тех бэкап-серверов, которые должны будут скачивать себе бэкапы, и на каждом бэкапном сервере добавляем по одной строчке в backup_All.sh

Теперь допустим, что нам надо помимо серверов бэкапить какую-нибудь железку. Если на ней есть SSH-сервер с авторизацией по ключам, то всё тривиально — в backup_All.sh добавляем вот такие строчки:

echo "show configuration" | ssh 10.9.0.8 > $dir_open/$date/mx80.conf

Кусочек конфига джунипера для такой красоты также красив:

system {
    login {
        user backuper {
            full-name "for backup";
            authentication {
                ssh-rsa "ssh-rsa AAAA<backuper@Backup1-PubKeyData>BBB";
                ssh-rsa "ssh-rsa AAAA<backuper@Backup2-PubKeyData>BBB";
            }
        }
    }
}

Основная идея, думаю, понятна. Обратите внимание — по паролю backuper зайти на маршрутизатор не может.
Ещё важный момент — ограничение доступных действий. Бэкапному юзеру нужен доступ к ровно одной команде — show configuration.
Даём такие команды:

set system login user backuper class backuper

set system login class backuper permissions secret
set system login class backuper permissions security
set system login class backuper permissions view-configuration
set system login class backuper allow-commands "(show configuration)"
set system login class backuper deny-commands "(clear)|(file)|(file show)|(help)|(load)|(monitor)|(op)|(request)|(save)|(set)|(start)|(test)"
set system login class backuper allow-configuration show
set system login class backuper deny-configuration all

Это позволит юзеру backuper только получить конфиг (включая отпечатки ключей, парольные хэши и прочие SECRET DATA), но не даст ему ничего изменить, ребутнуть железку или сделать ещё какое-либо незапланированнео зло.

Если же железка не умеет SSH — то можно вызвать вспомогательный телнет-скрипт. Например, с каталистов бэкап можно снять вот так (то есть одна строка на железку в скрипте на бэкап-сервере):

cd /home/backuper/сisco-script
./cisco-telnet.pl 3750.cfg "show running-config" > $dir_open/$date/3750-run.conf

Содержимое вспомогательных файлов:

[backuper@Backup1 ~]# cat /home/backuper/cisco-script/cisco-telnet.pl
#!/usr/bin/perl

use Fcntl;
use Net::Telnet::Cisco;

if (!$ARGV[1]) { print "Usage: cisco-backup.pl <config> <command>
    Config: [IP] [login] [password] [enable_password]  n"; exit; }
else {
    $cmd   = $ARGV[1];
    sysopen(CFG, $ARGV[0], O_RDONLY);
    ($ip, $login, $passw, $en_passw) = split(' ', <CFG>);
}

$telnet = new Net::Telnet::Cisco (Host=>$ip) or warn "!# NO_CONNECT ".$telnet->errmsg;
$telnet->login($login, $passw) or warn "!# NO_CONNECT ".$telnet->errmsg;

if ($telnet->enable($en_passw) ) {
      @output = $telnet->cmd($cmd);
      print  @output;
} else { warn "!# Can't enable: ".$telnet->errmsg; }

$telnet->close();


# cat /home/backuper/cisco-script/3750.cfg
192.168.82.186 backuper backuper_password enable_password

Само собой, применять телнет можно только в самом крайнем случае и только внутри доверенных сетей, а для возможности такого бэкапа на каталисте должен быть добавлен пользователь. Это просто демонстрационный пример, показывающий, что так тоже можно, если по каким-либо причинам нет возможности сделать доступ по SSH-ключам.

Про бэкапы виндовс-систем я рассказывать ничего не буду. Применяемый там софт частенько зело крив, и некоторым продуктам жизнедеятельности данной экосистемы можно посвятить отдельную статью. Про настройку SSH-сервера как раз под нашу задачу у меня есть статейка: https://aminux.wordpress.com/2011/10/06/ssh-2/ . К настоящему времени OpenSSHd под виндовс качественно пофиксили, и он уже как год с лишним работает под виндами без нареканий.

Добавление нового бэкапного сервера тоже в такой схеме не сложно. Ставим систему, делаем пользователя backuper, генерим пару ключей. После чего открытую часть с помощью cluster-ssh добавляем на все сервера, с которых надо лить бэкапы на новый сервер. Ну и шаблонный скрипт не забыть скопировать и прописать.

Естественно, надо попробовать залогиниться на сервера пользователем backuper, чтобы убедиться, что идентификации серверов корректно добавились в known_hosts.

Также надо быть внимательным с расписанием заданий. У меня применяется такая логика:
— все рабочие сервера начинают писать локальные бэкапы сразу после полуночи
— к часу ночи последний локальный бэкап записан
— дается защитный интервал в 4 часа (мало ли что)
— в 5 утра первый бэкапный сервер делает обход
— второй защитный интервал
— в 7 утра второй бэкапный сервер делает обход
Понятно, что если у вас есть очень долгие операции, не укладывающиеся в подобные временные рамки — то такие случаи надо рассматривать отдельно.

Что мы получили в конечном итоге:
1). Отказ сети не означает потерю бэкапов, как минимум локальные файлы должны остаться.
2). Рабочие серверы не могут испортить данные на серверах с бэкапами.
2а). Если рабочий сервер не порутали — то и локальные бэкапы не испортишь.
3). Бэкапный сервер не может испортить данные на рабочих серверах или на другом бэкапном сервере.
4). Не надо озадачиваться дополнительной защитой передаваемых по сети данных.
5). Вся схема осталась простой и прозрачной.
6). SSH без проблем проходит через NAT, чего нельзя сказать про какой-нить впн на PPTP или IPSec.
7). Сохраняется полный контроль над ключами.
8). Можно легко прикрутить оповещения.
9). Отказ любого из бэкап-серверов не критичен.
10). У нас есть несколько резервных копий и гибко регулируемая глубина бэкапа.

Как обычно, дельные комментарии и цитирование/репост приветствуются.

Реклама
- комментарии
  1. LokiTheGod:

    Сурьезно. Если есть желание, оформляй как статью, малость развертывай, напечатаю как статью на RSDN.

  2. Aminux:

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

  3. LokiTheGod:

    Originally posted by Aminux:

    Да ничего серьезного

    Ну как — если человек написал 3 печатных страницы при верстке 9 кеглем — значит, ему как минимум не лень было, а это уже серьезно. :)У нас все довольно просто — качаешь инсталлятор с сайта — он ставит вордовский шаблон и скрипты для преобразования в XML. заливаешь в шаблон свой текст и шлешь на mag@rsdn.ru

  4. Bradobrey:

    Систематизировано-вот это похвально!!!!Приятно почитать и взять на заметку.Вот только защитные интервалы иногда не помогали у меня- локальные бекапы иногда делались длительнее, чем нужно.Поэтому необходимо было увеличивать глубину бекапа и лишний контроль,пока система не отточится…Статью- в журналы!!!! 😉

  5. Aminux:

    Ну, у меня обычные ежедневные бэкапы делаются недолго. Самый длинный — 46 минут. С полуночи до 5 утра успеть можно. Защитные интервалы между северами нужны сугубо для того, чтобы равномернее была нагрузка на дисковую подсистему рабочих серверов. Все-таки а) выкачивается большой объем б) на приличной скорости в) грузиться сеть при этом.

  6. Aminux:

    Originally posted by LokiTheGod:

    Originally posted by Aminux:

    Да ничего серьезного

    Ну как — если человек написал 3 печатных страницы при верстке 9 кеглем — значит, ему как минимум не лень было, а это уже серьезно. :)У нас все довольно просто — качаешь инсталлятор с сайта — он ставит вордовский шаблон и скрипты для преобразования в XML. заливаешь в шаблон свой текст и шлешь на mag@rsdn.ru

    ох-х-х, вордовый шаблон, инсталлятор, скрипты… Это мне надо сперва на отдельном стенде попробовать.

  7. LokiTheGod:

    Originally posted by Aminux:

    Это мне надо сперва на отдельном стенде попробовать.

    В общем, у меня все это уже настроено, могу это сделать сам.

  8. Aminux:

    Я совершенно не против, если вы утащите статью на RSDN. Только укажите адрес оригинала (URL) и мой ник, потому что я статьи иногда связываю в цепочки с другими статьями.Может хоть кто-нибудь наконец-то начнет делать бэкапы по-уму, с разграничением доступов.P.S. Если где резкие высказывания или опечатки — смело убирайте, только смысл не потеряйте =)

  9. LokiTheGod:

    Ок, тогда дальнейшее лучше мылом.

  10. LokiTheGod:

    См. почту

  11. Aminux:

    Отписался.Основная вещь при публикации — ссылка на оригинал статьи в инете обязательна.