Snabbstart: Skapa en skalningsuppsättning för virtuella Windows-datorer med Bicep

Med en virtuell maskinskalningsuppsättning kan du distribuera och hantera en uppsättning automatiskt skalande virtuella datorer. Du kan skala antalet virtuella datorer i vm-skalningsuppsättningen manuellt eller definiera regler för automatisk skalning baserat på resursanvändning som PROCESSOR, minnesbehov eller nätverkstrafik. En Azure-lastbalanserare distribuerar sedan trafik till de virtuella datorinstanserna i VM-skalningsuppsättningen. I den här snabbstarten skapar du en VM-skalningsuppsättning och distribuerar ett exempelprogram med Bicep.

Bicep är ett domänspecifikt språk (DSL) som använder deklarativ syntax för att distribuera Azure-resurser. Det ger koncis syntax, tillförlitlig typsäkerhet och stöd för återanvändning av kod. Bicep erbjuder den bästa redigeringsupplevelsen för dina infrastruktur-som-kod-lösningar i Azure.

Förutsättningar

Om du inte har en Azure-prenumeration, skapa ett gratis konto innan du börjar.

Granska den Bicep-filen

Bicep-filen som används i den här snabbstarten kommer från Azure-snabbstartsmallar.

@description('String used as a base for naming resources. Must be 3-61 characters in length and globally unique across Azure. A hash is prepended to this string for some resources, and resource-specific information is appended.')
@minLength(3)
@maxLength(61)
param vmssName string

@description('Size of VMs in the VM Scale Set.')
param vmSku string = 'Standard_D2s_v3'

@description('The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter & 2016-Datacenter, 2019-Datacenter.')
@allowed([
  '2019-DataCenter-GenSecond'
  '2016-DataCenter-GenSecond'
  '2022-datacenter-azure-edition'
])
param windowsOSVersion string = '2022-datacenter-azure-edition'

@description('Security Type of the Virtual Machine.')
@allowed([
  'Standard'
  'TrustedLaunch'
])
param securityType string = 'TrustedLaunch'

@description('Number of VM instances (100 or less).')
@minValue(1)
@maxValue(100)
param instanceCount int = 3

@description('When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true.')
param singlePlacementGroup bool = true

@description('Admin username on all VMs.')
param adminUsername string = 'vmssadmin'

@description('Admin password on all VMs.')
@secure()
param adminPassword string

@description('The base URI where artifacts required by this template are located. For example, if stored on a public GitHub repo, you\'d use the following URI: https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vmss-windows-webapp-dsc-autoscale/.')
param _artifactsLocation string = deployment().properties.templateLink.uri

@description('The sasToken required to access _artifactsLocation.  If your artifacts are stored on a public repo or public storage account you can leave this blank.')
@secure()
param _artifactsLocationSasToken string = ''

@description('Location of the PowerShell DSC zip file relative to the URI specified in the _artifactsLocation, i.e. DSC/IISInstall.ps1.zip')
param powershelldscZip string = 'DSC/InstallIIS.zip'

@description('Location of the  of the WebDeploy package zip file relative to the URI specified in _artifactsLocation, i.e. WebDeploy/DefaultASPWebApp.v1.0.zip')
param webDeployPackage string = 'WebDeploy/DefaultASPWebApp.v1.0.zip'

@description('Version number of the DSC deployment. Changing this value on subsequent deployments will trigger the extension to run.')
param powershelldscUpdateTagVersion string = '1.0'

@description('Location for all resources.')
param location string = resourceGroup().location

@description('Fault Domain count for each placement group.')
param platformFaultDomainCount int = 1

var vmScaleSetName = toLower(substring('vmssName${uniqueString(resourceGroup().id)}', 0, 9))
var longvmScaleSet = toLower(vmssName)
var addressPrefix = '10.0.0.0/16'
var subnetPrefix = '10.0.0.0/24'
var vNetName = '${vmScaleSetName}vnet'
var publicIPAddressName = '${vmScaleSetName}pip'
var subnetName = '${vmScaleSetName}subnet'
var loadBalancerName = '${vmScaleSetName}lb'
var publicIPAddressID = publicIPAddress.id
var lbProbeID = resourceId('Microsoft.Network/loadBalancers/probes', loadBalancerName, 'tcpProbe')
var natPoolName = '${vmScaleSetName}natpool'
var bePoolName = '${vmScaleSetName}bepool'
var lbPoolID = resourceId('Microsoft.Network/loadBalancers/backendAddressPools', loadBalancerName, bePoolName)
var natStartPort = 50000
var natEndPort = 50119
var natBackendPort = 3389
var nicName = '${vmScaleSetName}nic'
var ipConfigName = '${vmScaleSetName}ipconfig'
var frontEndIPConfigID = resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', loadBalancerName, 'loadBalancerFrontEnd')
var osType = {
  publisher: 'MicrosoftWindowsServer'
  offer: 'WindowsServer'
  sku: windowsOSVersion
  version: 'latest'
}
var securityProfileJson = {
  uefiSettings: {
    secureBootEnabled: true
    vTpmEnabled: true
  }
  securityType: securityType
}
var imageReference = osType
var webDeployPackageFullPath = uri(_artifactsLocation, '${webDeployPackage}${_artifactsLocationSasToken}')
var powershelldscZipFullPath = uri(_artifactsLocation, '${powershelldscZip}${_artifactsLocationSasToken}')

resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = {
  name: loadBalancerName
  location: location
  properties: {
    frontendIPConfigurations: [
      {
        name: 'LoadBalancerFrontEnd'
        properties: {
          publicIPAddress: {
            id: publicIPAddressID
          }
        }
      }
    ]
    backendAddressPools: [
      {
        name: bePoolName
      }
    ]
    inboundNatPools: [
      {
        name: natPoolName
        properties: {
          frontendIPConfiguration: {
            id: frontEndIPConfigID
          }
          protocol: 'Tcp'
          frontendPortRangeStart: natStartPort
          frontendPortRangeEnd: natEndPort
          backendPort: natBackendPort
        }
      }
    ]
    loadBalancingRules: [
      {
        name: 'LBRule'
        properties: {
          frontendIPConfiguration: {
            id: frontEndIPConfigID
          }
          backendAddressPool: {
            id: lbPoolID
          }
          protocol: 'Tcp'
          frontendPort: 80
          backendPort: 80
          enableFloatingIP: false
          idleTimeoutInMinutes: 5
          probe: {
            id: lbProbeID
          }
        }
      }
    ]
    probes: [
      {
        name: 'tcpProbe'
        properties: {
          protocol: 'Tcp'
          port: 80
          intervalInSeconds: 5
          numberOfProbes: 2
        }
      }
    ]
  }
}

resource vmScaleSet 'Microsoft.Compute/virtualMachineScaleSets@2023-09-01' = {
  name: vmScaleSetName
  location: location
  sku: {
    name: vmSku
    tier: 'Standard'
    capacity: instanceCount
  }
  properties: {
    overprovision: true
    upgradePolicy: {
      mode: 'Automatic'
    }
    singlePlacementGroup: singlePlacementGroup
    platformFaultDomainCount: platformFaultDomainCount
    virtualMachineProfile: {
      storageProfile: {
        osDisk: {
          caching: 'ReadWrite'
          createOption: 'FromImage'
        }
        imageReference: imageReference
      }
      osProfile: {
        computerNamePrefix: vmScaleSetName
        adminUsername: adminUsername
        adminPassword: adminPassword
      }
      securityProfile: ((securityType == 'TrustedLaunch') ? securityProfileJson : null)
      networkProfile: {
        networkInterfaceConfigurations: [
          {
            name: nicName
            properties: {
              primary: true
              ipConfigurations: [
                {
                  name: ipConfigName
                  properties: {
                    subnet: {
                      id: vNet.properties.subnets[0].id
                    }
                    loadBalancerBackendAddressPools: [
                      {
                        id: lbPoolID
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
      extensionProfile: {
        extensions: [
          {
            name: 'Microsoft.Powershell.DSC'
            properties: {
              publisher: 'Microsoft.Powershell'
              type: 'DSC'
              typeHandlerVersion: '2.9'
              autoUpgradeMinorVersion: true
              forceUpdateTag: powershelldscUpdateTagVersion
              settings: {
                configuration: {
                  url: powershelldscZipFullPath
                  script: 'InstallIIS.ps1'
                  function: 'InstallIIS'
                }
                configurationArguments: {
                  nodeName: 'localhost'
                  WebDeployPackagePath: webDeployPackageFullPath
                }
              }
            }
          }
        ]
      }
    }
  }
}

resource publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-04-01' = {
  name: publicIPAddressName
  location: location
  properties: {
    publicIPAllocationMethod: 'Static'
    dnsSettings: {
      domainNameLabel: longvmScaleSet
    }
  }
}

resource vNet 'Microsoft.Network/virtualNetworks@2023-04-01' = {
  name: vNetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        addressPrefix
      ]
    }
    subnets: [
      {
        name: subnetName
        properties: {
          addressPrefix: subnetPrefix
        }
      }
    ]
  }
}

resource autoscalehost 'Microsoft.Insights/autoscalesettings@2022-10-01' = {
  name: 'autoscalehost'
  location: location
  properties: {
    name: 'autoscalehost'
    targetResourceUri: vmScaleSet.id
    enabled: true
    profiles: [
      {
        name: 'Profile1'
        capacity: {
          minimum: '1'
          maximum: '10'
          default: '1'
        }
        rules: [
          {
            metricTrigger: {
              metricName: 'Percentage CPU'
              metricResourceUri: vmScaleSet.id
              timeGrain: 'PT1M'
              statistic: 'Average'
              timeWindow: 'PT5M'
              timeAggregation: 'Average'
              operator: 'GreaterThan'
              threshold: 50
            }
            scaleAction: {
              direction: 'Increase'
              type: 'ChangeCount'
              value: '1'
              cooldown: 'PT5M'
            }
          }
          {
            metricTrigger: {
              metricName: 'Percentage CPU'
              metricResourceUri: vmScaleSet.id
              timeGrain: 'PT1M'
              statistic: 'Average'
              timeWindow: 'PT5M'
              timeAggregation: 'Average'
              operator: 'LessThan'
              threshold: 30
            }
            scaleAction: {
              direction: 'Decrease'
              type: 'ChangeCount'
              value: '1'
              cooldown: 'PT5M'
            }
          }
        ]
      }
    ]
  }
}

output applicationUrl string = uri('http://${publicIPAddress.properties.dnsSettings.fqdn}', '/MyApp')

Följande resurser definieras i Bicep-filen:

Definiera en skalningsgrupp

Om du vill skapa en VM-skalningsuppsättning med en Bicep-fil definierar du lämpliga resurser. Kärndelarna i resurstypen VM-skalningsuppsättning är:

Fastighet Egenskapsbeskrivning Exempelmallvärde
type Azure-resurstyp som ska skapas Microsoft.Compute/virtualMachineScaleSets
name Namnet på skalsatsen myScaleSet
location Platsen för att skapa skalningsuppsättningen East US
sku.namn Vm-storleken för varje skalningsuppsättningsinstans Standard_A1
sku.kapacitet Antalet vm-instanser som ska skapas från början 2
upgradePolicy.mode Uppgraderingsläge för virtuell datorinstans när ändringar sker Automatiskt
imageReference Plattformen eller den anpassade avbildningen som ska användas för de virtuella datorinstanserna Microsoft Windows Server 2016 Datacenter
osProfile.computerNamePrefix Namnprefixet för varje VM-instans myvmss
osProfile.adminUsername Användarnamnet för varje VM-instans azureuser
osProfile.administratörslösenord Lösenordet för varje VM-instans P@ssw0rd!

Om du vill anpassa en Bicep-fil för skalningsuppsättningar av virtuella maskiner kan du ändra storleken på den virtuella maskinen eller initialkapaciteten. Ett annat alternativ är att använda en annan plattform eller en anpassad avbildning.

Lägga till ett exempelprogram

För att testa din Virtual Machine Scale Set installerar du en grundläggande webbapplikation. När du distribuerar en VM-skalningsuppsättning kan VM-tillägg tillhandahålla konfigurations- och automatiseringsuppgifter efter distributionen, till exempel att installera en app. Skript kan laddas ned från GitHub eller tillhandahållas till Azure-portalen vid tilläggskörning. För att tillämpa ett tillägg på din Virtual Machine Scale Set, lägg till den extensionProfile-sektionen i resursexemplet ovan. Tilläggsprofilen definierar vanligtvis följande egenskaper:

  • Tilläggstyp
  • Tilläggsutgivare
  • Tilläggsversion
  • Plats för konfigurations- eller installationsskript
  • Kommandon som ska köras på de virtuella datorinstanserna

Bicep-filen använder PowerShell DSC-tillägget för att installera en ASP.NET MVC-app som körs i IIS.

Ett installationsskript laddas ned från GitHub enligt definitionen i url. Tillägget kör sedan InstallIIS från skriptet IISInstall.ps1, som definierat i function och Script. Själva ASP.NET-appen tillhandahålls som ett webbdistributionspaket, som också laddas ned från GitHub, enligt definitionen i WebDeployPackagePath:

Synkronisera Bicep-filen

  1. Spara Bicep-filen som main.bicep till din lokala dator.

  2. Distribuera Bicep-filen med antingen Azure CLI eller Azure PowerShell.

    az group create --name exampleRG --location eastus
    az deployment group create --resource-group exampleRG --template-file main.bicep --parameters vmssName=<vmss-name>
    

    Ersätt <vmss-name> med namnet på skala uppsättningen för virtuella maskiner. Den måste vara 3–61 tecken lång och globalt unik i Hela Azure. Du uppmanas att ange adminPassword.

    Anmärkning

    När distributionen är klar bör du se ett meddelande som anger att distributionen lyckades. Det kan ta 10–15 minuter innan den virtuella maskinskalan skapas, och tillägget används för att konfigurera appen.

Verifiera utplaceringen

Om du vill se din Virtual Machine Scale Set i aktion, öppna exempelwebbapplikationen i en webbläsare. Hämta den offentliga IP-adressen för lastbalanseraren med hjälp av Azure CLI eller Azure PowerShell.

az network public-ip show --resource-group exampleRG

Ange lastbalanserarens offentliga IP-adress i en webbläsare i formatet http://publicIpAddress/MyApp. Lastbalanseraren distribuerar trafik till en av dina VM-instanser, som du ser i följande exempel:

Köra IIS-webbplats

Rensa resurser

När den inte längre behövs använder du Azure-portalen, Azure CLI eller Azure PowerShell för att ta bort resursgruppen och dess resurser.

az group delete --name exampleRG

Nästa steg

I den här snabbstarten skapade du en Skalningsuppsättning för virtuella Windows-datorer med en Bicep-fil och använde PowerShell DSC-tillägget för att installera en grundläggande ASP.NET app på de virtuella datorinstanserna. Mer information finns i handledningen om hur du skapar och hanterar Azure Virtual Machine Scale Sets.