Azure Stack HCI Üzerinde Çalışan Tenant VM’ler İçin MAC Adres Atama Stratejileri

Azure Stack HCI, Windows Sunucuları (Hyper-V), Storage Spaces Direct ve Azure-inspired SDN içeren hiperbütünleşik altyapı (HCI) çözümüdür. Cluster sunucuları, Windows Server Failover Clustering özelliğini kullanarak ortak yapılandırmaları ve kaynakları paylaşır.

Bir Windows Failover Cluster, yüksek erişilebilirlik sağlamak için bir cluster’da çalışan birden fazla Windows sunucusundan oluşur; yani bir sunucu devre dışı kalırsa, başka bir node üzerindeki yükleri devralır. Failover cluster’da birden çok sanal makine oluşturabiliriz. Sanal makineler farklı tenant ağlarına bağlanabilir. Bu durumda, bir ağda statik IP ile bağlı bir VM’in cluster içinde sanal makine başka bir node’a taşındığında aynı ağ yapılandırmasını korumasını sağlamamız gerekir. Bu, VM için statik MAC/statik IP atayarak mümkündür. Ancak VM’ye atanacak boşta ve benzersiz MAC nasıl sağlanabilir. Bu sorunu çözmenin farklı yolları vardır. Bu makalede, bu sorunu çözmek için bazı yöntemleri inceleyeceğiz.

Önce, tenant VM oluşturmak için gereken temel adımları anlayalım. Stack-HCI’da tenant ağına bağlı tenant VM oluşturmak için aşağıdaki adımlar gerçekleştirilir.

Yukarıdaki adımları gerçekleştirmek için aşağıdaki PowerShell komutları kullanılabilir.

# 1. vm creation with static MAC
New-VM -Generation 2 -Name "MyVM" -Path "C:\VMs\MyVM" -MemoryStartupBytes 4GB -VHDPath "C:\VMs\MyVM\Virtual Hard Disks\WindowsServer2016.vhdx" -SwitchName "SDNvSwitch"

Set-VM -Name "MyVM" -ProcessorCount 4

# Setting static MAC
Set-VMNetworkAdapter -VMName "MyVM" -StaticMacAddress "00-11-22-33-44-55"

# Creating network interface on networkcontroller with same mac/static IP
$vnet = Get-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId "Contoso_WebTier"
$vmnicproperties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceProperties
$vmnicproperties.PrivateMacAddress = "001122334455"
$vmnicproperties.PrivateMacAllocationMethod = "Static"
$vmnicproperties.IsPrimary = $true

$vmnicproperties.DnsSettings = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceDnsSettings
$vmnicproperties.DnsSettings.DnsServers = @("24.30.1.11", "24.30.1.12")

$ipconfiguration = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfiguration
$ipconfiguration.resourceid = "MyVM_IP1"
$ipconfiguration.properties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfigurationProperties
$ipconfiguration.properties.PrivateIPAddress = "24.30.1.101"
$ipconfiguration.properties.PrivateIPAllocationMethod = "Static"

$ipconfiguration.properties.Subnet = New-Object Microsoft.Windows.NetworkController.Subnet
$ipconfiguration.properties.subnet.ResourceRef = $vnet.Properties.Subnets[0].ResourceRef

$vmnicproperties.IpConfigurations = @($ipconfiguration)
New-NetworkControllerNetworkInterface –ResourceID "MyVM_Ethernet1" –Properties $vmnicproperties –ConnectionUri $uri

$nic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId "MyVM_Ethernet1"

#Do not change the hardcoded IDs in this section, because they are fixed values and must not change.
# 3. Finally make association of vm network adapter with nic created in last step
$FeatureId = "9940cd46-8b06-43bb-b9d5-93d50381fd56"

$vmNics = Get-VMNetworkAdapter -VMName "MyVM"

$CurrentFeature = Get-VMSwitchExtensionPortFeature -FeatureId $FeatureId -VMNetworkAdapter $vmNics

if ($CurrentFeature -eq $null) {
$Feature = Get-VMSystemSwitchExtensionPortFeature -FeatureId $FeatureId

$Feature.SettingData.ProfileId = "{$($nic.InstanceId)}"
$Feature.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}"
$Feature.SettingData.CdnLabelString = "TestCdn"
$Feature.SettingData.CdnLabelId = 1111
$Feature.SettingData.ProfileName = "Testprofile"
$Feature.SettingData.VendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}"
$Feature.SettingData.VendorName = "NetworkController"
$Feature.SettingData.ProfileData = 1

Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $Feature -VMNetworkAdapter $vmNics
} else {
$CurrentFeature.SettingData.ProfileId = "{$($nic.InstanceId)}"
$CurrentFeature.SettingData.ProfileData = 1

Set-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $CurrentFeature -VMNetworkAdapter $vmNics
}
Get-VM -Name "MyVM" | Start-VM

Windows Failover Cluster içinde taşıma işlemi yaptığınızda VM’lerin düzgün çalışmasını sağlamak için statik MAC ve statik IP atamamız gerekiyor. Burada kullanılabilir ve benzersiz MAC elde etmek kullanıcıları zorlayan bir durum. Bu sorunu çözmek için aşağıdaki yöntemleri inceleyeceğiz.

Rastgele MAC oluşturma

Bu çok basit bir yaklaşımdır, rastgele bir MAC oluşturacağız ve aynısını kullanacağız.

Poweshell komutu

New-VM -Name $vm_name -MemoryStartupBytes $vm_memory -BootDevice VHD -VHDPath $image_path -Path $vm_data_path -Generation $vm_generation -SwitchName $switch_name

Add-ClusterVirtualMachineRole -vmname $vm_name -Name $vm_name
Start-Sleep -Seconds 3

############## Random MAC address generation and assignment
# script block for mac address assingment kept in retry block
$mac_address = Retry-Command -ScriptBlock {
# do something
# found used in az-auto-setup
#$mac_address=("{0:D12}" -f ( Get-Random -Minimum 0 -Maximum 99999 ))
$mac_address = (0..5 | ForEach-Object { '{0:x}{1:x}' -f (Get-Random -Minimum 0 -Maximum 15), (Get-Random -Minimum 0 -Maximum 15) }) -join '-'
write-host "Tring to set : $mac_address"
Set-VMNetworkAdapter -VMName $vm_name -StaticMacAddress "$mac_address"
write-host "Mac set succssfully: $mac_address"
Start-Sleep -Milliseconds 500
Write-host $( Get-VMNetworkAdapter -VMName $vm_name ).MacAddress
return $mac_address
}

write-host "Mac set succssfully: $mac_address"

Write-host 'VM created..'


##########################################################################

# network configuration starts here..
# you can refer for more info: https://learn.microsoft.com/en-us/windows-server/networking/sdn/manage/create-a-tenant-vm#prerequisites
$vnet = Get-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId $vnet_name



$vmnicproperties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceProperties
# give same mac address below as created before..
$mac = -join($mac_address.split("-")).toupper()
$vmnicproperties.PrivateMacAddress = $mac
Write-host $mac
$vmnicproperties.PrivateMacAllocationMethod = "Static"
$vmnicproperties.IsPrimary = $true

$vmnicproperties.DnsSettings = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceDnsSettings
#$vmnicproperties.DnsSettings.DnsServers = @("192.168.1.254", "8.8.8.8")
$vmnicproperties.DnsSettings.DnsServers = $dns_server
$ipconfiguration = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfiguration
$ipconfiguration.resourceid = $vm_name + "_IP1"
$ipconfiguration.properties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfigurationProperties
$ipconfiguration.properties.PrivateIPAddress = $ip_address
$ipconfiguration.properties.PrivateIPAllocationMethod = "Static"

$ipconfiguration.properties.Subnet = New-Object Microsoft.Windows.NetworkController.Subnet

# do: programatically decide subnet full ref, or form path directly
# $ipconfiguration.properties.subnet.ResourceRef = $vnet.Properties.Subnets[0].ResourceRef
$ipconfiguration.properties.subnet.ResourceRef = "/virtualNetworks/" + $vnet_name + "/subnets/" + $subnet_name
$vmnicproperties.IpConfigurations = @($ipconfiguration)
$NIC_name = $vm_name + "_Eth1"
New-NetworkControllerNetworkInterface -ResourceID $NIC_name -Properties $vmnicproperties -ConnectionUri $uri -Confirm:$false -force
Write-host 'NIC config created..'
Start-Sleep -Seconds 8

$nic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId $NIC_name

#########################################################################

#Do not change the hardcoded IDs in this section, because they are fixed values and must not change.

$FeatureId = "9940cd46-8b06-43bb-b9d5-93d50381fd56"

$vmNics = Get-VMNetworkAdapter -VMName $vm_name

$CurrentFeature = Get-VMSwitchExtensionPortFeature -FeatureId $FeatureId -VMNetworkAdapter $vmNics

if ($CurrentFeature -eq $null)
{
$Feature = Get-VMSystemSwitchExtensionPortFeature -FeatureId $FeatureId

$Feature.SettingData.ProfileId = "{$( $nic.InstanceId )}"
$Feature.SettingData.NetCfgInstanceId = "{56785678-a0e5-4a26-bc9b-c0cba27311a3}"
$Feature.SettingData.CdnLabelString = "TestCdn"
$Feature.SettingData.CdnLabelId = 1111
$Feature.SettingData.ProfileName = "Testprofile"
$Feature.SettingData.VendorId = "{1FA41B39-B444-4E43-B35A-E1F7985FD548}"
$Feature.SettingData.VendorName = "NetworkController"
$Feature.SettingData.ProfileData = 1

Add-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $Feature -VMNetworkAdapter $vmNics
}
else
{
$CurrentFeature.SettingData.ProfileId = "{$( $nic.InstanceId )}"
$CurrentFeature.SettingData.ProfileData = 1

Set-VMSwitchExtensionPortFeature -VMSwitchExtensionFeature $CurrentFeature -VMNetworkAdapter $vmNics
}
Write-host 'finally applying setting..'
Start-Sleep -Seconds 5



Get-VM -Name $vm_name | Start-VM

Ancak bu çözüm aşağıdaki sorunları beraberinde getiriyor.

Her node için özel benzersiz MAC adres havuzu aralığı atama ve node MAC adres aralığı havuzundan MAC adresi oluşturma

Her node (hyper-v) özel benzersiz MAC adres havuz aralığı atayabiliriz. Böylece yeni bir ağ arabirimi oluşturmak istediğimizde, VM’nin çalışacağı node havuzundan önce boşta bir MAC alırız. Aynı MAC, vm ağ adaptörü ve ağ arabirimi üzerinde statik IP ile aynı yapılır.

Following is an example of MAC pool range distribution plan for 255 clusters, 16 hosts each:

00-15-5D-[c1][c2]-[h1][v1]-[v2][v3]
field c1, c2: will indicate a cluster. 00 to FF : Max 255 clusters can be created.

field h1 - will be for host/node identification in a cluster. 0 to F = max 16 hosts in a cluster.

field v1,v2,v3 will be used for vms. 000 to FFF = 16*16*16 = total 4096 possible vms/network interfaces per node can be created.

Ancak buradaki zorluk, node havuzundan boşta MAC almak için kullanılabilecek herhangi bir API veya komut bulunmamasıdır. Çözüm olarak MAC’in havuzdan atanmış olması için boşta dinamik MAC’i almak için geçici bir ağ adaptörü oluşturmak ve VM’yi bir an için başlatmak. Ardından VM’yi durdurmalı ve değişikliği geri almalı ve aynı MAC’i kullanarak statik bir MAC oluşturmalı ve aynı adımları takip etmelisiniz.

# creating new network adapter with dynamic MAC
Add-VMNetworkAdapter -VMName $vm_name -SwitchName $switch_name -Name $adapter_name

# starting and stopping vm to get free MAC from node pool
Start-VM -VMName $vm_name; Stop-VM -VMName $vm_name -Force

# reading assigned dynamic MAC
$mac_address = (Get-VMNetworkAdapter -VMName $vm_name -Name $adapter_name).MacAddress

# make same MAC as static
Set-VMNetworkAdapter -VMName $vm_name -Name $adapter_name -StaticMacAddress $mac_address

# rest steps are same for network interface creation

Network controller servisinden boşta MAC alın ve aynısını VM ağ adaptöründe kullanın

Her Stack-hci cluster özel bir merkezi ağ denetleyici servisi bulunmaktadır. Burada, ağ denetleyici servisinde global MAC adres aralığı havuzunu kurabiliriz. Ağ denetleyici servisinde dinamik yapılandırmaya sahip yeni bir ağ arabirimi oluşturduğumuzda, global havuzdan bir MAC atanır. Bu, merkezi bir servis olduğundan çok güvenilir bir çözümdür.

# Creating network interface with dynamic MAC config on network controller
$vmnicproperties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceProperties
$vmnicproperties.PrivateMacAllocationMethod = "Dynamic"
$vmnicproperties.IsPrimary = $true

$vmnicproperties.DnsSettings = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceDnsSettings
$vmnicproperties.DnsSettings.DnsServers = $dns_server
$ipconfiguration = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfiguration
$ipconfiguration.resourceid = $vm_name + "_IP1"
$ipconfiguration.properties = New-Object Microsoft.Windows.NetworkController.NetworkInterfaceIpConfigurationProperties
$ipconfiguration.properties.PrivateIPAddress = $ip_address
$ipconfiguration.properties.PrivateIPAllocationMethod = "Static"

$ipconfiguration.properties.Subnet = New-Object Microsoft.Windows.NetworkController.Subnet

$ipconfiguration.properties.subnet.ResourceRef = "/virtualNetworks/" + $vnet_name + "/subnets/" + $subnet_name
$vmnicproperties.IpConfigurations = @($ipconfiguration)
$NIC_name = $vm_name + "_Eth1"
New-NetworkControllerNetworkInterface -ResourceID $NIC_name -Properties $vmnicproperties -ConnectionUri $uri -Confirm:$false -force
Write-host 'NIC config created..'
Start-Sleep -Seconds 8

$nic = Get-NetworkControllerNetworkInterface -ConnectionUri $uri -ResourceId $NIC_name
# Read obtained free MAC from global pool
$mac_address = $nic.Properties.PrivateMacAddress -replace '..(?!$)', '$&-'

###### Vm creation flow starts from here. We will set static MAC here
New-VM -Name $vm_name -MemoryStartupBytes $vm_memory -BootDevice VHD -VHDPath $image_path -Path $vm_data_path -Generation $vm_generation -SwitchName $switch_name
Add-ClusterVirtualMachineRole -vmname $vm_name -Name $vm_name
Set-VMNetworkAdapter -VMName $vm_name -StaticMacAddress "$mac_address"
write-host "Mac set succssfully: $mac_address"
Exit mobile version