-
ESXi VM backup vs host backup
-
How to backup ESXi VM with PowerShell scripts?
-
How to backup ESXi VM with enterprise backup software?
-
Sum Up
VMware vSphere is widely used in companies, providing a robust virtualization platform to fully utilize hardware resources on physical servers and its hypervisor ESXi is highly praised by users.
When virtualization technology breaks the limitation of traditional IT environment, it also brings new challenges in IT maintenance. Should IT administrators keep backing up the physical server or find a new solution to backup the ESXi VMs?
ESXi VM backup vs host backup
Before the physical servers are virtualized, IT administrators only need to backup them with traditional solutions, but now restoring the whole server to repair certain VM is not good for disaster recovery because this could influence the well-running VMs.
In addition, it’s hard to backup all the data on a virtualized host because ESXi is a type 1 hypervisor which means there is no operating system for the traditional solution to install backup agent. Some IT administrators will backup the ESXi configuration but more people think it is unnecessary.
The most effective way to protect data and business continuity in virtual environment is still backing up the VMs on the ESXi host so in the event of VM failure, IT administrators can recover a single VM while not influence the other ones.
How to backup ESXi VM with PowerShell scripts?
To manage virtual machines, you can deploy vCenter in the virtual environment and manually export the ESXi VMs as data backup.
With vCenter deployed, you can also run PowerShell scripts to backup VM as scheduled.
This section will guide you to write 3 scripts, Starter.ps1, _Configuration.ps1, and Backup-VM.ps1. After that, you need to place them in the directory structure below:
│ Backup-VM.ps1
│ Starter.ps1
│
└─vCenter01
_Configuration.ps1
Script functionalities explantation:
Starter.ps1 - Invoked by task scheduler, in its path, it will scan all _Configuration.ps1 files, and launch Backup-VM.ps1 asynchronously. Backup-VM.ps1 - Owns a sole parameter called "-vCenterFolder", pointing to a directory of _Configuration.ps1. _Configuration.ps1 - Configuration file, any number of it is ok, based on the contents, do different VM backup jobs on different vCenter servers.
Script contents and description:
Starter.ps1
# Enter directory of script Set-Location (Get-Item $MyInvocation.MyCommand.Definition).Directory # Scan all _Configuration.ps1 files Get-ChildItem -Filter '_Configuration.ps1' -Recurse | %{ # Launch Backup-VM.ps1 and pass _Configuration.ps1's path in Start-Process -FilePath 'powershell.exe' -ArgumentList @('-File', 'Backup-VM.ps1', '-vCenterFolder', "`"$($_.DirectoryName)`"") }
_Configuration.ps1
$Enable = $true # Below is a sample to backup VMs # VM - the VM name in vCenter # Host - VMHost name in vCenter # Datastore - Datastore name in vCenter in Host <# Sample: $Entries = @( @{VM = 'VMName01'; Host = 'TargetESXiServerName02'; Datastore = 'TargetESXiServerName02:storage1'; Reserve = 1;}, @{VM = 'VMName02'; Host = 'TargetESXiServerName01'; Datastore = 'TargetESXiServerName01:storage2'; Reserve = 1;} ) #> # Actual data filled in $Entries = @( ) # vCenter server name or IP address $vCenter = 'vCenter01' # Mail setting part, only there are errors needs manual work will be triggered. normal backup job will not trigger the alert. $From = "$($env:COMPUTERNAME)@test.com" $To = "AlertNeedsToSend@test.com" $Subject = "VMs backup completed with errors - $vCenter" $SmtpServer = 'mailgateway'
Backup-VM.ps1 - Automatically judge which backup way to use, if VM uses VDS (vSphere Distributed Switch), script will choose API backup, if VM uses normal vSphere Standard Switch, script can use New-VM to clone VM. (After VDS, New-VM will fail, unless both original and target ESXi servers have the same VDS settings)
PARAM( [parameter(Mandatory=$true)] [string]$vCenterFolder ) # Enter directory of _Configuration.ps1 Set-Location -Path $vCenterFolder $Date = Get-Date $strDate = $Date.ToString("yyyy-MM-dd") $strLogFile = "${strDate}.log" # Import _Configuration.ps1 variables . '.\_Configuration.ps1' # Define a logging function function Add-Log { PARAM( [String]$Path, [String]$Value, [String]$Type = 'Info' ) $Type = $Type.ToUpper() $Date = Get-Date Write-Host "$($Date.ToString('[HH:mm:ss] '))[$Type] $Value" -ForegroundColor $( switch($Type) { 'WARNING' {'Yellow'} 'Error' {'Red'} default {'White'} } ) if($Path){ Add-Content -LiteralPath $Path -Value "$($Date.ToString('[HH:mm:ss] '))[$Type] $Value" -ErrorAction:SilentlyContinue } } Add-Log -Path $strLogFile -Value 'New backup started' # Whether the configuration is enabled or not if(!$Enable) { Add-Log -Path $strLogFile -Value 'Repository disabled' exit } # $vCenter is necessary, without it, script doesn't know where to connect to if(!$vCenter) { Add-Log -Path $strLogFile -Value 'vCenter variable is null, can not continue' -Type Error $Alert = $true } else { Add-Log -Path $strLogFile -Value "vCenter: [$vCenter]" } # Looking for necessary snapin, early version of PowerCli has no snapin for VDS, output some information to ensure the environment of the script if(!(Get-PSSnapin -Name '*VMware.VimAutomation.Vds*' -Registered -ErrorAction:SilentlyContinue)) { Add-Log -Path $strLogFile -Value 'This script is built from [VMware vSphere PowerCLI 5.5], suggest to run on the version' -Type Error Add-Log -Path $strLogFile -Value 'PSSnapin [VMware.VimAutomation.Vds] is not found, which could cause backup failure' -Type Error Add-Log -Path $strLogFile -Value 'Installer path: [ServerVMwarevSphereVMware-PowerCLI-5.5.0-1295336.exe]' -Type Info exit } # Add snapin if(!(Get-PSSnapin '*vmware*' -ErrorAction:SilentlyContinue)) { Add-PSSnapin *vmware* if(!$?) { Add-Log -Path $strLogFile -Value 'Failed to add vmware pssnapin' -Type Error Add-Log -Path $strLogFile -Value $Error[0] -Type Error exit } } # Connect to vCenter,if error, set $Alert to $true to trigger alert at last Connect-VIServer -Server $vCenter -Force if(!$?) { Add-Log -Path $strLogFile -Value 'Failed to connect to vCenter, cause:' -Type Error Add-Log -Path $strLogFile -Value $Error[0] -Type Error $Alert = $true } $Tasks = @() # Loop every VM backup item foreach($e in $Entries) { Add-Log -Path $strLogFile -Value "Start doing backup for: [$($e.VM)]" # Add a new VM name as "%OLDVMName%_ScriptBackup_%CurrentDate%" $VMNew = "$($e.VM)_ScriptBackup_$strDate" $e.NewVM = $VMNew $VM = $null $VM = @(Get-VM -Name $e.VM -ErrorAction:SilentlyContinue) if(!$VM) { Add-Log -Path $strLogFile -Value 'Capture none VM, does the VM exists?' -Type Warning continue } if($VM.Count -ge 2) { Add-Log -Path $strLogFile -Value "Capture [$($VM.Count)] VM, duplicated VMs?: [$(($VM | %{$_.Id}) -join '], [')]" -Type Warning continue } $VM = $VM[0] # only one VM captured, no confuse to script $VMHost = $null $VMHost = @(Get-VMHost -Name $e.Host -ErrorAction:SilentlyContinue) if(!$VMHost) { Add-Log -Path $strLogFile -Value "Capture none VMHost, does the VMHost exists?: [$($e.Host)]" -Type Warning continue } if($VMHost.Count -ge 2) { Add-Log -Path $strLogFile -Value "Capture [$($VMHost.Count)] VMHost, duplicated VMHosts?: [$(($VMHost | %{$_.Id}) -join '], [')]" -Type Warning continue } $VMHost = $VMHost[0] # only one VMHost captured, no confuse to script $Datastore = $null $Datastore = @($VMHost | Get-Datastore -Name $e.Datastore -ErrorAction:SilentlyContinue) if(!$Datastore) { Add-Log -Path $strLogFile -Value "Capture none Datastore, does the Datastore exists on VMHost?: [$($e.Datastore)]" -Type Warning continue } if($Datastore.Count -ge 2) { Add-Log -Path $strLogFile -Value "Capture [$($Datastore.Count)] Datastore, duplicated Datastores?: [$(($Datastore | %{$_.Id}) -join '], [')]" -Type Warning continue } $Datastore = $Datastore[0] # only one Datastore captured, no confuse to script Add-Log -Path $strLogFile -Value "INFO[OLDName][NewName][Host][Datastore]: [$($VM.Name)][$VMNew][$($VMHost.Name)][$($Datastore.Name)]" # Whether the VM is using VDS $VDS = $null $VDS = $VM | Get-VDSwitch -ErrorAction:SilentlyContinue if(!$VDS) { # if VDS is not placed, use New-VM to clone Add-Log -Path $strLogFile -Value 'VDSwitch not found on the VM, use commandlet [New-VM] to clone' $Task = $null $Task = New-VM -Name $VMNew -VM $VM -VMHost $VMHost -Datastore $Datastore -RunAsync -ErrorAction:SilentlyContinue if(!$?) { Add-Log -Path $strLogFile -Value 'New-VM failed, cause:' -Type Warning Add-Log -Path $strLogFile -Value $Error[0] -Type Warning continue } Add-Log -Path $strLogFile -Value "Task launched: [$($Task.Id)]" $Tasks += $Task.Id } else { # using VDS, use API to clone Add-Log -Path $strLogFile -Value 'VDSwitch found on the VM, need to use 2nd way to clone VM' Add-Log -Path $strLogFile -Value "VDS [Name][KEY]: [$(($VDS | %{$_.Name}) -join ';')][$(($VDS | %{$_.Key}) -join ';')]" $TargetVDS = $null $TargetVDS = @($VMHost | Get-VDSwitch -ErrorAction:SilentlyContinue) # on target VMHost search VDS, if target ESXi has no VDS, clone will fail if(!$TargetVDS) { Add-Log -Path $strLogFile -Value 'Target VMHost server has no VDSwitch, VM which uses a VDS is unable to clone to the VMHost' -Type Warning continue } $TargetVDS = $TargetVDS[-1] # capture VDS and pick the one owns most number of ports $TargetVDSGroup = @($TargetVDS | Get-VDPortgroup | Sort-Object NumPorts)[-1] Add-Log -Path $strLogFile -Value "Target VDS randomly picked [Name][Key]: [$($TargetVDS.Name)][$($TargetVDS.Key)]" # API nesessary, use default resource pool of ESXi server is fine $Pool = $null $Pool = @($VMHost | Get-ResourcePool)[0] if(!$Pool) { Add-Log -Path $strLogFile -Value 'No resource pool found from VMHost, please use Get-ResourcePool to find resource pool on the VMhost' -Type Warning continue } # Capture VM's network adapter, change it to use VDS on target ESXi $VMNic = $null $VMNic = $VM.ExtensionData.Config.Hardware.Device | ?{$_.DeviceInfo.Label -imatch 'Network adapter'} if($VMNic.Count -ge 2) { Add-Log -Path $strLogFile -Value 'The VM has more than 2 network adapters, not supported' -Type Warning continue } $VMNicBacking = $VMNic.Backing $VMNicBacking.Port.SwitchUuid = $TargetVDS.Key $VMNicBacking.Port.PortgroupKey = $TargetVDSGroup.Key $VMNicBacking.Port.PortKey = '' $VMNicBacking.Port.ConnectionCookie = '' # API necessary $spec = New-Object VMware.Vim.VirtualMachineCloneSpec $spec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec $nicDev = New-Object VMware.Vim.VirtualDeviceConfigSpec $nicDev.Operation = 'edit' $nicDev.Device = $VMNic $nicDev.Device.Backing = $VMNicBacking $spec.Config.DeviceChange = $nicDev $spec.Config.DeviceChange[0].Device.Backing.Port.PortKey = '' $spec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec $spec.Location.Host = $VMHost.ExtensionData.MoRef $spec.Location.Datastore = $Datastore.ExtensionData.MoRef $spec.Location.Pool = $Pool.ExtensionData.MoRef $spec.PowerOn = $false $spec.Template = $false Add-Log -Path $strLogFile -Value 'Trying to get datacenter object, this could potentially cause a dead loop!' # to get the $Folder for API, must get datacenter of ESXi first $Datacenter = $VMHost.Parent while($Datacenter.Id -notmatch 'Datacenter') { $Datacenter = $Datacenter.Parent } # API necessary $Folder = $Datacenter | Get-Folder -Name 'Discovered virtual machine' Add-Log -Path $strLogFile -Value 'Did not fail into a dead loop!' # use API to launch clone task $Task = $null $Task = $VM.ExtensionData.CloneVM_Task($Folder.ExtensionData.MoRef, $VMNew, $spec) if(!$?) { Add-Log -Path $strLogFile -Value 'CloneVM_Task failed, cause:' -Type Warning Add-Log -Path $strLogFile -Value $Error[0] -Type Warning continue } Add-Log -Path $strLogFile -Value "Task launched: [$($Task.Type)-$($Task.Value)]" $Tasks += "$($Task.Type)-$($Task.Value)" } } $Tasks = @($Tasks | ?{$_}) Add-Log -Path $strLogFile -Value "Waiting for tasks to complete, count: [$($Tasks.Count)]" while($Tasks) { # clone is running asynchronously, so script needs to trace all tasks every 5 minutes # The sleep time better not exceed 15 minutes, due to vCenter will clean completed tasks after 15 minutes # when debugging, change the time to 10 seconds is fine Start-Sleep -Seconds 300 $Tasks = Get-Task -Id $Tasks -ErrorAction:SilentlyContinue if(!$?) { Add-Log -Path $strLogFile -Value 'Failed to refresh Task states, cause:' -Type Warning Add-Log -Path $strLogFile -Value $Error[0] -Type Warning } $Tasks = @( $Tasks | %{ if($_.State -ne 'Running') { Add-Log -Path $strLogFile -Value "Task completed [ID][State]: [$($_.Id)][$($_.State)]" if($_.State -eq 'Error') { Add-Log -Path $strLogFile -Value $_.ExtensionData.Info.Error.LocalizedMessage -Type Warning } } else { Add-Log -Path $strLogFile -Value "Task running [ID][% Complete]: [$($_.Id)][$($_.PercentComplete)%]" $_.Id } } ) } # script will start verification for VM backups after all Tasks done Add-Log -Path $strLogFile -Value 'Verification start' foreach($e in $Entries) { if((Get-VM -Name $e.NewVM -ErrorAction:SilentlyContinue) -and $?) { # Backup VM found in vCenter, suggest the backup was succeed Add-Log -Path $strLogFile -Value "[VM][NewVM]: [$($e.VM)][$($e.NewVM)] -- New VM found in vCenter" if($e.Reserve) { # If Reserve's valud is set, script will find all backups for the VM, and remove addtionals $VMBackups = $null $VMBackupsRemoval = $null $VMBackups = Get-VM -Name "$($e.VM)_ScriptBackup_*" | ?{$_.Name -imatch '_ScriptBackup_d{4}-d{2}-d{2}$'} -ErrorAction:SilentlyContinue $VMBackups = @($VMBackups | Sort-Object 'Name') Add-Log -Path $strLogFile -Value "Old VM backups captured: [$($VMBackups.Count)][$(($VMBackups | %{$_.Name}) -join ';')]" $i = $VMBackups.Count - $e.Reserve if($i -le 0) { $i = 0 Add-Log -Path $strLogFile -Value 'No old backups available to be removeds' } if($i -gt 0) { Add-Log -Path $strLogFile -Value "VM old backups can be removed count: [$i]" $VMBackupsRemoval = $VMBackups[0..(--$i)] Remove-VM -VM $VMBackupsRemoval -DeletePermanently -Confirm:$false } } } else { # backup VM not found in vCenter which means backup failed, better do nothing Add-Log -Path $strLogFile -Value "[VM][NewVM]: [$($e.VM)][$($e.NewVM)] -- New VM not found in vCenter, backup failure?" -Type Warning $Alert = $true } } Add-Log -Path $strLogFile -Value 'All done!' # If there is error needs manual work, email will be triggered if($Alert) { Send-MailMessage -To $To -From $From -SmtpServer $SmtpServer -Subject $Subject -Attachments $strLogFile if(!$?) { Add-Log -Path $strLogFile -Value 'Failed to send email, cause:' -Type Warning Add-Log -Path $strLogFile -Value $Error[0] -Type Warning } }
How to backup ESXi VM with enterprise backup software?
Script gives the free ESXi VM backup solution but actually it is not good for enterprise disaster recovery because it is not a comprehensive backup solution and doesn’t provide a quick VM recovery solution. Companies should have a more professional solution.
Vinchin Backup & Recovery is a VMware-verified professional enterprise backup solution supporting guest-level backup for VMware vSphere.
It just requires several minutes to deploy in virtual environment and then a user-friendly web console will help you easily create a backup job with the needed strategies.
1. Add the ESXi host with its credentials to backup VMs on it agentlessly
2. Select the ESXi host and then select the VMs on it
3. Select the backup storage
4. Select the backup strategies. For example, you will have incremental backup, data compression, BitDetector, etc. to reduce backup size, data encryption for data security, and LAN-free transfer to mitigate the impact on production environment.
5. Just review the backup job and submit
To facilitate disaster recovery, Vinchin Instant Recovery can let you instantly recover a fail VM from its backup in 15 seconds and to better manage multi-hypervisor environment, you can recover ESXi VM on another host like XenServer and RHV and vice verse.
Vinchin Backup & Recovery has been selected by thousands of companies and you can also start a 60-day full-featured free trial here. Also, contact us, leave your requirements, and then you will receive your tailored solution. We have established partnerships with reputable companies all over the world so if you would like to do a local business, you can select a local partner here.
Sum Up
ESXi can virtualize a bare metal physical server to let companies better utilize the hardware resources on it. To backup data on the server, companies can backup every VM on it so when certain VM is down, recovering the failed VM will not influence the other VMs.
Except for manually exporting VM from vCenter, there is also the way to run scripts to backup ESXi VM with more options.
There is also the solution better than the scripts. Vinchin Backup & Recovery is a professional enterprise backup solution for VMware ESXi VMs and provide more well-round protection to the virtual environment with easy operation. Don’t miss the free trial.
Share on: