2016年3月19日

Azure VM Scale Set

 

 

佈署大型系統時常遇到的問題便是如何快速大量的建立系統所需的機器資源;一般傳統的方式會將應用程式先安裝在某台機器上,將相關設定完成後,以此機器為樣本大量複製佈署新的機器;而當系統上線之後,常會遇到的狀況便是如果現有機器資源已經無法應付需求了,需要新增機器時,需要重新再做一次佈署機器的動作。

 

Azure上,我們可以透過Virtual MachineAuto-Scale功能,預先準備好所需要的機器,並設定Auto-Scale規則,在需要時才將機器開機來處理要求。這種方式雖然可以應付大部分的維運管理要求,但必須事先規劃好可能所需要的機器,事先建好機器。

透過Azure VM Scale Set (在本文撰寫的時間點2016/3/19仍為Preview階段),我們可以只先準備好自己的VM Base Image,透過VM Scale Set佈署一次,接著VM Scale Set便會依照我們的設定,自動在適當的時機新增或刪減機器資源,無須再多做人為操作,大幅減少維運的人工需求。

傳統的Azure Resource Manager架構

試想一個情況:我們想要架一個Web Server FarmInternet的要求會透過Load Balancer進來,並被導向Load Balancer後端任意一台Web Server處理。傳統的ARM架構中,要建立一台機器,你需要以下這些元件:

clip_image002[4]

我需要一個Storage存放VHD,每台機器需要至少一張網卡,每張網卡上需要綁定Private IP並加入Load Balancer backend pool

如果你需要多台機器,你需要不斷重複地建立這些元件,並加入Load Balancer

但是我們事實上並不關心這些Web Server,對系統來說,這些Web Server基本上是相同的;我們真正想要做的,只是告訴系統,我有一個Load Balancer幫我平衡HTTP/HTTPS負載。在Load Balancer後面,我需要一到多台機器,這些機器是以某個Base VM Image為基礎創建出來的;需要的時候我可以隨時新增或刪減機器。

同樣的情境,在VM Scale Set的架構下可以簡化成下圖這樣:

clip_image004[4]

我們定義好一組Scalable Storage作為VHD存放區,定義好Scalable NIC設定作為機器的網卡定義,然後告訴Scale Set我的Base VM Image資料、需要的機器數量及Load Balancer資訊;接著Azure VM Scale Set便會根據我的設定,自動地建立所需機器的數量,為每台機器加上一張網卡(Scalable NIC);需要時,自動把VHD分派到不同Storage存放(Scalable Storage)。只需要一次設定,就可以重複佈署。

步驟

接下來我會以Azure Quick Start template上的範例為基礎,說明如何設定VM Scale Set。在此範例中,我會透過VM Scale Set佈署以下的架構

clip_image006[4]

  • 首先我們需要Azure Powershell 1.0或是Azure CLI;在這篇文章中我會以Azure Powershell 1.0為範例
  • 執行Login-AzureRMAccount登入Azure

clip_image008[4]

  •    接著,如果尚未註冊Azure VM Scale Set,可以透過以下的指令註冊啟用

Register-AzureRmProviderFeature -FeatureName vmssApiPreviewV2Access -ProviderNamespace Microsoft.Compute

clip_image010[4]

  • 註冊完成後,先建立一個Resource Group以方便管理。

New-AzureRmResourceGroup -Name "michi-vmss-RG" -Location "East Asia

clip_image012[4]

以下我會針對比較需要注意的部分討論。

  • 首先定義我們需要的參數,包含:
  • instanceCount:告訴VM Scale Set我需要多少台Scalable的虛擬機器
  • adminUsername登入使用者的帳號;所有機器會以同樣的帳號登入。
  • adminPassword登入使用者的密碼;所有機器會以同樣的密碼登入。
  • 定義變數:
  • "imagePublisher": "MicrosoftWindowsServer"
  • "imageOffer": "WindowsServer"
  • "imageVersion": "2012-R2-Datacenter"

以上三個參數指定我們使用的Base Image

  • "publicIP1": "[concat(parameters('resourcePrefix'),'ip1')]", 指定Load BalancerPublic IP
  • "publicIP2": "[concat(parameters('resourcePrefix'),'ip2')]", 指定Jump Box機器的Public IP
  • "storageAccountSuffix": [ "a", "g", "m", "s", "y" ], 指定用以存放VHDStorage名稱尾碼,稍後我們會在Template中建立這些Storage
  • "wadlogs""wadperfcounters1""wadperfcounters2""wadcfgxstart""wadmetricsresourceid""wadcfgxend":指定Auto-Scale規則,系統開始運作之後,Azure Auto-Scale會監測在這裡指定的指標,並根據這裡指定的規則自動新增或刪減機器。

接著,開始定義Resources

 

  • 定義存放機器VHDStorage;在這裡我們會根據上面storageAcocuntSuffix數的大小建立5Storage Account來存放VHD。

(備註)目前這個時間點,Managed Storage尚未推出;待此服務推出後,搭配VM Scale Set就可以不需要事先處準備這些Storage Account

//Scalable Storage Account for VMSS

    {

      "type": "Microsoft.Storage/storageAccounts",

      "name": "[concat(parameters('resourcePrefix'), variables('storageAccountSuffix')[copyIndex()])]",

      "apiVersion": "2015-05-01-preview",

      "copy": {

        "name": "storageLoop",

        "count": 5

      },

      "location": "[resourceGroup().location]",

      "properties": {

        "accountType": "[variables('storageAccountType')]"

      }

    },

 

  • (重要)設定Load Balancer,在這裡我們指定一個inbountNatRule,將來源端(Internet)50000-50500 port對應到後端的3389 port
    • 在稍後的設定中我們會指定VM Scale Set的機器對應此NAT Rule,如此一來,當前端透過50000連線時,便會被導向第一台機器的3389 port、透過50001時,就會被導向第二台機器的3389 port,依此類推。

//Load Balancer

    {

      "apiVersion": "[variables('apiVersion')]",

      "name": "[variables('loadBalancerName')]",

      "type": "Microsoft.Network/loadBalancers",

      "location": "[resourceGroup().location]",

      "dependsOn": [

        "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIP1'))]"

      ],

      "properties": {

        "frontendIPConfigurations": [

          {

            "name": "loadBalancerFrontEnd",

            "properties": {

              "publicIPAddress": {

                "id": "[variables('publicIPAddressID1')]"

              }

            }

          }

        ],

        "backendAddressPools": [

          {

            "name": "bepool1"

          }

        ],

        "inboundNatPools": [

          {

            "name": "natpool1",

            "properties": {

              "frontendIPConfiguration": {

                "id": "[variables('frontEndIPConfigID')]"

              },

              "protocol": "tcp",

              "frontendPortRangeStart": 50000,

              "frontendPortRangeEnd": 50500,

              "backendPort": 3389

            }

          }

        ]

      }

    },

  • 設定VM Scale Set,其中幾個重要參數:
    • upgradePolicy:指定VM Scale Set的更新方式:
      • manual只有新的機器才會套用更新
      • automatic 所有機器都要套用更新,指定automatic時,如有更新,機器會被重開機。
    • vhdContainers:指定VHD要放在哪裡
    • loadBalancerInboundNatPools套用NAT RuleVM Scale Set的機器
    • extensionProfile:在這裡指定收集機器上的Performance IndexAuto-Scale會監測這些Index並根據我們的設定做Auto-Scale

//VM Scale Set

    {

      "type": "Microsoft.Compute/virtualMachineScaleSets",

      "apiVersion": "[variables('apiVersion')]",

      "name": "[parameters('vmSSName')]",

      "location": "[resourceGroup().location]",

      "dependsOn": [

        "storageLoop",

        "[concat('Microsoft.Storage/storageAccounts/', variables('diagnosticsStorageAccountName'))]",

        "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",

        "[concat('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]"

      ],

      "sku": {

        "name": "[variables('vmSize')]",

        "tier": "Standard",

        "capacity": "[parameters('instanceCount')]"

      },

      "properties": {

        "upgradePolicy": {

          "mode": "Manual"

        },

        "virtualMachineProfile": {

          "storageProfile": {

            "osDisk": {

              "vhdContainers": [

                "[concat('https://', parameters('resourcePrefix'), 'a.blob.core.windows.net/vmss')]",

                "[concat('https://', parameters('resourcePrefix'), 'g.blob.core.windows.net/vmss')]",

                "[concat('https://', parameters('resourcePrefix'), 'm.blob.core.windows.net/vmss')]",

                "[concat('https://', parameters('resourcePrefix'), 's.blob.core.windows.net/vmss')]",

                "[concat('https://', parameters('resourcePrefix'), 'y.blob.core.windows.net/vmss')]"

              ],

              "name": "vmssosdisk",

              "caching": "ReadOnly",

              "createOption": "FromImage"

            },

            "imageReference": {

              "publisher": "[variables('imagePublisher')]",

              "offer": "[variables('imageOffer')]",

              "sku": "[variables('imageVersion')]",

              "version": "latest"

            }

          },

          "osProfile": {

            "computerNamePrefix": "[parameters('vmSSName')]",

            "adminUsername": "[parameters('adminUsername')]",

            "adminPassword": "[parameters('adminPassword')]"

          },

          "networkProfile": {

            "networkInterfaceConfigurations": [

              {

                "name": "[variables('nicName2')]",

                "properties": {

                  "primary": "true",

                  "ipConfigurations": [

                    {

                      "name": "ip1",

                      "properties": {

                        "subnet": {

                          "id": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'),'/subnets/',variables('subnetName'))]"

                        },

                        "loadBalancerBackendAddressPools": [

                          {

                            "id": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Network/loadBalancers/',variables('loadBalancerName'),'/backendAddressPools/bepool1')]"

                          }

                        ],

                        "loadBalancerInboundNatPools": [

                          {

                            "id": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name,'/providers/Microsoft.Network/loadBalancers/',variables('loadBalancerName'),'/inboundNatPools/natpool1')]"

                          }

                        ]

                      }

                    }

                  ]

                }

              }

            ]

          },

          "extensionProfile": {

            "extensions": [

              {

                "name": "Microsoft.Insights.VMDiagnosticsSettings",

                "properties": {

                  "publisher": "Microsoft.Azure.Diagnostics",

                  "type": "IaaSDiagnostics",

                  "typeHandlerVersion": "1.5",

                  "autoUpgradeMinorVersion": true,

                  "settings": {

                    "xmlCfg": "[base64(concat(variables('wadcfgxstart'),variables('wadmetricsresourceid'),variables('wadcfgxend')))]",

                    "storageAccount": "[variables('diagnosticsStorageAccountName')]"

                  },

                  "protectedSettings": {

                    "storageAccountName": "[variables('diagnosticsStorageAccountName')]",

                    "storageAccountKey": "[listkeys(variables('accountid'), variables('apiVersion')).key1]",

                    "storageAccountEndPoint": "https://core.windows.net"

                  }

                }

              }

            ]

          }

        }

      }

},

  • 接著用以下的指令部署VM Scale Set

New-AzureRmResourceGroupDeployment -Name "michi031901" -ResourceGroupName "michi-vmss-RG" -TemplateFile "vmss-windows-jump-box-and-loadbalancer-nat.json"

clip_image014[4]

  • 建立完成後,可以在Portal上看到剛剛建立的資源

結語

透過VM Scale Set可以大幅簡化佈署的繁複手續。未來搭配Managed Storage服務後,更可以讓系統自動管理所需要的Storage Account。

另外要注意的是,目前如果要使用Custom VHD作為Base Image;此Custom VHD必須事先複製到Scalable Storage上;暫時的解決方式是參考這裡的Templa在佈署過程中將VHD複製到這些Scalable Storage中:https://github.com/Azure/azure-quickstart-templates/tree/master/301-custom-images-at-scale

Blog Archive

About Me