练习 - 通过使用模块将资源部署到多个范围

已完成

注意

本练习需要 Azure 订阅。 如果没有 Azure 订阅,则可以获取免费 Azure 订阅

研发团队要求你提供帮助,以便在 Project Teddybear 订阅中创建虚拟网络。 你知道将来可以在更多订阅中帮助团队,因此决定扩展可重用的 Bicep 模板,以部署一个虚拟网络供团队成员使用。

在本练习中,你将更新在上一个练习中开始生成的模板。

在此过程中,你将:

  • 更新订阅范围的模板以创建新的资源组。
  • 使用虚拟网络创建一个单独的 Bicep 模块,并使用参数来控制虚拟网络的配置方式。
  • 更新模板以将模块部署到资源组。
  • 部署模板。

此练习要求你有权部署订阅范围的资源。 如果你当前的 Azure 帐户无法满足此要求,可以获取免费试用版并创建新的 Azure 订阅和租户。 或者,你也可以跳过此练习中的部署步骤。

创建资源组

  1. 在 Visual Studio Code 中,打开在前面的练习中创建的 main.bicep 文件。

  2. 在当前变量定义下,添加以下变量定义:

    var resourceGroupName = 'ToyNetworking'
    
  3. 在文件底部,添加下列资源定义:

    resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-07-01' = {
      name: resourceGroupName
      location: deployment().location
    }
    

    请注意,定义资源组的方式与定义其他资源的方式相同。 资源组是订阅范围的资源,可以在 targetScope 设置为 subscription 的 Bicep 文件中部署和管理。

  4. 保存对文件所做的更改。

添加用于创建虚拟网络的模块

接下来,你将为研发团队的虚拟网络创建 Bicep 模块。 稍后在本练习中,将模块中的资源部署到资源组。

  1. 在 Visual Studio Code 中,在你创建了 main.bicep 文件的同一文件夹中,创建一个名为“模块”的新文件夹。

  2. 在 modules 文件夹中,创建并保存一个名为 virtualNetwork.bicep 的文件。

  3. 在 virtualNetwork.bicep 文件中,添加以下内容:

    param virtualNetworkName string
    param virtualNetworkAddressPrefix string
    
    resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = {
      name: virtualNetworkName
      location: resourceGroup().location
      properties: {
        addressSpace: {
          addressPrefixes: [
            virtualNetworkAddressPrefix
          ]
        }
      }
    }
    

    请注意,没有为此模块指定 targetScope。 当 Bicep 文件面向资源组时,无需指定目标范围。

  4. 保存对文件所做的更改。

使用订阅部署中的模块

现在,你已准备好告诉 Bicep 将模块部署到资源组。

  1. 在 Visual Studio Code 的 main.bicep 文件中,在 targetScope 行下添加以下参数定义:

    param virtualNetworkName string
    param virtualNetworkAddressPrefix string
    

    这些参数使模板可重复使用。 每当研发团队需要新的订阅时,你可以创建一个具有唯一名称和 IP 地址范围的虚拟网络。

  2. 在文件底部,添加以下模块定义:

    module virtualNetwork 'modules/virtualNetwork.bicep' = {
      scope: resourceGroup
      name: 'virtualNetwork'
      params: {
        virtualNetworkName: virtualNetworkName
        virtualNetworkAddressPrefix: virtualNetworkAddressPrefix
      }
    }
    

    请注意,你将为模块显式指定 scope。 Bicep 知道模块内的资源应部署到你之前在文件中创建的资源组。

验证模板

main.bicep 文件应如下所示:

targetScope = 'subscription'

param virtualNetworkName string
param virtualNetworkAddressPrefix string

var policyDefinitionName = 'DenyFandGSeriesVMs'
var policyAssignmentName = 'DenyFandGSeriesVMs'
var resourceGroupName = 'ToyNetworking'

resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2024-05-01' = {
  name: policyDefinitionName
  properties: {
    policyType: 'Custom'
    mode: 'All'
    parameters: {}
    policyRule: {
      if: {
        allOf: [
          {
            field: 'type'
            equals: 'Microsoft.Compute/virtualMachines'
          }
          {
            anyOf: [
              {
                field: 'Microsoft.Compute/virtualMachines/sku.name'
                like: 'Standard_F*'
              }
              {
                field: 'Microsoft.Compute/virtualMachines/sku.name'
                like: 'Standard_G*'
              }
            ]
          }
        ]
      }
      then: {
        effect: 'deny'
      }
    }
  }
}

resource policyAssignment 'Microsoft.Authorization/policyAssignments@2024-05-01' = {
  name: policyAssignmentName
  properties: {
    policyDefinitionId: policyDefinition.id
  }
}

resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-07-01' = {
  name: resourceGroupName
  location: deployment().location
}

module virtualNetwork 'modules/virtualNetwork.bicep' = {
  scope: resourceGroup
  name: 'virtualNetwork'
  params: {
    virtualNetworkName: virtualNetworkName
    virtualNetworkAddressPrefix: virtualNetworkAddressPrefix
  }
}

modules/virtualNetwork.bicep 文件应如下所示:

param virtualNetworkName string
param virtualNetworkAddressPrefix string

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-01-01' = {
  name: virtualNetworkName
  location: resourceGroup().location
  properties: {
    addressSpace: {
      addressPrefixes: [
        virtualNetworkAddressPrefix
      ]
    }
  }
}

如果任意文件均不匹配示例,请复制示例或调整模板。

将模板部署到 Azure

在 Visual Studio Code 终端中,使用以下 Azure CLI 命令部署模板:

templateFile="main.bicep"
today=$(date +"%d-%b-%Y")
deploymentName="sub-scope-"$today
virtualNetworkName="rnd-vnet-001"
virtualNetworkAddressPrefix="10.0.0.0/24"

az deployment sub create \
    --name $deploymentName \
    --location westus \
    --template-file $templateFile \
    --parameters virtualNetworkName=$virtualNetworkName \
                 virtualNetworkAddressPrefix=$virtualNetworkAddressPrefix

在 Visual Studio Code 终端中,使用以下 Azure PowerShell 命令部署模板:

$templateFile = 'main.bicep'
$today = Get-Date -Format 'MM-dd-yyyy'
$deploymentName = "sub-scope-$today"
$virtualNetworkName = 'rnd-vnet-001'
$virtualNetworkAddressPrefix = '10.0.0.0/24'

New-AzSubscriptionDeployment `
  -Name $deploymentName `
  -Location westus `
  -TemplateFile $templateFile `
  -virtualNetworkName $virtualNetworkName `
  -virtualNetworkAddressPrefix $virtualNetworkAddressPrefix

请注意,你要传入 virtualNetworkNamevirtualNetworkAddressPrefix 参数的值。 当另一个研发团队要求你为他们准备订阅时,你可以更改这些值,以便为该团队提供它自己的虚拟网络。

此部署可能需要一两分钟才能完成,然后你会看到部署成功。

验证部署

现在,你将检查该模块创建的资源组和部署。

  1. 转到 Azure 门户

  2. 在左窗格中,选择“资源组”。 请注意,已创建 ToyNetworking 资源组。

  3. 选择“ToyNetworking”资源组。 请注意,该模块已成功部署到资源组,并且已创建虚拟网络:

    Screenshot of the Azure portal, showing the ToyNetworking resource group.

清理资源

你已成功部署了订阅范围资源(包括资源组),并且已使用模块将资源部署到你创建的资源组中。 现在可以删除创建的策略资源和资源组。

注意

此命令会永久删除名为 ToyNetworking 的资源组及其所有资源。 如果已将任何其他内容部署到此资源组,则应跳过此步骤。

subscriptionId=$(az account show --query 'id' --output tsv)

az policy assignment delete --name 'DenyFandGSeriesVMs' --scope "/subscriptions/$subscriptionId"
az policy definition delete --name 'DenyFandGSeriesVMs' --subscription $subscriptionId
az group delete --name ToyNetworking
$subscriptionId = (Get-AzContext).Subscription.Id

Remove-AzPolicyAssignment -Name 'DenyFandGSeriesVMs' -Scope "/subscriptions/$subscriptionId"
Remove-AzPolicyDefinition -Name 'DenyFandGSeriesVMs' -SubscriptionId $subscriptionId
Remove-AzResourceGroup -Name ToyNetworking