Hyper-V Replica and VMs Failover with PowerShell


Hyper-V Replica offers a convenient and efficient way to provide failover capabilities for Hyper-V VMs, especially outside of a Hyper-V cluster. In its simplest form, two nodes can be set in replication mode to provide near continuous protection for virtual machines, which is the scenario I will cover here. Among other benefits, it can also provide the capability to patch a host with minimal downtime for the hosted services. As mentioned, I will cover the scenario of setting up a Hyper-V Replica with two standalone nodes in the same domain. I will also make some notes about specific cluster configuration.

After setting up the Hyper-V hosts, Hyper-V Replica can be enabled by going to the Hyper-V Settings in the Hyper-V Manager and enabling replication under Replication Configuration.

Enabling Hyper-V Replica from within the Hyper-V Manager settings

For Hyper-V clusters, the process differs slightly and involves creating a Hyper-V Replica Broker on both clusters where replication will occur. I will cover configuring Hyper-V clusters in a later article and more information can be found in this Microsoft Technet article.

Going back to the screenshot, replication traffic occurs over either HTTP or HTTPS depending on the chosen options. Kerberos is the easiest if both nodes are in the same domain (or different domains with trust) and requires no additional configuration other than selecting the option. Traffic is sent over port 80 by default but the traffic is not encrypted.

For a more secure replication, such as replication over untrusted links, or in case the nodes are not in the same domain, certificate based replication is the way to go. For each of the Hyper-V hosts, you will need to request a certificate from a Certification Authority. If you have an enterprise CA, you can use a built-in certificate template or, preferably, create a new template named Hyper-V Replica. The most important point is that both Client Authentication and Server Authentication key usage must be present in the desired template. The root of the certification chain must also be trusted by the Hyper-V nodes.

CA Template for Hyper-V Replica

Request the certificate and make sure that the common name (CN) specified in the request is the FQDN of the Hyper-V host. Do the same procedure for the second host. Note that in the case of Hyper-V clusters, the request should contain the FQDN of the Hyper-V Replica Broker. Once the certificate has been installed in the Computer store, enable the HTTPS option and select the appropriate certificate. Replication traffic will now go over port 443 by default and it will be encrypted.

The second section in the screenshot above involves setting up authorized servers for replication and the default location for incoming replication data. If more than one replica server exists, authorized servers options can be used to tune how each server will replicate. Different storage locations can be assigned to different servers and servers can be denied replication privileges as well. In this scenario, we will use a single storage location. The Move Storage option can later be used to move the replicated data to other folders on the replica server. The option can be found by right-clicking a virtual machine and choosing Move.

Move Hyper-V VM Storage

Apply the chosen options and the server is now ready for Hyper-V Replica. It is recommended to do this configuration on both nodes since this will enable reverse replication functionality. This functionality is needed when virtual machines are failed over to the Hyper-V Replica host and the replication direction needs to be reversed to the previous primary host in order to maintain replication.

One last configuration that we will do is dedicate a NIC for the replication traffic. The easiest way to accomplish this for two standalone nodes is by editing the hosts files on each server and pointing the FQDN of the other server to the dedicated IP of the replication NIC. This configuration works for both Kerberos and Certificate-based authentication.

Hosts for dedicated NIC

You can now enable replication for the hosted virtual machines from Hyper-V manager by right-clicking a VM and choosing Enable Replication. The first option is to specify the destination Hyper-V Replica server. The second page shows the authentication type that you can choose which we discussed above. An additional recommended option is to compress the data that is transmitted over the network.

The third page allows you to choose the virtual hard disks to replicate. In general, it is preferable to dedicate a VHD for the guest operating system paging file and exclude that VHD from replication. This will minimize unneeded replication traffic.

VHDX Replication

Following that, Configure Replication Frequency determines the interval at which changes will be sent. 30 seconds, 5 minutes and 15 minutes are available with Windows 2012 R2 Hyper-V. Moving on, additional recovery points can be configured. By default, only the latest recovery point is maintained. That can be extended to provide more coverage by specifying the number of additional recovery point desired. The additional recovery points are created every hour. Moreover, VSS can be used to create application-consistent snapshots. This requires the latest Hyper-V Integration Components to be installed.

Recovery Points for Hyper-V Replica

The final option is Choose Initial Replication Method. Depending on the network link between the two nodes, sending the initial copy over the network should work fine. Otherwise, you can export the virtual machine and transfer it to the other Hyper-V host using external media. Finally, replication can be set to start immediately or it can scheduled to a later date.

Initial Replication for Hyper-V Replica

The selected virtual machine will now start the initial replication. Once the initial replication is finished, Hyper-V Replica can be used with both planned and unplanned failover situations. To note that  on the replica virtual machine, several networking options can be set. If you use static addressing for example, you can specify alternate failover IPv4 and IPv6 TCP/IP settings. The options can be found under the attached network adapter.

As for the failover processes, unplanned failover forces the virtual machine to start on the destination replication server. This is useful in situations where the primary server has failed. Failover can also be tested. This will create a test replica machine that you can perform tests on and validate functionality. The screenshot below is from the Hyper-V Replica server and shows the unplanned and test failover options.

Failover Actions for destination Hyper-V Replica server

Planned failover on the other hand is initiated from the primary Hyper-V host and gracefully fails over the virtual machine to the Hyper-V Replica server. The virtual machine needs to be turned off to perform this. Hyper-V verifies this fact and verifies the replica virtual machine. It will then proceed to send any remaining replication data before failing over the VM to the replica server.

Planned Failover with Hyper-V Replica

Two options can be specified. The first is to reverse the replication direction. Hyper-V will perform a further check to verify this operation and will reverse the replication once failover occurs. This requires that Hyper-V Replica is configured on both nodes as stated earlier. The second option is to start the replica VM after failover.

Planned failover is the better option to use (when available). It will allow a graceful failover with no data loss and can be used for many purposes, for example, balancing the load between two nodes or failing over virtual machines before patching the Hyper-V host.

Below is a PowerShell script that can automate failing over all the virtual machines on a given host. It is optimized for two nodes operations. Most of the code is commented for easy understanding. As an overview, the script performs these actions:

  1. Asks the user to specify the Hyper-V source host
  2. Retrieves a list of all hosted virtual machines on that host
  3. One by one, the script checks if the VM is running, is not a critical VM and if replication is enabled
    • If VM is running, the script will shut it down and perform a planned failover. The VM is started after failover and replication is reversed
    • If VM is a critical VM, the script will skip it (this functionality can be removed if not needed)
    • If VM is off, the script will directly perform a planned failover. The VM is not started after failover, replication is reversed

If any portion of the script is not clear, feel free to comment on this article or get in touch with me.

$SourceHost = Read-Host "Please specify the name of the source Hyper-V host to failover VMs from (HVNode1 or HVNode2)" #Read input from user to choose which server to failover VMs from

if ($SourceHost -eq 'HVNode1') #Setting the second server as destination depending on the user input above
{
    $DestinationHost = 'HVNode2'
}
elseif ($SourceHost -eq 'HVNode2')
{
    $DestinationHost = 'HVNode1'
}
else
{
    Write-Host 'Invalid source Hyper-V host. Please rerun the script and specify a valid Hyper-V host server' -ForegroundColor Red #If invalid host server was specified, script exists
    Exit #Instead of exit, script can be modified to go in a loop until a correct hostname is given
}

Write-Host "Setting source Hyper-V host as $SourceHost and destination Hyper-V host as $DestinationHost" #Informational message showing HV host servers

$VMs = Get-VM -ComputerName $SourceHost #Retrieve list of all VMs on selected source server

foreach ($VM in $VMs) #Look for each VM in that list
{
    $VMName = $VM.Name #Setting VMName variable for use in output
    $SkipVM = 0 #Future use

    if ($VM.State -eq 'Running' -and $VM.Name -ne 'CriticalVM1' -and $VM.Name -ne 'CriticalVM2') #If the VM is in a running state and is not one of the critical VMs (the latter functionality can be removed if not needed)
    {
        try
        {
            $GetVMReplicaDetails = Get-VMReplication -VMName $VM.Name -ErrorAction Stop #Checking to make sure the VM has actually replication set up
        }
        catch
        {
            Write-Host "Replication is not enabled for the virtual machine $VMName. Skipping it" -ForegroundColor Yellow #If not, VM is skipped and loop proceeds to next VM in list
            Continue
        }
        
        try
        {
            Write-Host "Stopping virtual machine $VMName"

            Stop-VM -ComputerName $SourceHost -Name $VM.Name -Force -ErrorAction Stop #VM is shut down. If user is logged or machine is locked, shut down operation is forced

            $State = (Get-VM $VM.Name -ComputerName $SourceHost).State #State variable for use with loop below. Precautionary only

            do #Looping to wait for VM to be in a shut down state. Precautionary only, command above only finishes executing when the VM is off
            {
                $State = (Get-VM $VM.Name -ComputerName $SourceHost).State
                Start-Sleep -Seconds 5
            }
            while ($State -eq 'Running')
        }
        catch
        {
            Write-Error -Message "Failed to shut down $VMName, skipping it" #If VM failed to shutdown, it will be skipped
            Continue
        }

        if ($SkipVM -eq 0) #Future use
        {
            try
            {
                Write-Host "Failing over virtual machine $VMName"

                Start-VMFailover –Prepare –VMName $VM.Name -ComputerName $SourceHost -Confirm:$false -ErrorAction Stop #Sends any remaining replication data waiting to replicate
                Start-VMFailover –VMName $VM.Name -ComputerName $DestinationHost -Confirm:$false -ErrorAction Stop #Initiate a failover for the current VM
                Set-VMReplication –Reverse –VMName $VM.Name -ComputerName $DestinationHost -Confirm:$false -ErrorAction Stop #Reverse replication direction for the current VM
                Start-VM –VMName $VM.Name -ComputerName $DestinationHost -ErrorAction Stop #Starts the failed over VM on the destination server

                Write-Host "$VMName has been failed over from $SourceHost to $DestinationHost and has been started"
            }

            catch
            {
                Write-Error "$VMName failed to failover to $DestinationHost"
                Continue
            }
        }
    }
    elseif ($VM.Name -eq 'CriticalVM1' -or $VM.Name -eq 'CriticalVM2') #If VM is one of the critical servers, warning message is shown. If not needed, entire section can be removed
    {
        Write-Warning "Virtual machine $VMName cannot be failed over as it is one of the specified critical VMs"
    }
    else #If VM is already in a turned off state
    {
        try
        {
            $GetVMReplicaDetails = Get-VMReplication -VMName $VM.Name -ErrorAction Stop #Making sure VM is enabled for replication
        }
        catch
        {
            Write-Host "Replication is not enabled for the virtual machine $VMName. Skipping it" -ForegroundColor Yellow
            Continue
        }
        
        #This section is needed if initial input for Hyper-V Host server was not FQDN
        $CheckPrimaryHost = $GetVMReplicaDetails.PrimaryServer + '.' #Should always return FQDN, but just in case, '.' is added
        $CheckPrimaryHost = $CheckPrimaryHost.SubString(0, $CheckPrimaryHost.IndexOf('.'))

        if ($CheckPrimaryHost -eq $SourceHost) #If the VM is primary on the chosen source HV server, failover will proceed.
        {
            try
            {
                Write-Host "Failing over the already turned off virtual machine $VMName" #Notice already turned off in output message

                Start-VMFailover –Prepare –VMName $VM.Name -ComputerName $SourceHost -Confirm:$false -ErrorAction Stop #Same as above, 1- replicating any remaining data, 2- fail over VM, 3- reverse replication.
                Start-VMFailover –VMName $VM.Name -ComputerName $DestinationHost -Confirm:$false -ErrorAction Stop
                Set-VMReplication –Reverse –VMName $VM.Name -ComputerName $DestinationHost -Confirm:$false -ErrorAction Stop
                #Notice VM is not started
               
                Write-Host "$VMName has been failed over from $SourceHost to $DestinationHost"
            }

            catch
            {
                Write-Error "$VMName failed to failover to $DestinationHost"
                Continue
            }
        }
        else #If the VM is the replica and not the primary, skip it. Can be modified to output nothing if desired, in this case, only VMs being failed over will appear in the output
        {
            Write-Host "The specified virtual machine $VMName cannot be failed over because the specified Hyper-V source host is hosting the replicated VM and not the primary VM" -ForegroundColor Yellow
        }
    }
}

A second script that you may wish to run after failover is a quick ping script. The script queries a list of VMs hosted on the Hyper-V host and pings them all. The script assumes that the VM name is the same as the host name. I am performing some string replacements to convert the host name to FDQN (VM names and host names end with the domain they belong to). Moreover, the script removes spaces that may be present in the virtual machine name or in the retrieved list.

#Does not really matter which node you query if using the same name for the replicated VMs as well
$HostNames = (Get-VM -ComputerName 'HVNode1').Name

# $ sign to indicate only at the end of the string. Space is in case you use spaces in the VM's name but not in the host name
$HostNames = $HostNames -replace '-AD1$', '-AD1.ad1.test.local' -replace '-AD2$', '-AD2.ad2.test.local' -replace ' ', ''

foreach ($Server in $HostNames)
{
    try
    {
        Test-Connection $Server -Count 1 -ErrorAction Stop
    }

    catch
    {
        Write-Warning $_.Exception.Message
        Continue
    }
}

To note that Hyper-V cmdlets need to be available for these scripts to execute successfully.

One final note, starting with Server 2012 R2, Hyper-V Replica can now be extended to a third host. For example, Host1 replicates to Host2 then Host2 replicates to Host3. This enhances business continuity and disaster recovery by adding an extra layer of protection in terms of replication.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.