Backup maszyn wirtualnych na Hyper-V wydaje się skomplikowany, jeśli założymy, że chcemy, żeby był wykonywany automatycznie, downtime powinien dążyć do zera i co oczywiste żeby dało się z niego odzyskać dane, jeśli pojawi się taka potrzeba. Okazuje się, że można nim bardzo łatwo zarządzać.
Wirtualizacja stała się integralną częscią środowisk informatycznych. W ferworze minimalizacji ilości maszyn fizycznych bardzo często zapomina się o tym, że hosty, na których działają wirtualizatory, to również maszyny fizyczne i tak samo jak standardowe serwery mogą ulec uszkodzeniu, a dane utraceniu (nawet mimo tego, że krytyczne dane są trzymane na bezpiecznej zewnętrznej macierzy dyskowej).
Backup maszyn wirtualnych z pozycji maszyny, na której odbywa się wirtualizacja, jest dość skomplikowaną operacją, jeśli założymy, że chcemy, żeby był wykonywany automatycznie, downtime powinien dążyć do zera i co oczywiste, żeby dało się z niego odzyskać dane jeśli pojawi się taka potrzeba. Należy dobrze przemyśleć i zaplanować to zadanie łącznie ze scenariuszami odtwarzania na tym samym bądź innym sprzęcie. Jednak przy ogólniejszym spojrzeniu jest znacznie mniej czaso- i zasobochłonny niż zarządzanie backupami wewnętrznie na każdej wirtualnej maszynie z osobna.
W dalszej częsci artykułu zaproponuję dwa rozwiązania backupów wirtualnych maszyn działających na Hyper-V. Pierwsza działa w oparciu o skrypty w PowerShellu uruchamiane przez Task Scheduler. Druga wykorzystuje Windows Server Backup wykonywujący kopie systemu operacyjnego wirtualizatora oraz maszyn wirtualnych. Obie metody można z sobą łączyć dla uzyskania optymalnego dla naszego środowiska rozwiązania.
Backup i snapshoty wykonywane za pomocą PowerShell
PowerShell jest wymarzonym narzędziem do skryptowania. Wspierają go Hyper-V Server R2 oraz Windows Server 2008 R2 w wersji Core - podobnie jak wszystkie pełne instalacje Windows Server 2008/2008 R2. Dzieki temu PowerShell stał się bardzo uniwersalnym narzędziem do zarządzania systemami w tym hostami Hyper-V.
Poniżej znajduje się pięć skryptów PS umożliwających zarządzanie backupami (export) i snapshotami maszyn działających na Hyper-V. Skrypty przygotowałem jakiś czas temu wspólnie z Norweskim MVP, Tore Lervikiem. Dwa z nich służą do backupu, kolejne dwa do wykonywania snapshotów, a ostatni do utrzymywania porządku w folderach z backupami. Świetnie nadają się do okresowego uruchamiania przez Task Scheduler, można na ich podstawie zbudować kompletne rozwiązanie do backupu maszyn działających na Hyper-V.
Wszystkie skrypty zostały wielokrotnie przetestowane i z tego co wiem, działają w kilku produkcyjnych środowiskach. Jeśli jednak znajdziesz coś, co można w nich usprawnić proszę o informację w komentarzu.
Backup wszystkich maszyn - HVbackupAll
Skrypt HVbackupAll wykonuje się kolejno dla wszystkich wirtualnych maszyn. Każdą z nich zatrzymuje, dokonuje pełnego eksportu do wskazanego dla backupu folderu ($dest), zmienia jego nazwę zgodnie z datą i czasem wykonywania skryptu, a następnie wznawia działanie maszyny. Zawartość wyeksportowanych folderów to kompletny backup wirtualnego systemu: jego konfiguracja, plik dysku, stan pamięci oraz wszystkie snapshoty.
W przypadku konieczności przywrócenia stanu maszyny z backupu należy wykonać jej import na tę samą bądź inną maszynę (przy imporcie do Hyper-V działającego na systemie o odmiennej architekturze może być konieczny restart wirtualnego komputera).
## HVbackupAll.ps1
## Create a backup of all the VM's
## to edit: $dest
##
## last edit: 8:41 PM 9/13/2009 by Karol Stilger
$dest = "F:\HVbackup\machines"
$datetime = get-date -f yyMMdd_HHmmss
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName <> Name"
foreach ($VM in [array] $ListOfVMs)
{
$VMReturnState = $VM.EnabledState
$VMName = $VM.ElementName
if (($VM.EnabledState -eq 2) -or ($VM.EnabledState -eq 32768) -or ($VM.EnabledState -eq 32770))
{
$VM.RequestStateChange(32769)
echo "Saving the state of $VMName"
}
while (!($VM.EnabledState -eq 32769) -and !($VM.EnabledState -eq 3))
{
Start-Sleep(1)
$VM = get-wmiobject -namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VMName'"
}
if ([IO.Directory]::Exists("$dest\TmpDir\$VMName"))
{
[IO.Directory]::Delete("$dest\TmpDir\$VMName", $True)
}
echo "Exporting the VM"
$status = $VM_Service.ExportVirtualSystem($VM.__PATH, $True, "$dest\TmpDir")
if ($status.ReturnValue -eq 4096)
{
$job = [Wmi]$status.Job
while (!($job.PercentComplete -eq 100) -and ($job.ErrorCode -eq 0))
{
Start-Sleep(5)
$job = [Wmi]$status.Job
echo $job.PercentComplete
}
}
## Store the files on in a temp directory before moving them to their location and then remove the old files.
if ([IO.Directory]::Exists("$dest\$VMName"))
{
[IO.Directory]::Move("$dest\$VMName", "$dest\$VMName-OldTmpDir")
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
[IO.Directory]::Delete("$dest\$VMName-OldTmpDir", $True)
}
else
{
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
}
echo "Done with $VMName"
$VM.RequestStateChange($VMReturnState)
}
rename-item $dest -newname ("$datetime All")
Backup pojedyńczej maszyny - HVbackupOne
Skrypt HVbackupOne jest modyfikacją HVbackupAll i wykonywany jest tylko dla maszyny $VMsystemName.
## HVbackupOne.ps1
## Create a backup of one VM
## to edit: $dest and $VMsystemName
##
## last edit: 12:33 PM 9/13/2009 by Karol Stilger
$dest = "F:\HVbackup\machines"
$VMsystemName = 'MyFavoriteMachine'
$datetime = get-date -f yyMMdd_HHmmss
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName = '$VMsystemName'"
foreach ($VM in [array] $ListOfVMs)
{
$VMReturnState = $VM.EnabledState
$VMName = $VM.ElementName
if (($VM.EnabledState -eq 2) -or ($VM.EnabledState -eq 32768) -or ($VM.EnabledState -eq 32770))
{
$VM.RequestStateChange(32769)
echo "Saving the state of $VMName"
}
while (!($VM.EnabledState -eq 32769) -and !($VM.EnabledState -eq 3))
{
Start-Sleep(1)
$VM = get-wmiobject -namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VMName'"
}
if ([IO.Directory]::Exists("$dest\TmpDir\$VMName"))
{
[IO.Directory]::Delete("$dest\TmpDir\$VMName", $True)
}
echo "Exporting the VM"
$status = $VM_Service.ExportVirtualSystem($VM.__PATH, $True, "$dest\TmpDir")
if ($status.ReturnValue -eq 4096)
{
$job = [Wmi]$status.Job
while (!($job.PercentComplete -eq 100) -and ($job.ErrorCode -eq 0))
{
Start-Sleep(5)
$job = [Wmi]$status.Job
echo $job.PercentComplete
}
}
## Store the files on in a temp directory before moving them to their location and then remove the old files.
if ([IO.Directory]::Exists("$dest\$VMName"))
{
[IO.Directory]::Move("$dest\$VMName", "$dest\$VMName-OldTmpDir")
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
[IO.Directory]::Delete("$dest\$VMName-OldTmpDir", $True)
}
else
{
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName")
}
echo "Done with $VMName"
$VM.RequestStateChange($VMReturnState)
}
rename-item $dest -newname ("$datetime $VMsystemName")
Snapshot wszystkich maszyn - HVsnapshotAll
Wykonywanie migawek nie jest backupem (snapshot jest trzymany na tym samym dysku co pliki konfiguracyjne wirtualnej maszyny, co może powodować problem w przypadku próby odzyskania go po awarii hosta Hyper-V), ale świetnie sprawdza się przy wprowadzaniu testowych zmian na wirtualnych hostach. Skrypt wykonuje snapshot wszystkich wirtualnych hostów, jednocześnie usuwając migawki starsze niż 6 dni.
## HVsnapshotAll.ps1
## Take a snapshot of all the VM's and delete snapshots older than 6 days
##
## last edit: 12:31 PM 9/13/2009 by Karol Stilger
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName <> Name "
foreach ($VM in [array] $ListOfVMs)
{
$VM_service.CreateVirtualSystemSnapShot($VM.__PATH)
}
##
## Giving Hyper-V 30 sec to take the snapshots
##
Start-Sleep(30)
##
## Remove snapshots older than 6 days (except Sundays)
##
$VSVR = get-wmiobject -namespace root\virtualization -class Msvm_ComputerSystem
$VSSNAP = get-wmiobject -namespace root\virtualization -class Msvm_VirtualSystemSettingData -filter "SettingType =
5"
if (!($VSSNAP -eq $null))
{
foreach ($SS in [array] $VSSNAP)
{
if ($SS.ConvertToDateTime($SS.CreationTime) -le [DateTime]::Now.AddDays(-6).Date)
{
if (!($SS.ConvertToDateTime($SS.CreationTime).DayOfWeek -eq 0))
{
$VM_Service.RemoveVirtualSystemSnapshot($SS)
Start-Sleep(3)
}
}
}
}
Snapshot pojedyńczej maszyny - HVsnapshotOne
Skrypt HVsnapshotOne jest modyfikacją HVsnapshotAll i wykoywany jest tylko dla maszyny $VMsystemName.
## HVsnapshotOne.ps1
## Take a snapshot of one VM and delete snapshots older than 6 days
## to edit: $VMsystemName
##
## last edit: 12:31 PM 9/13/2009 by Karol Stilger
$VMsystemName = 'MyFavoriteMachine'
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName = '$VMsystemName'"
foreach ($VM in [array] $ListOfVMs)
{
$VM_service.CreateVirtualSystemSnapShot($VM.__PATH)
}
##
## Giving Hyper-V 30 sec to take the snapshots
##
Start-Sleep(30)
##
## Remove snapshots older than 6 days (except Sundays)
##
$VSVR = get-wmiobject -namespace root\virtualization -class Msvm_ComputerSystem
$VSSNAP = get-wmiobject -namespace root\virtualization -class Msvm_VirtualSystemSettingData -filter "SettingType = 5"
if (!($VSSNAP -eq $null))
{
foreach ($SS in [array] $VSSNAP)
{
if ($SS.ConvertToDateTime($SS.CreationTime) -le [DateTime]::Now.AddDays(-6).Date)
{
if (!($SS.ConvertToDateTime($SS.CreationTime).DayOfWeek -eq 0))
{
$VM_Service.RemoveVirtualSystemSnapshot($SS)
Start-Sleep(3)
}
}
}
}
Usuwanie backupów starszych niż X dni - HVcleanBackup
Aby zadbać o miejsce niezbędne do wykonywania nowych backupów, warto pozbyć się tych już nieaktualnych. Skrypt HVbackupClean usuwa z folderu $CleanPath wszystkie pliki i katalogi starsze niż $Old dni.
## HVcleanBackup.ps1
## Deletes backup older than $Old days
## to edit: $CleanPath and $Old
##
## last edit: 12:30 PM 9/13/2009 by Karol Stilger
$CleanPath = "F:\HVbackup"
$Old = 10
gci $CleanPath -recurse | where {$_.lastWriteTime -le (Get-Date).addDays(-$Old)} | Remove-Item -recurse -force
Backup z użyciem Windows Server Backup
Windows Server Backup (WSB) współpracuje z usługą Volume Shadow Copy (VSS), dzięki czemu można za jego pomocą wykonywać kopie zapasowe uruchomionych maszyn wirtualnych bez konieczności ich zatrzymywania. To spora zaleta, ponieważ minimalizuje przestoje przewidziane na czynności administracyjne środowiska.
Konfiguracja i uruchomienie WSB dla backupowanie Hyper-V
Aby skorzystać WSB do onlinowego backup Hyper-V, należy:
- Upewnić się czy na maszynach wirtualnych nie są wykorzystywane dyski dynamiczne, jeśli są to backup tych maszyn będzie przeprowadzany offline - maszyny zostaną na czas backupu zatrzymane (saved). W razie potrzeby należy przekonwertować dyski na Fixed.
- Upewnić się czy maszyny wirtualne mają zainstalowane Integration Services (jeśli ich nie ma maszyna będzie backupowana jako saved).
- Upewnić się czy maszny wirtualne wspierają VSS i czy ich dyski są sformatowane w NTFS (Windows 2000 nie wspiera VSS - te maszyny będą backupowane jako saved).
- Zainstalować na serwerze z Hyper-V Windows Server Backup features: Windows Server Backup oraz Command-line Tools.
- Do rejestru dodać następujący wpis:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WindowsServerBackup\Application Support\{66841CD4-6DED-4F4B-8F17-FD23F8DDC3DE}]
"Application Identifier"="Hyper-V"
- Można przystąpić do planowania tego jak będą wykonywane backupy. Przechodzimy do panelu Start -> Administratine tools (Narzędzia administracyjne) -> Windows Server Backup (Kopia zapasowa systemu Windows Server). Konsolę MMC możemy podłaczyć do innego hosta (przydatne przy planowaniu backupów na wersji Core lub Hyper-V Server).
- Z kreatora backupu wybieramy typ: Full Backup lub Custom Backup. Minimalną opcją (Custom) backupu niezbędną do odzyskania działającego servera z Hyper-V na innym sprzęcie wraz działającymi maszynami jest wybranie - Bare metal recovery (wykonuje on backup: System State, System Reserverd oraz partycji systemowej) oraz wskazanie woluminu, na którym znajdują się wirtualne dyski twarde oraz pliki konfiguracyjne maszyn (jeśli znajdują się poza partycją systemową).

Rys. 1. - Windows Server Backup - wybór elementów do przeprowadzenie kopii zapasowej.
- Planujemy czas wykonywania backupu wybierając Backup Once (Jednorazowa kopia zapasowa) lub Backup Schedule (Harmonogram tworzenia kopii zapasowej).
- Wybieramy miejsce przechowywania backupu (sugeruję użycie dedykowanego dysku do składowania backupu).
- Po zatwierdzeniu wszystkich opcji zamykamy kreator, wybierając Close.
Odtwarzanie Hyper-V z kopii wykonanej przez WSB
Aby przywrócić stan Hyper-V do stanu z sprzed awarii, należy:
- Uruchomić kreator odzyskiwania w Windows Server Backup.
- Z panelu Actions (Akcje) wybrać Recover (Przywróć).
- Wybrać serwer, z którego mają być odtwarzane dane.
- Wybrać datę i godzinę backupu, który ma być przywrócony.
- Wybrać Applications (Przywracanie aplikacji).

Rys. 2. - Windows Server Backup, odtwarzanie - wybór typu odtwarzania.

Rys. 3. - Windows Server Backup, odtwarzanie wybór aplikacji do odtwarzania.
- Wybrać Recover to original location.
- Zatwierdzić wybór wciśnięciem Recover.
- Wyświetlony zostaje wskaźnik postępu odzyskiwania, po odzyskaniu backupu mamy poprawnie działający Hyper-V wraz z wirtualnymi maszynami.
Uwaga: W przypadku kiedy odzyskiwana maszyna wirtualna ma dwa i więcej snapshotów nie zostanie przywrócona za pomocą powyższej metody. Aby ją przywrócić należy po przeprowadzeniu powyższych operacji:
- Podłaczyć się do hosta Hyper-V za pomocą Hyper-V managera.
- Skasować maszynę wirtualną której nie udało się odzyskać.
- Przywrócić zawartość folderów ze snapshotami, domyślnie znajdują się one: C:\ProgramData\Microsoft\Windows\Hyper-V\Snapshots.
- Po przywróceniu zawartości snapshotów należy jeszcze raz wykonać procedurę odtwarzania Hyper-V (poprzedni opis).
W razie potrzeby można odzyskać np. sam plik VHD za pomoca opcji odzyskiwania pojedyńczych plików i podmienić go, jeśli konfiguracja systemu wirtualnego nie uległa zmianie.
W przypadku uszkodzenia całego systemu lub wszystkich danych możemy odzyskać z backupu system operacyjny na hoście Hyper-V łacznie ze wszystkimi uruchamianymi tam maszynami wirtuanymi. Aby to osiągnąć, należy uruchomić Windows Recovery - np. z płyty instalacyjnej Windows Server 2008 R2 - i z niego wykonać dalszą część odtwarzania.
Backup za pomocą Data Protection Manager
Pisząc o backupie Hyper-V wypada choć wspomnieć o Microsoft System Center Data Protection Manager (DPM). W tym artykule będzie to tylko symboliczne, bo bardziej chciałem się skupić tym co w kwestii backupuów Hyper-V ma do zaoferowania sam system operacyjny. Poprzednie rozwiązania które przedstawiłem są dedykowane do małych organizacji ze względnie niewielką ilością wirtualnej inftrastruktury. Przy większej ilości systemów nie sposób obejść się bez rozwiązania do globalnego zarządzania backupem systemów i aplikacji i tu świetnie sprawdza się DPM.
DPM wykorzystuje również VVS do przeprowadzania onlinowych backupów Hyper-V. Można za jego pomocą zarządzać tworzeniem kopii zapasowych i odtwarzaniem wybranych maszyn. Wspiera ciągłą ochronę danych za pomocą migawek. Rozpoznaje klaster Hyper-V i pozwala na podążanie kopii zapasowej za wirtualną maszyną na aktualny węzeł klastra. Zapewnia wsparcie dla nośników taśmowych w konfiguracjach: disk to disk, disk to tape oraz disk to disk to tape.
Poza wsparciem dla Hyper-V, Data Protection Manager potrafi zarządzac kopiami zapasowymi Virtual Server, SQL Server, Exchange oraz SharePointa.
Podsumowanie
Backup i odzyskiwanie Hyper-V i maszyn wirtualnych nie jest tak trudne, jak może się wydawać na początku. Warto jednak przemyśleć metody przeprowadzania kopii zapasowych i procedury ich odtwarzania. Oczywiście lepiej zrobić to przed awarią:).
Autor:

Karol Stilger (AaaA)
Microsoft MVP Setup & Deployment, MCTS, MCSA
Inżynier IT pracujący w międzynarodowej korporacji. Członek zespołu redakcyjnego WSS.pl. Prowadzi techniczny blog.