Hyper-V 复制在系统关闭时暂停
本文可帮助解决关闭主服务器或副本服务器时 Hyper-V 复制挂起的问题。
当主服务器或副本服务器关闭时,Hyper-V 复制将暂停。 此外,Hyper-V 虚拟机管理服务(VMMS)使用事件 ID 32086 和 32022 记录一系列事件日志。
事件 ID 32086
输出Log Name: Microsoft-Windows-Hyper-V-VMMS/Admin Source: Hyper-V-VMMS Event ID: 32086 Level: Error Description: Hyper-V suspended replication for virtual machine <VM Name> due to a non-recoverable failure. Resume replication after correcting the failure. (Virtual machine ID <VM GUID>)
事件 ID 32022
输出Log Name: Microsoft-Windows-Hyper-V-VMMS/Admin Source: Hyper-V-VMMS Event ID: 32022 Level: Error Description: Hyper-V could not replicate changes for virtual machine <VM Name>: The operation has been canceled (0x80004004). (Virtual Machine ID <VM GUID>)
备注
说明还可能包含消息“操作已中断(0x80004004)。
此问题发生在 Windows Server 2012 Standard、Windows Server 2012 Datacenter 和 Windows Server 2012 R2 Standard 中。 此问题已在 Windows Server 2016 KB4088889中修复。
出现此问题的原因是 Hyper-V VMMS 停止发出新进程。 当主服务器和副本服务器关闭时,Hyper-V VMMS 将停止发出新进程(任务)。 如果 Hyper-V 副本服务器的不同数据此时到达或传输,则无法发出传输或接收过程,并且可能会暂停复制。
可以从 Hyper-V 管理器中选择并按住虚拟机(或右键单击),然后选择“复制>恢复复制”以手动重启复制。
还可以在任务计划程序中设置 复制自动重启脚本 ,以便在系统启动时自动重启复制。
该脚本会自动重启在系统重启或关闭时暂停的复制,并在复制处于挂起状态时自动恢复复制。
在主服务器和副本服务器上执行以下步骤:
复制复制自动重启脚本并将其保存在任何文件夹中(例如 C:\Scripts),文件名 为 restartReplication.ps1。
启动 PowerShell 并运行以下 cmdlet:
PowerShellPS > Set-ExecutionPolicy RemoteSigned
备注
- 无需在已运行该 cmdlet 的系统上运行该 cmdlet。
- 默认情况下,无法在从未运行 PowerShell 的系统上启动 PowerShell。
按 Windows 徽标键 + X 以显示屏幕左下角的菜单,然后选择“ 计算机管理”。
在左窗格中展开 任务计划程序 。 选择并按住(或右键单击) 任务计划程序库,然后选择“ 创建任务”。 将显示任务创建窗口。
在 “常规 ”选项卡上设置以下选项:
- 名称:指定任务名称(例如 Hyper-V 副本自动恢复任务)
- 运行任务时,请使用以下用户帐户:指定具有管理员权限的用户帐户(例如 <,域名>\管理员)
- 仅当用户登录时运行:取消选中该选项
- 运行用户是否登录:选中该选项
- 使用最高权限运行:选中选项
选择“触发器”选项卡,然后选择“新建”。
设置以下选项,然后选择“ 确定” :
- 开始任务:在启动时选择
- 已启用高级设置>:选中选项
备注
未选中其他选项。
选择“操作”选项卡,然后选择“新建”。
设置以下选项,然后选择“ 确定” :
- 操作:选择“启动程序”
- 程序/脚本:类型 powershell.exe
- 添加参数(可选):指定自动重启脚本的完整路径(例如 C:\Scripts\restartReplication.ps1)
- 从 (可选)开始:将值保留为空白
在“条件”和“设置”选项卡上保留默认设置,然后选择“确定”以完成设置。
身份验证提示时,输入管理员密码。
完成脚本设置后,可以按照以下步骤在主服务器上测试脚本的操作状态。
从主服务器的 Hyper-V 管理器中选择为其配置复制的虚拟机。 选择并按住(或右键单击),然后选择“复制暂停复制>”以有意暂停复制。
在 Hyper-V 管理器中选择挂起的虚拟机,然后选择 屏幕底部的“复制 ”选项卡。 确保复制状态已暂停。
重启主服务器。 如果无法重启,请在主服务器上启动任务计划程序。 选择并按住上面创建的任务(或右键单击),然后选择“ 运行”。
当系统启动时或执行手动任务时,将运行该脚本。 若要检查复制是否自动重启,请从主服务器上的 Hyper-V 管理器中选择 挂起的虚拟机,然后选择屏幕底部的“复制 ”选项卡。 如果复制状态为“复制”已启用,则复制已正常恢复。
还可以检查系统事件日志,确认脚本的操作状态。
启动脚本的事件
输出Log Name: System Source: Hyper-V Replica script Event ID: 0 Level: Information Description: Starting script to restart replication.
恢复复制的事件
输出Log Name: System Source: Hyper-V Replica script Event ID: 4 Level: Information Description: Replication for <VM Name> on <Primary Server Name> was in suspended and resumed successfully.
如果发生诸如重启失败之类的错误,则会在系统事件日志中记录错误内容,其中包含名为“Hyper-V 副本脚本”的事件源。
下面是复制自动重启脚本:
$EventSource = "Hyper-V Replica script" ### Event source name recorded in system log.
$StartUpTimeout = 60 ### Startup timeout value for replication service in second.
If ([System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $false)
{
New-EventLog -LogName System -Source $EventSource
}
Write-EventLog -LogName System -Source $EventSource -EntryType Information -EventID 0 -Message "Starting script to restart replication."
### Wait until VMMS starts up.
(Get-Service "vmms").WaitForStatus("Running") ### No timeout.
### Wait until replication service in VMMS gets active.
$Count = 0
While((Get-VMReplication).count -eq 0)
{
Start-Sleep -s 1
$Count++
If ($Count -eq $StartUpTimeout)
{
Write-EventLog -LogName System -Source $EventSource -EntryType Error -EventID 1 -Message "VMMS did not complete initialization after VMMS service started up. Exiting..."
Exit(1)
}
}
$Message = "Replication service in VMMS was started successfully. It took " + $Count + " seconds after VMMS started."
Write-EventLog -LogName System -Source $EventSource -EntryType Information -EventID 2 -Message $Message
###
### MAIN
###
$LocalVMs = Get-VMReplication ### Get local VMs with replication enabled.
Foreach($LocalVM in $LocalVMs)
{
$PrimaryServer = $LocalVM.PrimaryServer
$VMName = $LocalVM.Name
### Get-VMReplication will access remote primary server if this VM is RecoveryVM.
$VM = Get-VMReplication -ComputerName $PrimaryServer | Where-Object { $_.Name -eq $VMName}
If ($VM -eq $null -or $VM.count -eq 0)
{
$Message = "Get-VMReplication has failed." + $Error[0].Exception + "(VM: " + $VMName + " Server: " + $PrimaryServer + ")"
Write-EventLog -LogName System -Source $EventSource -EntryType Error -EventID 3 -Message $Message
Exit(1)
}
### If the VM is normal, move to next VM.
If ($VM.State -ne "Suspended" -and $VM.State -ne "Error") { continue }
### Resuming replication here.
$Err = Resume-VMReplication -VMName $VMName -ComputerName $PrimaryServer 2>&1
### Wait status update for 1 sec.
Start-Sleep -s 1
### Checking the replication status after resuming the replication
$CurrentVM = Get-VMReplication -ComputerName $PrimaryServer | Where-Object { $_.Name -eq $VMName}
### If the replication state is still in suspended or error, it logs to event service.
If ($CurrentVM.State -eq "Suspended" -or $VM.State -eq "Error")
{
$Message = "Failed to resume replication for " + $VMName + " on " + $PrimaryServer + ". Please check replication status manually." + $Err.Exception
Write-EventLog -LogName System -Source $EventSource -EntryType Error -EventID 3 -Message $Message
}
Else
{
$Message = "Replication for " + $VMName + " on " + $PrimaryServer + " was in suspended and resumed successfully."
Write-EventLog -LogName System -Source $EventSource -EntryType Information -EventID 4 -Message $Message
}
}