И тут то все четко начинают понимать, что нужны резервные копии (много, разных, в разных местах). Т.е. правило 3-2-1, придуманное и описанное Peter-ом Krogh-ом, весьма желательно выполнять. Данная статья – пример, который помогает сделать реальным выполнение данного правила на «коленке» — без покупки дорогостоящего оборудования (в условиях жесткой экономии).
Итак – условия решаемой задачи:
• Есть небольшая среда виртуализации от Vmware (пара-тройка ESXi-серверов, vCenter, самый дешевый пакет лицензий – начальный Kit – в целом это не важно для данной статьи. Аналогично статья подойдет и для Hyper-V);
• Есть с десяток виртуальных машин, содержимое которых не хочется потерять в случае отработки автоматизированным Ransomware скриптом;
• Есть система резервного копирования от Veeam (бесплатная редакция, бекапы делаются с помощью PowerShell и Task Schedule).
Задачи:
• Делать резервные копии серверов 1 раз в день по ночам;
• Размножать копии (копировать на NAS-сервер с FreeBSD + ZFS). К слову, на ZFS тоже делаются снапшоты, которые автоматически удаляются по заданному расписанию (zfSnap + Cron);
• Иметь оффлайновую копию «бекапов» на съемном носителе.
Реализация:
Так как основной сервер, который делает резервные копии из работающих виртуальных машин, управляется операционной системой Windows Server (ввиду того, что Veeam Backup работает пока что только на базе этой ОС), было решено для реализации задач использовать PowerShell.
Решение задачи синхронизации бекапов между основным сервером (Windows) и NAS-сервером (FreeBSD):
Для решения задачи требовался скрипт, который бы запускался через Task Scheduler и синхронизировал каталог A с сетевым ресурсом B, доступным через протокол SMB. Вначале я попробовал использовать robocopy – но тесты показали весьма низкую скорость работы полученного скрипта. И я решил реализовать данный скрипт на другом инструменте.
Пятиминутный поиск и 10 минут тестов показали наличие весьма жизнеспособного и готового решения: powershell-synchronizing-a-folder
Скрипт оказался шикарным:
• Работает как с локальными дисками, так и с сетевыми ресурсами;
• Позволяет исключать определенные файлы из задачи;
• Позволяет синхронизировать файлы по заданному шаблону
• Работает на максимальной скорости (т.е. сколько железо и сеть могут выдать – с такой скоростью синхронизация и проходит, в отличие от robocopy).
В итоге на основном сервере появилась пачка заданий в Task Schedule вида:
powershell.exe "C:\Scripts\syncfolder.ps1 -SourceFolder:G:\Backups\WEBAPPS -TargetFolder:\\192.168.0.232\backups$\WEBAPPS"
И задача синхронизации резервных копий после выполнения заданий Veeam Backup была решена (2 копия с дельтой по времени).
Решение задачи создания оффлайновых резервных копий:
Сама идея проста:
• Подключаем к серверу с Veeam Backup внешний USB 3.0 жесткий диск на 2 Тб
• Большую часть времени держим его Offline (и этим мы защищаемся от автоматизированных Ransomware);
• Когда скрипт отрабатывает, он переводит диск в Online, делает каталог с текущей датой, копирует в него текущие резервные копии, и по окончании выполнения снова переводит диск в Offline.
Реализация:
Отправной точкой служит команда: Get-Disk – нам нужно понять, какие диски у нас есть в системе и виден ли нам внешний USB-диск:
PS C:\Windows\system32> Get-Disk
Number Friendly Name OperationalStatus Total Size Partition Style
------ ------------- ----------------- ---------- ---------------
1 WDC WD30PURX-64P6ZY0 Online 2.73 TB GPT
0 WDC WD10EZEX-60M2NA0 Online 931.51 GB GPT
2 WD Elements 25A3 USB Device Offline 1.82 TB GPT
Теперь нам нужно поместить ссылку на USB-диск в переменную. Для его идентификации предлагается использовать атрибут «Friendly Name». Если Вы предпочитаете использовать другие атрибуты – выведите полный список (get-disk | select *). Либо посмотрите список доступных свойств и методов (get-disk | get-member).
Итого первая часть скрипта:
# Find USB disk by FriendlyName
$mybackupdisk = get-disk | where {$_.FriendlyName -like 'WD Elements 25A3 USB Device'}
Далее – нужно перевести диск из Offline в Online, а также убедиться, что диск в режиме Read-Write (иногда, по невыясненной причине, диск после перехода в Online становился Read-Only. Для выяснения номера диска используем свойство Number ($mybackupdisk.Number).
Получаем кусок:
# Make disk Online
Set-Disk -Number $mybackupdisk.Number -IsOffline $False
Start-Sleep -s 5
# Make disk Writeable (some times it ReadOnly after online - shit happens...)
Set-Disk –Number $mybackupdisk.Number -IsReadonly $False
Start-Sleep -s 5
Для идентификации буквы диска сделаем следующий финт – на USB диск повесим метку (имя): VMUSBBACKUPS (либо через Disk Manager, либо с помощью команды Set-Volume).
Далее – с помощью команды Get-Volume определяем букву подключенного USB-диска (после перевода его в Online):
# Find Disk Volume
$usbvolumename = Get-Volume | where {$_.FileSystemLabel -like 'VMUSBBACKUPS'}
И собственно само копирование нужных данных на диск:
Создаем каталог с текущей датой в имени:
$date = Get-Date
$newbackupfolder = $date.ToString("yyyy-MM-dd")
# Full Backup Fath
$createdirfullpath = $usbvolumename.DriveLetter + ":\" + $newbackupfolder
# Create Backup Directory
New-Item -ItemType directory -Path $createdirfullpath -Force -Confirm:$false
Start-Sleep -s 2
Копируем резервные копии:
# Source Backup Dir (with backups)
$sourcebackup = "F:\Backups\VCENTER\"
# Copy to USB from Disk
Copy-Item $sourcebackup -Destination $createdirfullpath -Recurse
Start-Sleep -s 5
Другой вариант – когда нам нужно не создавать каждый раз новые каталоги и копии – а переписывать файлы новыми версиями – тогда используем уже ранее найденный скрипт для синхронизации каталога А с Б:
# Sync from HDD to USB:
C:\Scripts\syncfolder.ps1 -SourceFolder:F:\Backups\ -TargetFolder:$usbvolumename.DriveLetter:\VMsStart-Sleep -s 5
В любом случае – когда Вы закончите копировать либо синхронизировать, весьма желательно сбросить кэш операций (из ОЗУ на HDD/USB) командой:
# Write USB Disk Cache before offline
Write-VolumeCache $usbvolumename.DriveLetter
Start-Sleep -s 5
И не забыть снова перевести диск из Online в Offline:
# Place USB to Offline
Set-Disk -Number $mybackupdisk.Number -IsOffline $True
Результаты:
• Получили резервные копии в трех местах (Windows-сервер, FreeBSD-сервер, USB-диск);
• Два вида хранения (в шарах и на диске);
• Один носитель другого типа – отсуждаемый. Можно вообще иметь пару дисков – и просто 1 или 2 раза в месяц менять их местами (один в сейф). Так как USB-диск в режиме Offline 95% времени – его всегда можно безболезненно выдернуть из сервера.
Моя статистика:
• данная схема работает уже 6 месяцев без сбоев;
• объем синхронизируемых данных (сжатые и дедуплицированные бекапы – от 500 до 700 Гб);
• Время синхронизации на USB-диск – 1 час 20 минут в среднем (1 раз в неделю в выходные).
Полные скрипты можно скачать с Google Disk: BackupExamples
Комментарии (18)
Dorlas
31.05.2017 17:56Скрипт проверяет при синхронизации хеши файлов.
А вот то, что сделал бесплатный Veeam Backup — увы, не проверяется никак (автоматически).
Пока решили ручным способом 1 раз в квартал тестировать бекапы (восстанавливать виртуалки в отдельный vSwitch и тестировать.Dorlas
31.05.2017 18:09А вообще, есть все необходимые инструменты для того, чтобы написать скрипт для автоматической проверки:
1) PowerShell модули в бесплатном Veeam чтобы восстановить виртуалки с новыми именами
2) PowerCLI к ESXi/vCenter, чтобы изменить им vSwitch и запустить их после восстановления
3) Организовать проверку запущенных виртуалок с помощью опроса IP-адресов, служб и т.д. (PowerShell скорее всего тоже — типа HTTP GET, ping и т.д.)
Возможно в будущем эта идея найдет практическую реализацию )
kxl
31.05.2017 18:27слабое место — подключаемый диск все равно виден целиком и, если зловред уже в системе, то он, как правило успевает зашифровать файлы, пусть не все сразу, но постепенно… ещё вопрос — получится ли отсоединить диск после бекапа, если на нем будут открыты файлы (антивирусом или зловредом)?
Dorlas
31.05.2017 18:34Тогда уж лучше забирать с FTP (ставить на сервер с Veeam FTP-службу — например FileZilla FTP Server) и по расписанию с него забирать бекапы. Но да — идея хорошая.
Есть еще надежда на ZFS и его снапшоты (делаются каждый день, удаляются ротацией через 14 дней).
Если «зловред» будет шифровать махом и все разом — в снапшотах на ZFS будут оригинальные файлы.
В общем надежда на гибридный подход — что все «преграды» разом не обойдут (особенно автоматизированный скрипт — не человек).
ClearAirTurbulence
31.05.2017 19:41Остается слабое место — постоянно подключенный внешний диск. Есть риск вывода его из строя в случае сбоя питания компьютера. Риск, понятное дело, невелик, но он есть.
ChampionLoo
01.06.2017 02:44Во всём есть слабое место, поэтому и сохраняют копии в трёх местах. Простите, конечно, но комментарий будто ради комментария писался.
pnetmon
31.05.2017 22:00А не проще заместо подключения диска использовать другой компьютер у которого отключается сетевой интерфейс?
Dorlas
01.06.2017 02:49Тоже рабочий вариант как мне видится. Но тогда уж лучше заморочиться с WakeONLan и расписанием включения, синхронизации с последующим выключением.
Иначе это просто лишняя трата электроэнергии.
aik
01.06.2017 02:41+1синхронизировал каталог A с сетевым ресурсом B, доступным через протокол SMB
Здесь иногда выплывает подводный камень с длинными русскими именами. За фрю не поручусь, а вот когда сервер на линуксе, то файлы с именами длиннее 127 символов не копируются без серьезных танцев с бубном (типа перехода нa reiserfs, к примеру).durnoy
01.06.2017 10:49Да, это беда. В протоколе SMB ограничение на длину имени файла 255 символов, которые есть UTF-16 code units — опять же определено протоколом, а в Линуксе у обычных файловых систем — это 255 байт, которые обычно UTF-8.
aik
01.06.2017 11:12В протоколе SMB ограничение на длину имени файла 255 символов
Скорее в NTFS, чем в протоколе.
В линуксе для решения проблемы можно либо перейти на упомянутый reiser4, либо поменять локаль на однобайтовую (и получить другие проблемы), либо попробовать пропатчить ядро на тему длины имени файла.
Lelik13a
01.06.2017 06:38Необходимо обрабатывать коды возврата вызываемых утилит.
А так же желательно слать отчёты о бекапах на почту, особенно, если что не так.
И полезно проверять размеры получившихся бекапов на адекватность.
varnav
01.06.2017 15:44Бекаплю целиком только два legacy сервера.
Остальное сделано иначе — бекапятся только данные (duply/duplicity на Amazon S3), развёртывание нового сервера с помощью скрипта (даже Ansible не нужен) делается быстрее чем восстановление его из бекапа.
keenx
Спасибо большое! Очень нужная статья. Такое решение давно зрело в уме, теперь можно перейти к действиям.