[Azure] 以 Azure PowerShell 結合虛擬機器擴展集 (Virtual Machine Scale Set) 快速佈建相同環境的虛擬機器

Azure 在以前服務管理模式 (Service Management Mode) 下最大的問題之一就是無法快速佈建大量的虛擬機器,這個問題雖然在管理機制升級到資源管理模式 (Resource Management Mode) 後似乎有改善的狀況,但在 ARM 初期,只是改變了 VM 各資源的組成方式,沒有真正解決快速部署的問題,這個問題一直到 Azure 發表了虛擬機器擴展集 (VMSS) 後才真的得到解決,不過網路上用的幾乎都是使用 Resource Template 的作法,這篇文章要教授如何使用 Azure PowerShell 來做到這件事,而且還是用自訂的作業系統映像,而不是平台本身的。

虛擬機器擴展集 (Virtual Machine Scale Set) 是 Azure 轉進資源管理觀點之後的代表作之一,以往要佈建大量虛擬機器,只能使用 PowerShell 跑迴圈,或是用 REST API 寫程式呼叫的作法來處理,一台虛擬機器可能要花上 10-20 分鐘建置,若是要建個 100 台,那最少也要 1000 分鐘,等於要花上 41 個小時都不停,才能完成佈建,時間成本實在太高,VMSS 正式將這個問題解決了,它可以利用平行佈建的方式,一次快速佈建很多虛擬機器,經過我的實測,以 PowerShell 指令方式佈建 10 台 VM,要花上 1 個多小時,而使用 VMSS,只要約 20 分鐘。

VMSS 是以 ARM (Azure Resource Management) 範本為基礎的技術,早期它還在 Preview 的時候,看到的教學幾乎都是編輯範本,即使到現在,微軟官方還是建議以範本方式處理,但是 ARM 範本的 JSON 結構複雜 (不是因為 JSON 本身,而是資源類型太多了,還有相依性之類的要管理),微軟雖然也釋出了像 Azure Resource Explorer、Visual Studio 的 Azure Resource Template、在入口網站直接能看到資源轉成的 Resource Template 等工具,但是仍然無法降低它的門檻。所幸微軟還是有提供 REST API 以及指令如 Azure PowerShell 和 Azure CLI 等佈建 VMSS 的作法。VMSS 是一個能快速佈建多虛擬機器的環境,因此它會有一些需求,像是它要求要有一個虛擬網路與子網路 (用來部署虛擬機器);一個負載平衡器以及一個對外的公用 IP 等,有了這些才能開始佈建 VMSS。

本文使用的 Azure PowerShell 是 v3.x 的版本 (撰寫時的最新版本為 v3.7),若您不是使用 v3.x,請到這裡安裝

首先,請先用 PowerShell 登入 Azure,指令為 Login-AzureRmAccount,若你的 Azure 帳戶有使用多個訂閱,而且登入的預設訂閱不是你要用的,請再使用 Select-AzureRmSubscription 切換到你想使用的訂閱,接著,請按下列步驟進行。

1. 建立一個資源群組,這個資源群組會在後面經常使用到。

$groupName = "vmssgroup"
$location = "eastasia"

$group = New-AzureRmResourceGroup -Name $groupName -Location $location -Force

2. 建立虛擬網路,本文使用的位址空間是 10.0.0.0/8,子網路的位址空間則是 10.1.0.0/16,可容納超過 1000 台虛擬機器。

$subnetName = 'vmsubnet'
$subnet = New-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix "10.1.0.0/16"

$vnetName = 'vmssnetwork'
$vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $groupName -Location $location -AddressPrefix "10.0.0.0/8" -Subnet $subnet
$vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $groupName

$subnetId = $vnet.Subnets[0].Id

3. 建立一個公用 IP 位址,它會用在待會建立的負載平衡器的對外介面上,且若沒有這個 IP,除非使用 VPN 連到虛擬網路,否則無法由外界存取。

$publicIp = New-AzureRmPublicIpAddress -Name "vmssnetpip" -ResourceGroupName $groupName -Location $location -AllocationMethod Dynamic -DomainNameLabel "testingvm"
$publicIp = Get-AzureRmPublicIpAddress -Name "vmssnetpip" -ResourceGroupName $groupName

4. 建立負載平衡器,負載平衡器需要的設定比較多,包括對公用網路的組態 (Front-end IP Configuration)、對私人網路的位址池 (Backend Address Pool)、輸入 NAT 池 (Inbound NAT Pool)。

公用網路的組態,要將剛才建的公用 IP 設定繫結起來,而私人網路的位址池,只要給它個名稱就好,後面會有子網路的關聯。

$frontAddressConfig = New-AzureRmLoadBalancerFrontendIpConfig -Name "vmsslb-frontpool" -PublicIpAddress $publicIp
$backAddressPool = New-AzureRmLoadBalancerBackendAddressPoolConfig -Name "vmsslb-backpool"

接著是輸入 NAT 池,可在這裡定義公用網路與私人網路的埠對應。在這裡我定義 3000-3999,共 1000 個埠,對應到內網的 Port 3389,也就是允許外面使用 RDP 協定連到 VMSS 內的 VM。

$inboundNatPool = New-AzureRmLoadBalancerInboundNatPoolConfig -Name "vmsslb-inboundnatpool" -FrontendIpConfigurationId $frontAddressConfig.Id -FrontendPortRangeStart 3000 -FrontendPortRangeEnd 3999 -Protocol Tcp -BackendPort 3389

接下來,就可以建立負載平衡器了。

$lb = New-AzureRmLoadBalancer -Name "vmsslb" -ResourceGroupName $groupName -Location $location -FrontendIpConfiguration $frontAddressConfig -BackendAddressPool $backAddressPool -InboundNatPool $inboundNatPool
$lb = Get-AzureRmLoadBalancer -Name "vmsslb" -ResourceGroupName $groupName

5. 設定 VMSS 虛擬機的網路位址來源組態,VMSS 會依照虛擬機器的順序配給 IP,以及前面定義的公用網路埠號。

$vmssIpConfig = New-AzureRmVmssIpConfig -Name "nic" -LoadBalancerInboundNatPoolsId $lb.InboundNatPools[0].Id -LoadBalancerBackendAddressPoolsId $lb.BackendAddressPools[0].Id -SubnetId $subnetId

6. 建立 VMSS 的組態,決定 VMSS 要部署在哪個位置 (資料中心)、內含的 VM 數量 (在本例是 10 台)、VM 等級 (在本例為 D1 v2) 以及更新原則。

$vmcount = 10
$vmssConfig = New-AzureRmVmssConfig -Location $location -SkuCapacity $vmcount -SkuName "Standard_D1_v2" -UpgradePolicyMode Automatic

7. 設定 VMSS 的網路介面組態,來源由前面設定的 VMSS 網路位址來源 IP 組態供應,這個設定會在每台 VM 上建立網路介面卡 (NIC)。

Add-AzureRmVmssNetworkInterfaceConfiguration -VirtualMachineScaleSet $vmssConfig -Name $subnetName -Primary $true -IpConfiguration $vmssIpConfig

8. 設定 VMSS 虛擬機器的作業系統基本設定,包含電腦名稱的前綴字、登入 VM 的帳戶名稱與密碼,帳戶名稱與密碼必須符合 Azure 的規範。

Set-AzureRmVmssOsProfile -VirtualMachineScaleSet $vmssConfig -ComputerNamePrefix "demovm" -AdminUsername "demouser" -AdminPassword "PaSS#W0Rd"

9. 設定 VMSS 的儲存設定,這個設定會指定映像的來源,以及每台 VM 的 OS Disk 的存放位置,目前 VMSS 要求映像來源和 OS Disk 的存放位置必須在同一個儲存帳戶內。

本文使用的是自訂的作業系統映像檔,因此要設定-Image 參數,指定作業系統映像檔的位置。

Set-AzureRmVmssStorageProfile -VirtualMachineScaleSet $vmssConfig -Image "https://myimagevhds.blob.core.windows.net/vhds/customosimage.vhd" -OsDiskCaching ReadWrite -OsDiskCreateOption FromImage -OsDiskOsType Windows -Name "vmssOsDisk" 

若是要使用平台的映像檔,可參考微軟文件

10. 設定 VMSS 虛擬機器的 VM Extensions,這個也可以不用,本文使用的是 BGInfo。

Add-AzureRmVmssExtension -VirtualMachineScaleSet $vmssConfig -Name "BGInfo" -Publisher "Microsoft.Compute" -Type "BGInfo" -TypeHandlerVersion "2.1"

11. 最後,使用前面的 VMSS 組態佈建 VMSS。

New-AzureRmVmss -Name "vmss" -ResourceGroupName $groupName -VirtualMachineScaleSet $vmssConfig

在佈建的過程中,可以到 Azure Portal 去看,可看到 VMSS 會一次部署指定數量的 VM,而不像以往 PowerShell 那樣一個一個建。

若需要一次停止所有的 VMSS 內的 VM,可使用下列指令。

Stop-AzureRmVmss -VMScaleSetName "vmss" -ResourceGroupName $groupName 

References:

Creating Virtual Machine Scale Sets using PowerShell cmdlets