HyperV

¿VMs con MAC Address Duplicadas en Hyper-V?

*Nota importante: Si tus VMHost estan siendo administrados por System Center VMM, este articulo no aplica, ya que el rango de MAC Addresses es administrado por SCVMM.

Es posible que construyendo sus primeros Hosts de Hyper-V encuentren que algunas de sus VMs que viven en hosts diferentes tengan problemas de conectividad, esto debido a que las MAC address de las VMs se duplican y le genera conflictos a la tabla ARP de los switches. ¿Porque sucede esto?

Hyper-V tiene un mecanismo en el cual cada VMHost genera un rango de MAC Address que serán asignados a cada vNIC conectada a los vSwitches declarados dentro del Host. Esta Mac Address se conforma de la siguiente manera:

00-15-5D

– XX –

XX

– 00

Rango predefinido para HyperV Basado en el 3er Octeto de la dirección IP del Host Basado en el 4to Octeto de la direccion IP Rango inicial y Rango final

 

Los últimos 2 dígitos son “00” para el rango inicial y “FF” para el rango final.

Existe un pequeño issue con esta lógica y es que debido a que todos los servidores al momento de ser instalados, el rango de Mac Address asignado es siempre el mismo, siendo en todos los casos 00-15-5D-00-00-00 hasta  00-15-5D-00-00-FF. Si no ajustamos previamente este rango, o bien, si el vSwitch es generado antes de asignarle una dirección IP estática al VMHost, y se generan los vSwitches con el VMHost usando las direcciones IP de APIPA (Automatic Private Internet Protocol Addressing)  y  además tenemos en nuestro ambiente 2 o mas VMhosts, cada uno de estos generará MAC address para las VMs y vNICs empezando desde el rango inferior e ira incrementado en uno.  Aqui un ejemplo:

VMHost 1

VM1      00-15-5D-00-00-00

VM2      00-15-5D-00-00-01

VMHost 2

VM3      00-15-5D-00-00-00

VM4      00-15-5D-00-00-01

En el ejemplo anterior, tendriamos un conflicto con la MAC address entre la VM1 y VM3, y el mismo caso para la VM2 y VM4

¿Como evitar esto?

La recomendación es configurar previamente los rangos de MAC address que serán asignados a las VMs en cada VMHost, esto puede realizarse con Powershell y tansolo es necesario tener armada una tabla de los rangos a usar basados en la tabla mostrada al principio de esta entrada. Asi podrian armar una tabla similar a la siguiente:

Servername MinMACAddress MaxMACAddress
VMHost1 00-15-5D-46-0B-00 00-15-5D-46-0B-FF
VMHost2 00-15-5D-46-0C-00 00-15-5D-46-0C-FF
VMHost3 00-15-5D-46-0D-00 00-15-5D-46-0D-FF

En el ejemplo mostrado en la tabla, los primeros 3 bloques, es el rango pre-definido por HyperV (“00-15-5D”). Para el 4to bloque (“46”)corresponderia al 3er Octeto de las direcciones IP de nuestros VMHosts, como en nuestro caso el segmento es “172.18.70.0/24”, vemos que el 3er octeto siempre será “70”, lo cual en hexadecimal es….. “46” 🙂  . El cuarto bloque corresponde al 4to octeto de la dirección IP, por ejemplo para el VMHost1 la dirección IP es 172.18.70.11, al tomar el 4to octeto (“11”) y convertirlo a hexadecimal, obtenemos “0B” y como podrán deducir el la IP del VMHost2 es 172.18.70.12. Ya con esta tabla armada, la podemos tener en un CSV y tomar el siguiente bloque para usar en Powershell.

 


$MacAddress = import-csv C:\MacAddresses.csv
#En este loop se establece el Rango de MacAddress para cada VMHost.
foreach($server in $MacAddress ){
    if($env:computername -eq $server.ServerName){
        Set-VMHost -MacAddressMinimum $server.MinMacAddress -MacAddressMaximum $server.MaxMacAddress
    }
}

La lógica de este pedazo de código es simple. Tan solo hay que pegar en un CSV la tabla que preparamos previamente con los rangos de MAC Addresses, este archivo es importado en una variable y se procesa. Si se encuentra que el Hostname del servidor donde esta siendo ejecutado, coincide con el valor de la columna “Servername“, entonces se establece el rango de MacAddresses establecido en las columnas “MinMacAddress” y “MaxMacAddress“. Si desean hacerlo de manera manual, pueden usar el cmdlet Set-VMHost con los parametros MacAddressMinimum y MacAddressMaximum. Con esto, las MAC Address asiganadas a cada VM en cada VMHost, variaran.

 

Trabajando con HyperV y vSwitches

Se nos ha presentado la necesidad de configurar múltiples Host de Hyper-V en nuestro ambiente laboral, para el cual el tiempo (como siempre) es limitado. Una de las partes que toma un tiempo en configurar son los “Teaming” de Windows así como los switches virtuales.

Con Hyper-V se puede tomar la ventaja de utilizar alguno de los vSwitches para poder Administrar el Hypervisor al crear una vNIC (algo asi como los vkernel ports de VMWare).
En el ejemplo especifico que se muestra a continuación estamos realizando 3 Teaming (de 2 NICs cada una) y a traves de estos separando el trafico de Administracion (Admin), de trafico para las VMs (BackNet) y del “expuesto” a Internet, para nuestro caso varia un poco, pero esta es la base que se utiliza. Toda la información utilizada para este script proviene de un archivo separado por comas (CSV) el cual contiene la información del servidor, Interfase, MacAddress y Grupo al que pertenecera (Admin, BackNet o FrontNet). Obviamente esta información debe ser obtenida de antemano.

El siguiente código esta pensado para ser utilizado como modulo de PowerShell, así que es necesario importarlo.

function Rename-NICs{
    [CmdletBinding()]
    param(
        
        [parameter(Mandatory=$true)]
        [string]$PathCSV
    )

    #Se importa la información desde el CSV
    $CSV=Import-Csv $PathCSV | Select Server,Interface,MacAddress,Grupo
    #Se inicializa una variable que servira para evitar duplicados en los nombres de las interfaces
    $CounterBack=1
    $CounterAdmin=1
    $CounterFront=1

    foreach($item in $CSV) {
        if (get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress}) {
            switch($item.Grupo) {
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de Administración, se etiqueta con esta función.
                'Admin' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyAdministracion$CounterAdmin"
                    $CounterAdmin=$CounterAdmin+1
                }
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de BackNet (VMs), se etiqueta con esta función.
                'BackNet' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyBackNet$CounterBack"
                    $counterBack=$CounterBack+1
                }
                #Si la MAC address en el archivo esta etiquetada para ser parte del vSwitch de FrontNet (VMs), se etiqueta con esta función.
                'FrontNet' {
                    get-NetAdapter | where {$_.MacAddress -eq $item.MacAddress} | Rename-NetAdapter -NewName "phyFrontNet$CounterFront"
                    $counterFront=$CounterFront+1
                }
            }
        }
    }
} 

<#La siguiente función se encarga de crear los NIC Teaming y ademas genera los vSwitches.
La parte de la asignación de las direcciones IP puede realizarse a traves de una variable, pero sigo trabajando en eso.
#>
Function Crea-NicTeams {
    [CmdletBinding()]

    $AdministracionNICS = Get-NetAdapter | where {$_.Name -like 'phyAdministracion*'} | %{$_.Name}
    $BackNetNICS = Get-NetAdapter | where {$_.Name -like 'phyBackNet*'} | %{$_.Name}
    $FrontNetNICS = Get-NetAdapter | where {$_.Name -like 'phyFrontNet*'} | %{$_.Name}

    New-NetLbfoTeam -Name TeamAdministracion -TeamMembers $AdministracionNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name AdminSwitch -NetAdapterName TeamAdministracion –MinimumBandwidthMode Weight –AllowManagementOS $false

    New-NetLbfoTeam -Name TeamBackNet -TeamMembers $BackNetNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name BackNetSwitch -NetAdapterName TeamBackNet –MinimumBandwidthMode Weight –AllowManagementOS $false

    New-NetLbfoTeam -Name TeamFrontNet -TeamMembers $FrontNetNICS -TeamingMode SwitchIndependent -LoadBalancingAlgorithm Dynamic -Confirm:$False
    New-VMSwitch -Name FrontNetSwitch -NetAdapterName TeamFrontNet –MinimumBandwidthMode Weight –AllowManagementOS $false


    #Crea las vNICs para Administración del Host de Hyper-V
    Add-VMNetworkAdapter -ManagementOS -Name vAdminNet -switchName AdminSwitch
    Rename-NetAdapter -Name "vEthernet (vAdminNet)" -NewName vAdminNet
    Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vAdminNet -Access -VLanID 457
    New-NetIpAddress -InterfaceAlias vAdminNet -IPAddress 172.20.67.41 -PrefixLength 25 -DefaultGateway 172.23.67.127

    #Crea las vNIC dentre de la vLAN alcanzable para las VMs del Host de Hyper-V
    Add-VMNetworkAdapter -ManagementOS -Name vBackNet -switchName AdminSwitch
    Rename-NetAdapter -Name "vEthernet (vBackNet)" -NewName vBackNet
    Set-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName vBackNet -Access -VLanID 417
    New-NetIpAddress -InterfaceAlias vBackNet -IPAddress 172.20.47.41 -PrefixLength 25 -DefaultGateway 172.23.46.127

}