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 VMMS 将停止发出新进程(任务)。 如果 Hyper-V 副本服务器的不同数据此时到达或传输,则无法发出传输或接收过程,并且可能会暂停复制。

解决方法 1:手动重启复制

可以从 Hyper-V 管理器中选择并按住虚拟机(或右键单击),然后选择“复制>恢复复制以手动重启复制。

解决方法 2:使用脚本自动重启复制

还可以在任务计划程序中设置 复制自动重启脚本 ,以便在系统启动时自动重启复制。

该脚本会自动重启在系统重启或关闭时暂停的复制,并在复制处于挂起状态时自动恢复复制。

在主服务器和副本服务器上执行以下步骤:

  1. 复制复制自动重启脚本并将其保存在任何文件夹中(例如 C:\Scripts),文件名 为 restartReplication.ps1

  2. 启动 PowerShell 并运行以下 cmdlet:

    PowerShell
    PS > Set-ExecutionPolicy RemoteSigned
    

    备注

    • 无需在已运行该 cmdlet 的系统上运行该 cmdlet。
    • 默认情况下,无法在从未运行 PowerShell 的系统上启动 PowerShell。
  3. 按 Windows 徽标键 + X 以显示屏幕左下角的菜单,然后选择“ 计算机管理”。

  4. 在左窗格中展开 任务计划程序 。 选择并按住(或右键单击) 任务计划程序库,然后选择“ 创建任务”。 将显示任务创建窗口。

  5. “常规 ”选项卡上设置以下选项:

    • 名称:指定任务名称(例如 Hyper-V 副本自动恢复任务
    • 运行任务时,请使用以下用户帐户:指定具有管理员权限的用户帐户(例如 <,域名>\管理员
    • 仅当用户登录时运行:取消选中该选项
    • 运行用户是否登录:选中该选项
    • 使用最高权限运行:选中选项
  6. 选择“触发器”选项卡,然后选择“新建”。

  7. 设置以下选项,然后选择“ 确定” :

    • 开始任务:在启动时选择
    • 已启用高级设置>:选中选项

    备注

    未选中其他选项。

  8. 选择“操作”选项卡,然后选择“新建”。

  9. 设置以下选项,然后选择“ 确定” :

    • 操作:选择“启动程序”
    • 程序/脚本:类型 powershell.exe
    • 添加参数(可选):指定自动重启脚本的完整路径(例如 C:\Scripts\restartReplication.ps1
    • 从 (可选)开始:将值保留为空白
  10. 在“条件”和“设置”选项卡上保留默认设置,然后选择“确定以完成设置。

身份验证提示时,输入管理员密码。

测试脚本的操作状态

完成脚本设置后,可以按照以下步骤在主服务器上测试脚本的操作状态。

  1. 从主服务器的 Hyper-V 管理器中选择为其配置复制的虚拟机。 选择并按住(或右键单击),然后选择“复制暂停复制>以有意暂停复制。

  2. 在 Hyper-V 管理器中选择挂起的虚拟机,然后选择 屏幕底部的“复制 ”选项卡。 确保复制状态已暂停

  3. 重启主服务器。 如果无法重启,请在主服务器上启动任务计划程序。 选择并按住上面创建的任务(或右键单击),然后选择“ 运行”。

  4. 当系统启动时或执行手动任务时,将运行该脚本。 若要检查复制是否自动重启,请从主服务器上的 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 副本脚本”的事件源。

复制自动重启脚本

下面是复制自动重启脚本:

PowerShell
$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
    }
}