Configurar o failover de VM entre redes virtuais
Importante
Esta versão do VMM (Virtual Machine Manager) chegou ao fim do suporte. Recomendamos que você atualize para o VMM 2022.
Este artigo descreve como lidar com a replicação e o failover de VMs no System Center - Virtual Machine Manager (VMM), entre redes virtuais quando você não estiver usando o Azure Site Recovery para gerenciar a recuperação de desastres.
- É recomendável usar o Azure Site Recovery para replicar máquinas virtuais. O VMM não gerencia a Réplica do Hyper-V sem o Site Recovery, e você precisa usar os cmdlets do PowerShell de Réplica do Hyper-V para automatizar as operações de Réplica do Hyper-V.
- Para recuperação de desastres, recomendamos que você use redes virtuais separadas primárias e secundárias. As VMs primárias se conectam à rede principal e as VMs de réplica à rede secundária. Isso garante que ambas as VMs possam ser conectadas a uma rede ao mesmo tempo.
- Se você tiver uma única rede virtual, use Site Recovery para automatizar o gerenciamento de rede usando o recurso de mapeamento de rede. Se você não usar o Site Recovery, precisará verificar com cuidado os pré-requisitos e a ordem na qual as VMs são conectadas à rede. Em particular, a VM de réplica e a VM principal não devem estar conectadas à rede virtual única ao mesmo tempo. Caso contrário, os registros CA-PA poderão ser excluídos no VMM e causar perda de conectividade de rede.
Solução de exemplo
Esta solução de exemplo descreve o seguinte ambiente:
- Um único servidor VMM gerencia sites primários e secundários.
- As máquinas virtuais primárias e de réplica são hospedados em uma única rede virtual do Hyper-V.
- Você precisará executar um failover planejado e reter o endereço IP da VM após o failover.
- As VMs têm endereços IPv4.
Antes de começar
Verifique se as configurações do comutador virtual e do comutador lógico são válidas e correspondem à malha do VMM. Se não, as operações de anexação de rede poderão não funcionar após o failover.
A VM primária deve estar conectada a uma rede virtual
A VM de réplica não deve estar conectada a uma rede
Apenas um endereço IP deve ser atribuído a cada adaptador de rede da máquina virtual primária. Execute este comando para garantir isso. Se houver mais de um adaptador de rede conectado na VM, execute-o alterando o índice de matriz.
$VMOnPD = Get-SCVirtualMachine -Name "VM Name" | where {$_.IsPrimaryVM -eq $true} Get-SCIPAddress –GrantToObjectId $VMOnPD.VirtualNetworkAdapters[0].ID``
Verifique se o endereço IP atribuído à VM pelo sistema operacional é o mesmo que o endereço IP mostrado acima. Entre na VM e execute ipconfig para marcar isso.
Verifique se as tabelas de pesquisa estão definidas corretamente no primário e no réplica. Para fazer isso, execute o seguinte comando em cada servidor e verifique se há uma entrada que corresponda ao endereço IP retornado acima:
Get-NetVirtualizationLookupRecord
Verifique se o endereço IP é IPv4 e não IPv6
Verifique se ambas as VMs estão desativadas antes de executar os scripts.
Verifique se o estado de replicação está habilitado em ambas as VMs.
Execute o script de failover planejado
Veja o que esse script faz:
- Para cada adaptador de rede em uma máquina virtual primária, ele armazena o endereço IP, a rede de VM e o pool de IP.
- Revoga todos os endereços IP de cada adaptador de rede nas máquinas virtuais primárias e secundárias.
- Desconecta todos os adaptadores de rede.
- Faz failover das VMs primárias e secundárias.
- Opcionalmente, inicia a replicação inversa.
- Dá o mesmo endereço IP (para cada adaptador de rede) à VM de réplica.
- Anexa cada adaptador de rede na VM replicada às redes de VM que foram armazenadas na etapa 1.
Executar o script
O script usa dois argumentos:
- $VMName – nome da máquina virtual
- $ReverseRep – argumento booliano para especificar se a replicação inversa deve ser executada ou não
- Se $true for passado, a replicação inversa será iniciada imediatamente e você não poderá cancelar o failover mais tarde.
- Após esse script ser concluído com êxito com $ReverseRep como $true:
- A VM primária deve estar em um estado de replicação Preparada para o failover planejado.
- A VM de réplica deve estar em um estado de replicação Failover concluído.
- Se $false for passado, a replicação inversa não será realizada. ReverseRepORCancelFO.ps1 pode ser usado para executar a replicação inversa ou cancelar o failover.
- Após o script ser concluído com êxito com $ReverseRep como $false:
- A VM primária deve estar em um estado de replicação Preparada para o failover planejado.
- A VM de réplica deve estar em um estado de replicação Failover concluído.
Se o script não concluir nenhuma das etapas, você precisará concluir as etapas com falha manualmente e, em seguida, retornar à janela do PowerShell. As etapas de script incluem failover da VM primária, failover da VM réplica e, opcionalmente, replicação reversa.
Executar o script:
Param(
[Parameter(Mandatory=$True)]
[string]$VMName,
[Parameter(Mandatory=$true)]
[boolean]$ReverseRep
)
# the script running on system with SCVMM Console/PowerShell installed. Also, requires Hyper-V powershell module.``
Import-Module hyper-v
## Refresh VM configuration and initialize
Write-Host -ForegroundColor Green (Get-Date) ".....Refreshing the VMs..."
Get-SCVirtualMachine -Name $VMName | Read-SCVirtualMachine
$VMOnPD = Get-SCVirtualMachine -Name $VMName | where {$_.IsPrimaryVM -eq $true}
$VMOnDR = Get-SCVirtualMachine -Name $VMName | where {$_.IsPrimaryVM -eq $false}
if ($VMOnPD.StatusString -ne "Stopped")
{
write-host -ForegroundColor Red (Get-Date) "....VM is not in stopped state. Actual State " $VMOnPD.StatusString
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
$error.Clear()
$VMRepConfig = Get-VMReplication -ComputerName $VMOnPD.HostName -VMName $VMOnPD.Name
$VMRepConfig = Get-VMReplication -ComputerName $VMOnDR.HostName -VMName $VMOnPD.Name
if ($error -ne 0)
{
$temp = $VMOnPD.HostName.Split(".")
$primaryHostName = $temp[0]
$temp = $VMOnDR.HostName.Split(".")
$recoveryHostName = $temp[0]
write-host -ForegroundColor Red (Get-Date) "....Error in getting VM Replication state using FQDN, switching to Hostname"
write-host -ForegroundColor Yellow (Get-Date) "....Primary Hostname: " $primaryHostName " Replica Hostname: " $recoveryHostName
$error.Clear()
$VMRepConfig = Get-VMReplication -ComputerName $primaryHostName -VMName $VMOnPD.Name
$VMRepConfig = Get-VMReplication -ComputerName $recoveryHostName -VMName $VMOnPD.Name
if ($error -ne 0)
{
write-host -ForegroundColor Red (Get-Date) "....Error in getting VM Replication state using Hostname"
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
write-host -ForegroundColor Green (Get-Date) "....Successful in getting VM Replication state using Hostname"
}
else
{
$primaryHostName = $VMOnPD.HostName
$recoveryHostName = $VMOnDR.HostName
}
$VMOnPDAdapter = Get-SCVirtualNetworkAdapter -VM $VMonPD
$VMOnDRAdapter = Get-SCVirtualNetworkAdapter -VM $VMonDR
$fileName = $VMName + (Get-Date).ToString() + ".txt"
$fileName = $fileName.Replace("/","_")
$fileName = $fileName.Replace(":","_")
Write-Host -ForegroundColor Yellow (Get-Date) "....Dumping network information for $VMName to file $fileName"
Write-Host -ForegroundColor Yellow (Get-Date) "....Number of Network adapters found: " $VMOnPDAdapter.count
$VMNetwork = @()
$VMSubnet = @()
$Pools = @()
$counter = 0
foreach($vmAdapter in $VMOnPDAdapter)
{
if ($vmAdapter.VMNetwork -eq $null)
{
$VMNetwork = $VMNetwork + $null
$VMSubnet = $VMSubnet + $null
$Pools = $Pools + $null
$counter = $counter + 1
continue
}
$VMNetwork = $VMNetwork + (Get-SCVMNetwork -Name $vmAdapter.VMNetwork.Name -ID $vmAdapter.VMNetwork.ID)
$VMSubnet = $VMSubnet + (Get-SCVMSubnet -Name $vmAdapter.VMSubnet.Name | where {$_.VMNetwork.ID -eq $vmAdapter.VMNetwork.ID})
#$PortClassification = Get-SCPortClassification | where {$_.Name -eq "Guest Dynamic IP"}
$Pools = $Pools + (Get-SCStaticIPAddressPool -IPv4 | where {$_.VMsubnet.name -eq $vmAdapter.VMSubnet.Name})
Out-File -FilePath $fileName -InputObject $VMNetwork[$counter] -Append
Out-File -FilePath $fileName -InputObject $VMSubnet[$counter] -Append
Out-File -FilePath $fileName -InputObject $Pools[$counter] -Append
$counter = $counter + 1
}
if ($error.Count -ne 0)
{
write-host -ForegroundColor Red (Get-Date) "....Error is gathering information for $VMName. No changes made"
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
$IP = @()
$counter = 0
foreach($vmAdapter in $VMOnPDAdapter)
{
if ($VMNetwork[$counter] -eq $null)
{
Write-Host -ForegroundColor Yellow (Get-Date) ".....Network Adapter '" $counter "' not connected"
$IP = $IP + $null
$counter = $counter + 1
continue
}
## Revoke IP
$error.Clear()
$IP = $IP +(Get-SCIPAddress –GrantToObjectId $VMOnPD.VirtualNetworkAdapters[$counter].ID)
Write-Host -ForegroundColor Yellow (Get-Date) "....Revoking IP " $IP[$counter] "from Primary VM"
Revoke-SCIPAddress $IP[$counter]
if ($error.count -eq 0)
{
Write-Host -ForegroundColor Green (Get-Date) "....." $IP[$counter] "revoke completed"
}
## Disconnect Primary VM
Write-Host -ForegroundColor Yellow (Get-Date) "....Disconnecting Primary VM from Network " $VMNetwork[$counter]
Set-SCVirtualNetworkAdapter -VirtualNetworkAdapter $VMOnPD.VirtualNetworkAdapters[$counter] -NoLogicalNetwork -NoConnection -NoPortClassification
Write-Host -ForegroundColor Green (Get-Date) "....Network Adapter '" $counter "' of Primary VM Disconnected"
$counter = $counter + 1
}
## Start failover
Write-Host -ForegroundColor Yellow (Get-Date) ".....We are going to Failover " $VMName " from " $primaryHostName " to " $recoveryHostName
$error.Clear()
Start-VMFailover -ComputerName $primaryHostName -VMName $VMOnPD.Name -Prepare -Confirm:$false
start-sleep 5
Write-Host -ForegroundColor Yellow (Get-Date) ".....Completing Failover on Replica site..."
Start-VMFailover -ComputerName $recoveryHostName -VMName $VMOnDR.Name -Confirm:$false
if ($ReverseRep)
{
write-host -ForegroundColor Green (Get-Date) ".....Starting Reverse Replication..."
Set-VMReplication -ComputerName $recoveryHostName -reverse -VMName $VMOnDR.Name
}
if ($error -ne 0)
{
write-host -ForegroundColor Red (Get-Date) ".....Error occured during Planned Failover for VM $VMName"
write-host -ForegroundColor Red (Get-Date) ".....Please manually complete Failover before continuing"
Write-Host -ForegroundColor Red (Get-Date) ".....Press any key to continue..."
$ignoreKey = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
Write-Host -ForegroundColor Green (Get-Date) ".....Connecting Network(s) to Failed-over VM"
$counter = 0
foreach($vmAdapter in $VMOnPDAdapter)
{
if ($VMNetwork[$counter] -eq $null)
{
Write-Host -ForegroundColor Yellow (Get-Date) ".....Network Adapter '" $counter "' not connected"
$counter = $counter + 1
continue
}
Write-Host -ForegroundColor Yellow (Get-Date) "Granting " $IP[$counter] "to Failed-over VM"
Grant-SCIPAddress -GrantToObjectType "VirtualNetworkAdapter" -GrantToObjectID $VMOnDRAdapter[$counter].ID -StaticIPAddressPool $Pools[$counter] –IPAddress $IP[$counter]
Write-Host -ForegroundColor Green (Get-Date) "Granting IP completed"
Write-Host -ForegroundColor Yellow (Get-Date) "Connecting Replica VM to " $VMNetwork[$counter]
Set-SCVirtualNetworkAdapter -VirtualNetworkAdapter $VMOnDRAdapter[$counter] -IPv4AddressType static -VMNetwork $VMNetwork[$counter] -VMSubnet $VMSubnet[$counter]
Write-Host -ForegroundColor Green (Get-Date) "Network Adapter '" $counter "' of Failed-over VM connected to " $VMNetwork[$counter]
$counter = $counter + 1
}
Execute script de replicação inversa/cancelar
Veja o que esse script faz:
- Se você não tiver executado a replicação inversa no script de failover, poderá usar esse script para a replicação inversa ou para cancelar o failover.
- Se você cancelar, o script reverterá as etapas de rede e restaurará as conexões de VM primárias depois de desconectar as redes de VM réplica.
Executar o script
Esse script deve ser executado para o script de failover com $ReverseRep definido como $false. Esse script usa três argumentos:
- $VMName: nome da VM
- $ReverseRep: argumento booliano para especificar se a replicação inversa deve ser executada. $true indica que a replicação inversa é executada.
- $CancelFO - argumento booliano para especificar se o failover é cancelado. $true indica cancelamento em sites primários e de recuperação.
Somente $ReverseRep ou $CancelFO pode ser passado como $true por vez. Depois que o script é executado com sucesso, o estado em ambas as VMs deve ser Replicação habilitada.
Executar o script:
Param(
[Parameter(Mandatory=$True)]
[string]$VMName,
[Parameter(Mandatory=$true)]
[boolean]$ReverseRep,
[Parameter(Mandatory=$true)]
[boolean]$CancelFO
)
# the script running on system with SCVMM Console/PowerShell installed. Also, requires Hyper-V powershell module.
Import-Module hyper-v
if ($ReverseRep -eq $CancelFO)
{
write-host -ForegroundColor Red (Get-Date) "....Please ensure that one and only one of the parameters -ReverseRep and -CancelFO is passed as $True"
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
## Refresh VM configuration and initialize
Write-Host -ForegroundColor Green (Get-Date) ".....Refreshing the VMs..."
Get-SCVirtualMachine -Name $VMName | Read-SCVirtualMachine
$VMOnPD = Get-SCVirtualMachine -Name $VMName | where {$_.IsPrimaryVM -eq $true}
$VMOnDR = Get-SCVirtualMachine -Name $VMName | where {$_.IsPrimaryVM -eq $false}
$error.Clear()
$VMRepConfig = Get-VMReplication -ComputerName $VMOnPD.HostName -VMName $VMOnPD.Name
$VMRepConfig = Get-VMReplication -ComputerName $VMOnDR.HostName -VMName $VMOnPD.Name
if ($error -ne 0)
{
$temp = $VMOnPD.HostName.Split(".")
$primaryHostName = $temp[0]
$temp = $VMOnDR.HostName.Split(".")
$recoveryHostName = $temp[0]
write-host -ForegroundColor Red (Get-Date) "....Error in getting VM Replication state using FQDN, switching to Hostname"
write-host -ForegroundColor Yellow (Get-Date) "....Primary Hostname: " $primaryHostName " Replica Hostname: " $recoveryHostName
$error.Clear()
$VMRepConfig = Get-VMReplication -ComputerName $primaryHostName -VMName $VMOnPD.Name
$VMRepConfig = Get-VMReplication -ComputerName $recoveryHostName -VMName $VMOnPD.Name
if ($error -ne 0)
{
write-host -ForegroundColor Red (Get-Date) "....Error in getting VM Replication state using Hostname"
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
write-host -ForegroundColor Green (Get-Date) "....Successful in getting VM Replication state using Hostname"
}
else
{
$primaryHostName = $VMOnPD.HostName
$recoveryHostName = $VMOnDR.HostName
}
if ($VMOnDR.ReplicationStatus.ReplicationState -ne "Recovered")
{
write-host -ForegroundColor Red (Get-Date) "....Replica VM is not in Failed over state. Actual State " $VMOnDR.ReplicationStatus.ReplicationState
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
$error.Clear()
if ($ReverseRep -eq $true)
{
write-host -ForegroundColor Green (Get-Date) ".....Starting Reverse Replication..."
Set-VMReplication -ComputerName $recoveryHostName -reverse -VMName $VMOnDR.Name
if ($error -ne 0)
{
write-host -ForegroundColor Red (Get-Date) ".....Error occured during Reverse Replication for VM $VMName"
write-host -ForegroundColor Red (Get-Date) ".....Please manually complete Reverse replication"
exit 1
}
write-host -ForegroundColor Green (Get-Date) ".....Reverse Replication completed..."
exit 0
}
if ($VMOnDR.StatusString -ne "Stopped")
{
write-host -ForegroundColor Red (Get-Date) "....VM is not in stopped state. Actual State " $VMOnDR.StatusString
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
$VMOnPDAdapter = Get-SCVirtualNetworkAdapter -VM $VMonPD
$VMOnDRAdapter = Get-SCVirtualNetworkAdapter -VM $VMonDR
$fileName = $VMName + (Get-Date).ToString() + ".txt"
$fileName = $fileName.Replace("/","_")
$fileName = $fileName.Replace(":","_")
Write-Host -ForegroundColor Yellow (Get-Date) "....Dumping network information for $VMName to file $fileName"
Write-Host -ForegroundColor Yellow (Get-Date) "....Number of Network adapters found on Failed-over VM: " $VMOnDRAdapter.count
$VMNetwork = @()
$VMSubnet = @()
$Pools = @()
$counter = 0
foreach($vmAdapter in $VMOnDRAdapter)
{
if ($vmAdapter.VMNetwork -eq $null)
{
$VMNetwork = $VMNetwork + $null
$VMSubnet = $VMSubnet + $null
$Pools = $Pools + $null
$counter = $counter + 1
continue
}
$VMNetwork = $VMNetwork + (Get-SCVMNetwork -Name $vmAdapter.VMNetwork.Name -ID $vmAdapter.VMNetwork.ID)
$VMSubnet = $VMSubnet + (Get-SCVMSubnet -Name $vmAdapter.VMSubnet.Name | where {$_.VMNetwork.ID -eq $vmAdapter.VMNetwork.ID})
#$PortClassification = Get-SCPortClassification | where {$_.Name -eq "Guest Dynamic IP"}
$Pools = $Pools + (Get-SCStaticIPAddressPool -IPv4 | where {$_.VMsubnet.name -eq $vmAdapter.VMSubnet.Name})
Out-File -FilePath $fileName -InputObject $VMNetwork[$counter] -Append
Out-File -FilePath $fileName -InputObject $VMSubnet[$counter] -Append
Out-File -FilePath $fileName -InputObject $Pools[$counter] -Append
$counter = $counter + 1
}
if ($error.Count -ne 0)
{
write-host -ForegroundColor Red (Get-Date) "....Error is gathering information for $VMName. No changes made"
write-host -ForegroundColor Red (Get-Date) "....Exiting"
exit 1
}
$IP = @()
$counter = 0
foreach($vmAdapter in $VMOnDRAdapter)
{
if ($VMNetwork[$counter] -eq $null)
{
Write-Host -ForegroundColor Yellow (Get-Date) ".....Network Adapter '" $counter "' not connected"
$IP = $IP + $null
$counter = $counter + 1
continue
}
## Revoke IP
$error.Clear()
$IP = $IP +(Get-SCIPAddress –GrantToObjectId $VMOnDR.VirtualNetworkAdapters[$counter].ID)
Write-Host -ForegroundColor Yellow (Get-Date) "....Revoking IP " $IP[$counter] "from Replica VM"
Revoke-SCIPAddress $IP[$counter]
if ($error.count -eq 0)
{
Write-Host -ForegroundColor Green (Get-Date) "....." $IP[$counter] "revoke completed"
}
## Disconnect Replica VM
Write-Host -ForegroundColor Yellow (Get-Date) "....Disconnecting Replica VM from Network " $VMNetwork[$counter]
Set-SCVirtualNetworkAdapter -VirtualNetworkAdapter $VMOnDR.VirtualNetworkAdapters[$counter] -NoLogicalNetwork -NoConnection -NoPortClassification
Write-Host -ForegroundColor Green (Get-Date) "....Network Adapter '" $counter "' of Replica VM Disconnected"
$counter = $counter + 1
}
## Cancel failover
Write-Host -ForegroundColor Yellow (Get-Date) ".....We are going to Cancel Failover " $VMName " on both " $primaryHostName " and " $recoveryHostName
$error.Clear()
Stop-VMFailover -ComputerName $recoveryHostName -VMName $VMName
Start-Sleep -Seconds 10
Stop-VMFailover -ComputerName $primaryHostName -VMName $VMName
if ($error -ne 0)
{
write-host -ForegroundColor Red (Get-Date) ".....Error occured during Cancel Failover for VM $VMName"
write-host -ForegroundColor Red (Get-Date) ".....Please manually Cancel Failover on both Primary and Recovery Server"
Write-Host -ForegroundColor Red (Get-Date) ".....Press any key to continue..."
$ignoreKey = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
Write-Host -ForegroundColor Yellow (Get-Date) ".....Connecting Network(s) back to the Primary VM"
$counter = 0
foreach($vmAdapter in $VMOnDRAdapter)
{
if ($VMNetwork[$counter] -eq $null)
{
Write-Host -ForegroundColor Yellow (Get-Date) ".....Network Adapter '" $counter "' not connected"
$counter = $counter + 1
continue
}
Write-Host -ForegroundColor Yellow (Get-Date) "Granting " $IP[$counter] "to Primary VM"
Grant-SCIPAddress -GrantToObjectType "VirtualNetworkAdapter" -GrantToObjectID $VMOnPDAdapter[$counter].ID -StaticIPAddressPool $Pools[$counter] –IPAddress $IP[$counter]
Write-Host -ForegroundColor Green (Get-Date) "Granting IP completed"
Write-Host -ForegroundColor Yellow (Get-Date) "Connecting Primary VM to " $VMNetwork[$counter]
Set-SCVirtualNetworkAdapter -VirtualNetworkAdapter $VMOnPDAdapter[$counter] -IPv4AddressType static -VMNetwork $VMNetwork[$counter] -VMSubnet $VMSubnet[$counter]
Write-Host -ForegroundColor Green (Get-Date) "Network Adapter '" $counter "' of Primary VM connected to " $VMNetwork[$counter]
$counter = $counter + 1
}
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de