Azure Load Balancer : 支援 IPv6

sparkdev發表於2019-01-29

越來越多的網站開始支援 IPv6,即使是哪些只提供 api 服務的站點也需要支援 IPv6,比如蘋果應用商店中的 app 早就強制要求伺服器端支援 IPv6 了。
筆者在前文《Azure Load Balancer : 簡介》中介紹了通過 Azure 門戶站點建立基礎的 Azure Load Balancer 配置,本文將接著介紹如何建立支援 IPv6 的 Azure Load Balancer。

關於 IPv6 的一些限制

讓我們先來了解一下 Azure Load Balancer 在 IPv6 支援方面的一些限制(完整的限制列表請參考這裡):

  • 無法在 Azure 門戶中新增 IPv6 負載均衡規則。 只能通過模板、CLI 或 PowerShell 建立規則。
  • 無法將現有 VM 升級為使用 IPv6 地址。 為此必須部署新 VM。
  • 無法將公共 IPv6 地址分配給 VM, 只能分配給負載均衡器。

這三條限制看起來讓人很沮喪!其中第一條意味著我們沒辦法通過 UI 簡單的建立支援 IPv6 的 Load Balancer;第二條則讓老機器失去了升級的機會;第三條則把 IPv6 的支援完全綁死到了 Load Balancer 上!

換個角度看問題也許能讓人心情愉快些:
不支援 UI 操作就是逼著我們寫指令碼,剛好可以朝著基礎架構即程式碼的方向前進!
不支援現有虛機的升級,可以拋掉歷史的包袱輕裝上陣!
不支援將公共 IPv6 地址分配給 VM,那就只用在 Load Balancer 上維護 IPv6 的配置!

使用 PowerShell 指令碼建立 Load Balancer

既然無法通過 Azure 門戶站點上的 UI 建立支援 IPv6 的 Load Balancer,筆者就選擇通過 PowerShell 指令碼完成這個任務, 我們來建立一個具有兩臺後端虛機的 Load Balancer,下面是指令碼中的主要邏輯。

定義指令碼中所需的變數
為了能更好的重用該指令碼,筆者把所需的變數都定義到了指令碼的開頭處,雖然變數的數目很多,但是隻要修改 prodNamePrefix、userName、sshPublicKey 和 location 等幾個關鍵變數的值指令碼就可以工作了:

# 資源名稱的字首
$prodNamePrefix = "Nick"
$lowerProdNamePrefix = $prodNamePrefix.ToLower()

# vm user name
$userName = "nick"
# vm user public key
$sshPublicKey = "xxxxxxxxxx"

# resource loacation
$location = "japaneast"
# resource group name
$rgName = $prodNamePrefix + "LBGroup"
...

建立 Resource Group、虛擬網路及其虛擬子網

# 建立 Resource Group
New-AzureRmResourceGroup -Name $rgName -location $location

# 虛擬網路及其虛擬子網
$backendSubnet = New-AzureRmVirtualNetworkSubnetConfig `
                 -Name $subnetName `
                 -AddressPrefix $subnetPrefix
$vnet = New-AzureRmvirtualNetwork -Name $vnetName `
                                  -ResourceGroupName $rgName `
                                  -Location $location `
                                  -AddressPrefix $vnetPrefix `
                                  -Subnet $backendSubnet

建立 Load Balancer

# 建立 Load Balancer 的公共 IP
$publicIPv4 = New-AzureRmPublicIpAddress `
              -Name $publicIpv4Name `
              -ResourceGroupName $rgName `
              -Location $location `
              -AllocationMethod Static `
              -IpAddressVersion IPv4 `
              -DomainNameLabel $dnsLabelv4
$publicIPv6 = New-AzureRmPublicIpAddress `
              -Name $publicIpv6Name `
              -ResourceGroupName $rgName `
              -Location $location `
              -AllocationMethod Dynamic `
              -IpAddressVersion IPv6 `
              -DomainNameLabel $dnsLabelv6

# 建立 Load Balancer 的 Frontend IP
$FEIPConfigv4 = New-AzureRmLoadBalancerFrontendIpConfig `
                -Name $frontendV4Name `
                -PublicIpAddress $publicIPv4
$FEIPConfigv6 = New-AzureRmLoadBalancerFrontendIpConfig `
                -Name $frontendV6Name `
                -PublicIpAddress $publicIPv6

# 建立 Load Balancer 的 Backend pools
$backendpoolipv4 = New-AzureRmLoadBalancerBackendAddressPoolConfig `
                   -Name $backendAddressPoolV4Name
$backendpoolipv6 = New-AzureRmLoadBalancerBackendAddressPoolConfig `
                   -Name $backendAddressPoolV6Name

# 建立 Load Balancer 的 Inbound NAT rules
$inboundNATRule1v4 = New-AzureRmLoadBalancerInboundNatRuleConfig `
                     -Name $natRule1V4Name `
                     -FrontendIpConfiguration $FEIPConfigv4 `
                     -Protocol TCP `
                     -FrontendPort 10022 `
                     -BackendPort 22
$inboundNATRule2v4 = New-AzureRmLoadBalancerInboundNatRuleConfig `
                     -Name $natRule2V4Name `
                     -FrontendIpConfiguration $FEIPConfigv4 `
                     -Protocol TCP `
                     -FrontendPort 20022 `
                     -BackendPort 22

# 建立 Load Balancer 的 Health probes
$healthProbe = New-AzureRmLoadBalancerProbeConfig -Name $probeV4V6Name `
                                                  -Protocol Tcp `
                                                  -Port 22 `
                                                  -IntervalInSeconds 15 `
                                                  -ProbeCount 2

# 建立 Load Balancer 的 Load balancing rules
$lbrule1v4http = New-AzureRmLoadBalancerRuleConfig `
                 -Name $lbRule1V4HTTPName `
                 -FrontendIpConfiguration $FEIPConfigv4 `
                 -BackendAddressPool $backendpoolipv4 `
                 -Probe $healthProbe `
                 -Protocol Tcp `
                 -FrontendPort 80 `
                 -BackendPort 80
$lbrule1v6http = New-AzureRmLoadBalancerRuleConfig `
                 -Name $lbRule1V6HTTPName `
                 -FrontendIpConfiguration $FEIPConfigv6 `
                 -BackendAddressPool $backendpoolipv6 `
                 -Probe $healthProbe `
                 -Protocol Tcp `
                 -FrontendPort 80 `
                 -BackendPort 80
$lbrule1v4https = New-AzureRmLoadBalancerRuleConfig `
                  -Name $lbRule1V4HTTPSName `
                  -FrontendIpConfiguration $FEIPConfigv4 `
                  -BackendAddressPool $backendpoolipv4 `
                  -Probe $healthProbe `
                  -Protocol Tcp `
                  -FrontendPort 443 `
                  -BackendPort 443
$lbrule1v6https = New-AzureRmLoadBalancerRuleConfig `
                  -Name $lbRule1V6HTTPSName `
                  -FrontendIpConfiguration $FEIPConfigv6 `
                  -BackendAddressPool $backendpoolipv6 `
                  -Probe $healthProbe `
                  -Protocol Tcp `
                  -FrontendPort 443 `
                  -BackendPort 443

# 建立 Load Balancer
$loadbalancer = New-AzureRmLoadBalancer `
                -ResourceGroupName $rgName `
                -Name $lbName `
                -Location $location `
                -FrontendIpConfiguration $FEIPConfigv4,$FEIPConfigv6 `
                -InboundNatRule $inboundNATRule2v4,$inboundNATRule1v4 `
                -BackendAddressPool $backendpoolipv4,$backendpoolipv6 `
                -Probe $healthProbe `
                -LoadBalancingRule $lbrule1v4http,$lbrule1v6http,`
                $lbrule1v4https,$lbrule1v6https

建立兩個虛擬網路卡

# 重新獲得虛擬網路及其虛擬子網的例項,
# 否則建立網路卡時會提示沒有指定虛擬子網
$vnet = Get-AzureRmVirtualNetwork -Name $vnetName `
                                  -ResourceGroupName $rgName
$backendSubnet = Get-AzureRmVirtualNetworkSubnetConfig `
                 -Name $subnetName `
                 -VirtualNetwork $vnet

$nic1IPv4 = New-AzureRmNetworkInterfaceIpConfig `
            -Name "IPv4IPConfig" `
            -PrivateIpAddressVersion "IPv4" `
            -Subnet $backendSubnet `
            -LoadBalancerBackendAddressPool $backendpoolipv4 `
            -LoadBalancerInboundNatRule $inboundNATRule1v4
$nic1IPv6 = New-AzureRmNetworkInterfaceIpConfig `
            -Name "IPv6IPConfig" `
            -PrivateIpAddressVersion "IPv6" `
            -LoadBalancerBackendAddressPool $backendpoolipv6
$nic1 = New-AzureRmNetworkInterface `
        -Name $nic1Name `
        -IpConfiguration $nic1IPv4,$nic1IPv6 `
        -ResourceGroupName $rgName `
        -Location $location

$nic2IPv4 = New-AzureRmNetworkInterfaceIpConfig `
            -Name "IPv4IPConfig" `
            -PrivateIpAddressVersion "IPv4" `
            -Subnet $backendSubnet `
            -LoadBalancerBackendAddressPool $backendpoolipv4 `
            -LoadBalancerInboundNatRule $inboundNATRule2v4
$nic2IPv6 = New-AzureRmNetworkInterfaceIpConfig `
            -Name "IPv6IPConfig" `
            -PrivateIpAddressVersion "IPv6" `
            -LoadBalancerBackendAddressPool $backendpoolipv6
$nic2 = New-AzureRmNetworkInterface `
        -Name $nic2Name `
        -IpConfiguration $nic2IPv4,$nic2IPv6 `
        -ResourceGroupName $rgName `
        -Location $location

建立虛擬機器並分配新建的 NIC

# 建立 Availability Set
New-AzureRmAvailabilitySet -Name $availabilitySetName `
                           -Sku Aligned `
                           -PlatformFaultDomainCount 2 `
                           -PlatformUpdateDomainCount 5 `
                           -ResourceGroupName $rgName `
                           -location $location
$availabilitySet = Get-AzureRmAvailabilitySet `
                   -Name $availabilitySetName `
                   -ResourceGroupName $rgName

# 建立使用者 Credential
$securePassword = ConvertTo-SecureString $userPassword `
                                         -AsPlainText -Force
$userCred = New-Object System.Management.Automation.PSCredential `
            ($userName, $securePassword)

# 建立第一臺虛機,可以以同樣的方式建立第二臺虛機
$vm1 = New-AzureRmVMConfig -VMName $vm1Name `
                           -VMSize $vmSize `
                           -AvailabilitySetId $availabilitySet.Id
$vm1 = Set-AzureRmVMOperatingSystem `
       -VM $vm1 `
       -Linux `
       -ComputerName $vm1ComputerHostName `
       -Credential $userCred `
       -DisablePasswordAuthentication
$vm1 = Set-AzureRmVMSourceImage `
       -VM $vm1 `
       -PublisherName Canonical `
       -Offer UbuntuServer `
       -Skus $vmVersion `
       -Version "latest"
$vm1 = Set-AzureRmVMBootDiagnostics `
       -VM $vm1 `
       -Disable
$vm1 = Add-AzureRmVMNetworkInterface `
       -VM $vm1 `
       -Id $nic1.Id `
       -Primary
$vm1 = Set-AzureRmVMOSDisk `
       -VM $vm1 `
       -Name $vm1DiskName `
       -CreateOption FromImage `
       -StorageAccountType $storageAccountTypeName
Add-AzureRmVMSshPublicKey `
    -VM $vm1 `
    -KeyData $sshPublicKey `
    -Path "/home/$userName/.ssh/authorized_keys"
New-AzureRmVM -ResourceGroupName $rgName `
              -Location $location `
              -VM $vm1

到這裡我們的 Load Balancer 已經建立完成了,完整的指令碼程式碼請參考這裡

在 Azure 門戶上的 Cloud Shell 中執行指令碼

假設你已經編輯好了自己的 Load Balancer 建立指令碼,並命名為 azureloadbalancer.sp1。讓我們先把指令碼上傳到 Azure 門戶上的 Cloud Shell 中,然後在 Cloud Shell 中執行該指令碼:

指令碼執行完成後,一個支援 IPv6 的 Load Balancer 就部署成功了:

總結

雖然寫指令碼比 UI 操作的難度要高一些,但是一旦這些指令碼寫好了今後就可以通過重用這些指令碼來提升自動化的程度,絕對是物有所值!在後續的文章中,筆者將介紹如何使用 PowerShell 指令碼擴充套件支援 IPv6 的 Load Balancer 後端的虛機池。

參考:
用 PowerShell 建立支援 IPv6 的 Azure Load Balancer
Powershell load balancer
Azure Load Balancer 對 IPv6 的支援

相關文章