vMotion (or any other VMkernel) Network-changer

2020-03-05 Off By vvanvierzen

Over the years I have been involved in a lot of workload migrations. Most of them where VM based migrations. A long time ago I have done some storage level migrations and used VMware converter quite often to onboard workloads into a virtualized environment. Nowadays however and with the newer vSphere versions, the majority of the migrations is nothing more than a (cross-vCenter) vMotion.

The technique behind this is pretty straight forward and has been described a million times in various blogposts already. So, I won’t bother you with that. But preparing for migration and to get all the pre-reqs in place, can be a bit more time consuming. Whether you use the fling or a script to migrate your workloads, you will have to make sure the hosts can talk “vMotion” to each other.

Basically, there are two options to prepare:

  1. Ensure that vMotion is on its own net stack so that it is routable. This is by far the easiest option and requires no additional rework to be done if all is set up correctly from scratch. When doing migrations however, the source environment is often outdated and more often doesn’t have vMotion running in its own IP stack. It also happens that creating the required gateway and ensure proper routing is not an option for the customer.
  2. Option 2 is to stretch the vMotion VLAN between the 2 environments. Using this option, you could just re-use the existing VLAN and assign some unused IP addresses to the new hosts. Knowing IT-People though, it will be very likely that they will want to align IP addresses for the new hosts and perhaps also align the VLAN’s used. For example, the Mgmt. IP’s last byte for host ESXi-05 will also be .5. IT’s staff’s default OCD behavior will make them wat to have vSAN / vMotion IP addresses also ending on .5 (and I don’t say that I do not agree 😊)

So, running into forced option 2 a lot of times, what will need to be done to prepare for a successful  migration:

  1. Ensure vMotion VLAN is stretched between old and new environment
  2. Align the use of jumbo frames between the old and new environment
  3. Ensure vMotion VMkernel ports are in the same subnets

Of course, you can manually adjust settings on either the old or the new environment, but being an It fellow, you will want to automate this. Here is our example scenario

Old cluster vMotion settings:

  • MTU 1500
  • vMotion VLAN 10
  • IP addresses in use: 192.168.100.1 – 192.168.100.10 in use for VMkernel ports
  • No vMotion net stack configured

New cluster vMotion settings:

  • MTU 9000
  • vMotion VLAN 20
  • IP addresses in use 192.168.200.1 – 192.168.100.10 in use for VMkernel ports
  • vMotion net stack configured w/o gateway

As the “new” environment does not run any active workloads yet, the decision was made to do the temp. reconfiguration of VMkernel ports on that environment. This would also decrease the risk of making errors on an environment which is in production.

We needed some logics to be able to automatically change the IP addresses and VLAN back and forward (comes also in handy for testing etc) so we identified that in the “old” environments vMotion IP range, the address range 192.168.100.101 – 192.168.100.110 was not in use. Good news, because now we can use those IP’s for the “new” environment.

Above gave me enough info to go ahead and create a PowerShell script to automate this.

The script contains the logic to add 100 or subtract 100 depending on the menu choice. The first 2 bytes are predefined as they are the same for both the old and new environment. The third byte is also configured with the menu option you select. It additionally changes the MTU depending on the selected menu option and finally, it optionally changes the VLAN id on the vMotion portgroup.

#Gather Info
$vCenter = Read-Host "Enter the FQDN of the vCenter server you want to connect to"
$targetClusterName = Read-Host "Enter the name of the cluster you would like to configure"
$userName = "administrator@vsphere.local" #enter username here
$targetVcPassword = Read-Host ("Enter Password for vCenter user: " + $userName) -AsSecureString:$true
$credTarget = New-Object System.Management.Automation.PSCredential -ArgumentList $userName,$targetVcPassword
$targetVcConnection = Connect-VIServer -Server $vCenter -Credential $credTarget
write-host ("Succesfully connected to vCenter server: " + $targetVcConnection.Name + ".") -ForegroundColor Green

#Shows menus for setting cluster to Temp migration settings or to reset settings once migration is done and to specify if the VLAN ID on the portgroup needs to be modified
function showMenuMigrateOrOriginal {
    param (
        [string]$migrateOrOriginal = "Do you want to configure migrate settings, or restore original?"
        )
        cls
        Write-Host ("================== " + $migrateOrOriginal + " ==================") -ForegroundColor Cyan

        Write-Host "Press '1' to configure `"Migration settings.`""
        Write-Host "Press '2' to configure `"Original settings.`""
}

showMenuMigrateOrOriginal
$input = Read-Host "Please make your selection"
Switch ($input) {
    '1' {$thirdByte = 100
         $fourthByteMod = [int]::Parse(100)
         $mtu = 1500
         $vMotionVlan = 10}
    '2' {$thirdByte = 200
         $fourthByteMod = [int]::Parse(-100)
         $mtu = 9000
         $vMotionVlan = 20}
}

function showMenuVLAN {
    param (
        [string]$vlanMenu = "Do you want to modify the portgroup's VLAN ID?"
        )
        cls
        Write-Host ("================== " + $vlanMenu + " ==================") -ForegroundColor Cyan

        Write-Host "Press '1' to set VLAN id to change the VLAN according to your previous choice for migration or original"
        Write-Host "Press '2' to leave the VLAN config in place"
}

showMenuVLAN
$input = Read-Host "Please make your selection"
Switch ($input) {
    '1' {$vlanChange = $true
		 $vMotionPG = Read-Host "Enter the name of the vMotion portgroup, this is required to change the VLAN ID"}
    '2' {$vlanChange = $false}
}

#Get target cluster and hosts
$targetVmHosts = Get-Cluster -Name $targetClusterName | Get-VMHost
#$targetVmHosts = @() #used for testing a single host!!
#$targetVmHosts += get-vmhost -Name "<hostname>"   #used for testing a single host!!

#Reconfigure vMotion VMK (IP and MTU)
foreach ($vmHost in $targetVmHosts){
	$vMotionVmk = get-vmhost $vmHost | Get-VMHostNetworkAdapter | where vmotionEnabled -eq $true
	$currentVMotionIP = $vMotionVmk.IP
	$fourthByte = [int]::Parse($currentVMotionIp.Split(".")[3]) + $fourthByteMod
	$newVMotionIp = "192.168." + $thirdByte.ToString() + "." + $fourthByte.ToString() #network bits needs to be modified if using different networks
	$vMotionVmk | Set-VMHostNetworkAdapter -IP $newVMotionIp -Mtu $mtu -Confirm:$false
}

#Reconfigure vMotion Portgroup (VLAN)
if ($vlanChange){
    Get-VDPortgroup -Name $vMotionPg | Set-VDPortgroup -VlanId $vMotionVlan
}

The script could use a little polishing (stuff like error handling), but I didn’t have the time to do so yet. So it is likely that the script will be updated at a later stage.

Feel free to use and modify it. I figured I would share it since it could serve all kind of purposes 😊