Udostępnij za pośrednictwem


Konfigurowanie przełączania awaryjnego maszyny wirtualnej między sieciami wirtualnymi

W tym artykule opisano sposób obsługi replikacji i trybu failover maszyn wirtualnych w programie System Center Virtual Machine Manager (VMM) między sieciami wirtualnymi, gdy nie używasz usługi Azure Site Recovery do zarządzania odzyskiwaniem po awarii.

  • Użyj usługi Azure Site Recovery do replikowania maszyn wirtualnych. Program VMM nie zarządza Hyper-V Replica bez Site Recovery, dlatego należy użyć poleceń cmdlet PowerShell Hyper-V Replica do automatyzacji operacji.
  • W przypadku odzyskiwania po awarii zalecamy używanie oddzielnych podstawowych i pomocniczych sieci wirtualnych. Podstawowe maszyny wirtualne łączą się z siecią podstawową i replikami maszyn wirtualnych z siecią pomocniczą. Dzięki temu obie maszyny wirtualne mogą być jednocześnie połączone z siecią.
  • Jeśli masz jedną sieć wirtualną, użyj usługi Site Recovery, aby zautomatyzować zarządzanie siecią przy użyciu funkcji mapowania sieci. Jeśli nie używasz usługi Site Recovery, należy dokładnie sprawdzić wymagania wstępne i kolejność dołączania maszyn wirtualnych do sieci. W szczególności maszyna wirtualna repliki i podstawowa maszyna wirtualna nie muszą być jednocześnie połączone z pojedynczą siecią wirtualną. W przeciwnym razie rekordy CA-PA mogą zostać usunięte w programie VMM i spowodować utratę łączności sieciowej.

Przykładowe rozwiązanie

To przykładowe rozwiązanie opisuje następujące środowisko:

  • Pojedynczy serwer programu VMM zarządza lokacjami podstawowymi i dodatkowymi.
  • Podstawowe i repliki maszyn wirtualnych są hostowane w jednej wirtualnej sieci Hyper-V.
  • Chcesz uruchomić planowane przejście w tryb failover i zachować adres IP maszyny wirtualnej po przejściu w tryb failover.
  • Maszyny wirtualne mają adresy IPv4.

Przed rozpoczęciem

Poniżej przedstawiono kilka zagadnień przed rozpoczęciem konfigurowania trybu failover maszyny wirtualnej między sieciami wirtualnymi:

  • Upewnij się, że ustawienia przełącznika wirtualnego i przełącznika logicznego są prawidłowe i pasują do sieci szkieletowej programu VMM. Jeśli tak nie jest, operacje dołączania do sieci mogą zakończyć się niepowodzeniem po przejściu w tryb failover.

  • Podstawowa maszyna wirtualna musi być połączona z siecią wirtualną

  • Maszyna wirtualna repliki nie może być połączona z siecią

  • Do każdej karty sieciowej podstawowej maszyny wirtualnej musi być przypisany tylko jeden adres IP. Uruchom to polecenie, aby to zapewnić. Jeśli na maszynie wirtualnej znajduje się więcej niż jedna połączona karta sieciowa, uruchom proces dla każdej karty, zmieniając indeks tablicy.

    $VMOnPD = Get-SCVirtualMachine -Name "VM Name" | where {$_.IsPrimaryVM -eq $true}
    Get-SCIPAddress –GrantToObjectId $VMOnPD.VirtualNetworkAdapters[0].ID``
    
  • Upewnij się, że adres IP przypisany do maszyny wirtualnej przez system operacyjny jest taki sam jak adres IP wyświetlany powyżej. Zaloguj się do maszyny wirtualnej i uruchom polecenie ipconfig , aby to sprawdzić.

  • Upewnij się, że tabele wyszukiwania są poprawnie ustawione na serwerze podstawowym oraz serwerze repliki. W tym celu uruchom następujące polecenie na każdym serwerze i upewnij się, że istnieje wpis odpowiadający adresowi IP zwróconym powyżej: Get-NetVirtualizationLookupRecord

  • Sprawdź, czy adres IP to IPv4, a nie IPv6

  • Przed uruchomieniem skryptów upewnij się, że obie maszyny wirtualne są wyłączone.

  • Upewnij się, że stan replikacji jest włączony na obu maszynach wirtualnych.

Oto co robi ten skrypt:

  1. Dla każdej karty sieciowej w głównej maszynie wirtualnej przechowuje adres IP, sieć VM i pulę adresów IP.
  2. Cofa wszystkie adresy IP dla każdej karty sieciowej na maszynach wirtualnych głównych i pomocniczych.
  3. Rozłącza wszystkie karty sieciowe.
  4. Przełącz w tryb awaryjny maszyny wirtualne podstawowe i zapasowe.
  5. Opcjonalnie uruchamia replikację odwrotną.
  6. Przypisuje ten sam adres IP (dla każdej karty sieciowej) dla maszyny wirtualnej repliki.
  7. Dołącza każdą kartę sieciową na replikowanej maszynie wirtualnej do sieci maszyn wirtualnych przechowywanych w kroku 1.

Uruchamianie skryptu

Skrypt przyjmuje dwa argumenty:

  • $VMName — nazwa maszyny wirtualnej
  • $ReverseRep — argument logiczny określający, czy należy wykonać replikację odwrotną, czy nie
    • Jeśli $true zostanie przekazana, replikacja odwrotna zostanie uruchomiona natychmiast i nie będzie można anulować trybu failover później.
    • Po pomyślnym ukończeniu tego skryptu, gdy $ReverseRep jest $true:
      • Podstawowa maszyna wirtualna musi być w stanie Przygotowany do zaplanowanego przełączenia awaryjnego replikacji.
      • Maszyna wirtualna repliki musi być w stanie replikacji „Failover complete”.
    • Jeśli $false jest przekazywana, replikacja odwrotna nie jest wykonywana. ReverseRepORCancelFO.ps1 może służyć do wykonywania replikacji odwrotnej lub anulowania trybu failover.
    • Po pomyślnym ukończeniu skryptu z ustawionym $ReverseRep na $false:
      • Podstawowa maszyna wirtualna musi być w stanie Przygotowany do zaplanowanego przełączenia awaryjnego replikacji.
      • Maszyna wirtualna repliki musi być w stanie replikacji „Failover complete”.

Jeśli skrypt nie wykonuje żadnych kroków, musisz ręcznie wykonać kroki zakończone niepowodzeniem, a następnie wrócić do okna programu PowerShell. Kroki skryptu obejmują awarię podstawowej maszyny wirtualnej, awarię repliki maszyny wirtualnej oraz opcjonalnie replikację odwrotną.

Uruchom skrypt:

 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
}