使用 ARM 模板进行订阅部署

若要简化资源管理,可以使用 Azure 资源管理器模板(ARM 模板)在 Azure 订阅级别部署资源。 例如,可以将策略Azure 基于角色的访问控制 (Azure RBAC) 部署到你的订阅中,从而将它们应用于整个订阅。 还可以在订阅中创建资源组,然后将资源部署到订阅中的资源组。

备注

可在订阅级别部署中部署到 800 个不同的资源组。

若要在订阅级别部署模板,请使用 Azure CLI、PowerShell、REST API 或门户。

支持的资源

并非所有资源类型都可以部署到订阅级别。 本部分列出了支持的资源类型。

对于 Azure 蓝图,请使用:

  • 项目
  • blueprints
  • blueprintAssignments
  • versions

对于 Azure 策略,请使用:

  • policyAssignments
  • policyDefinitions
  • policySetDefinitions
  • remediations

对于 Azure 基于角色的访问控制 (Azure RBAC),请使用:

  • roleAssignments
  • roleDefinitions

对于部署到资源组的嵌套模板,请使用:

  • deployments

若要创建新的资源组,请使用:

  • resourceGroups

若要管理订阅,请使用:

  • 顾问配置
  • 预算
  • 更改分析配置文件
  • supportPlanTypes
  • 标记

其他支持的类型包括:

  • scopeAssignments
  • eventSubscriptions
  • peerAsns

架构

用于订阅级别部署的架构不同于资源组部署的架构。

对于模板,请使用:

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  ...
}

对于所有部署范围,参数文件的架构都相同。 对于参数文件,请使用:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  ...
}

部署命令

若要部署到订阅,请使用订阅级别部署命名。

备注

当我们使用以 https://raw.githubusercontent.com/ 开头的指定模板文件 URI 部署资源时,控制台有时会生成错误,如 Unable to download deployment content

可以执行以下操作来解决相应问题。

  1. 复制模板 URI,通过更改前缀、中缀和模板文件名来转换 URI。 例如,源 URI 是 https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    类别 原始值 转换后的值 操作
    前缀 https://raw.githubusercontent.com https://github.com 更新
    中辍 blob mastermain 之前添加分支名称
    模板文件名 azuredeploy.json 你的下载模板文件名 update

    修改后,转换后的 URI 看起来将类似于 https://github.com/Azure/azure-quickstart-templates/blob/master/101-cosmosdb-sql-autoscale/azuredeploy.json

    请注意,某些模板 URI 已更新为 https://github.com/Azure/azure-quickstart-template/quickstarts/{Microsoft_Resource_Provider_Name}/ ,你可以按照相应的路径规定来更新原始 URI。

  2. 复制转换后的 URI,并在 Internet 浏览器中手动下载特定的模板内容。

  3. 修改从 GitHub 存储库下载或引用的模板,以适应 Azure 中国世纪互联环境。 例如,替换某些终结点(将“blob.core.windows.net”替换为“blob.core.chinacloudapi.cn”,将“cloudapp.azure.com”替换为“chinacloudapp.cn”);必要时更改某些不受支持的位置、VM 映像、VM 大小、SKU 以及资源提供程序的 API 版本。

  4. 将参数 -TemplateUri 替换为 -TemplateFile(对于 powershell)或将参数 --template-uri 替换为 --template-file(针对 CLI),然后用已下载的实际文件名称更新指定的 URI,然后重新运行脚本。

    语言类别 参考链接 操作
    PowerShell New-AzResourceGroupDeployment -TemplateUri 替换为 -TemplateFile
    如有必要,请按照前面的步骤下载 -TemplateParameterUri 内容并在 cmdlet 中替换为 -TemplateParameterFile
    Azure CLI az deployment group create --template-uri 替换为 --template-file

对于 Azure CLI,请使用 az deployment sub create。 以下示例会部署一个模板来创建资源组:

az deployment sub create \
  --name demoSubDeployment \
  --location chinaeast \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/emptyrg.json" \
  --parameters rgName=demoResourceGroup rgLocation=chinaeast

有关部署命令和部署 ARM 模板的选项的更多详细信息,请参阅:

部署位置和名称

对于订阅级别部署,必须为部署提供位置。 部署位置独立于部署的资源的位置。 部署位置指定何处存储部署数据。 管理组租户部署也需要位置。 对于资源组部署,资源组的位置用于存储部署数据。

可以为部署提供一个名称,也可以使用默认部署名称。 默认名称是模板文件的名称。 例如,部署一个名为 azuredeploy.json 的模板将创建默认部署名称 azuredeploy

每个部署名称的位置不可变。 当某个位置中已有某个部署时,无法在另一位置创建同名的部署。 例如,如果在 chinaeast 中创建名为“deployment1”的订阅部署,则以后不能创建另一个名为“deployment1”但位置为“chinanorth”的部署。 如果出现错误代码 InvalidDeploymentLocation,请使用其他名称或使用与该名称的以前部署相同的位置。

部署范围

部署到订阅时,可以将资源部署到:

  • 操作中的目标订阅
  • 租户中的任何订阅
  • 该订阅或其他订阅中的资源组
  • 订阅的租户

可以将扩展资源的范围设置为与部署目标不同的范围。

部署模板的用户必须有权访问指定的作用域。

本部分演示如何指定不同范围。 可以在单个模板中组合这些不同范围。

将范围限制为目标订阅

若要将资源部署到目标订阅,请将这些资源添加到模板的资源部分。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    subscription-level-resources
  ],
  "outputs": {}
}

有关部署到订阅的示例,请参阅创建资源组分配策略定义

将范围限制为其他订阅

若要将资源部署到与操作中的订阅不同的订阅,请添加嵌套部署。 将 subscriptionId 属性设置为要部署到的订阅的 ID。 为嵌套部署设置 location 属性。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedDeployment",
      "subscriptionId": "00000000-0000-0000-0000-000000000000",
      "location": "chinanorth",
      "properties": {
        "mode": "Incremental",
        "template": {
          subscription-resources
        }
      }
    }
  ],
  "outputs": {}
}

将范围限定于资源组

若要将资源部署到订阅中的资源组,请添加嵌套部署并包括 resourceGroup 属性。 在以下示例中,嵌套部署以名为 demoResourceGroup 的资源组为目标。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedDeployment",
      "resourceGroup": "demoResourceGroup",
      "properties": {
        "mode": "Incremental",
        "template": {
          resource-group-resources
        }
      }
    }
  ],
  "outputs": {}
}

有关部署到资源组的示例,请参阅创建资源组和资源

将范围设定为租户

若要在租户中创建资源,请将 scope 设置为 /。 部署模板的用户必须具有在租户中进行部署所需的访问权限

若要使用嵌套部署,请设置 scopelocation

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedDeployment",
      "location": "chinaeast",
      "scope": "/",
      "properties": {
        "mode": "Incremental",
        "template": {
          tenant-resources
        }
      }
    }
  ],
  "outputs": {}
}

或者,可将某些资源类型(如管理组)的范围设置为 /

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "mgName": {
      "type": "string",
      "defaultValue": "[concat('mg-', uniqueString(newGuid()))]"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Management/managementGroups",
      "apiVersion": "2021-04-01",
      "name": "[parameters('mgName')]",
      "scope": "/",
      "location": "chinaeast",
      "properties": {}
    }
  ],
  "outputs": {
    "output": {
      "type": "string",
      "value": "[parameters('mgName')]"
    }
  }
}

有关详细信息,请参阅管理组

资源组

创建资源组

若要在 ARM 模板中创建资源组,请为该资源组定义包含名称和位置的 Microsoft.Resources/resourceGroups资源。

以下模板创建空资源组。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "rgName": {
      "type": "string"
    },
    "rgLocation": {
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2021-04-01",
      "name": "[parameters('rgName')]",
      "location": "[parameters('rgLocation')]",
      "properties": {}
    }
  ],
  "outputs": {}
}

结合使用 copy 元素与资源组来创建多个资源组。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "rgNamePrefix": {
      "type": "string"
    },
    "rgLocation": {
      "type": "string"
    },
    "instanceCount": {
      "type": "int"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2021-04-01",
      "location": "[parameters('rgLocation')]",
      "name": "[concat(parameters('rgNamePrefix'), copyIndex())]",
      "copy": {
        "name": "rgCopy",
        "count": "[parameters('instanceCount')]"
      },
      "properties": {}
    }
  ],
  "outputs": {}
}

有关资源迭代的信息,请参阅 ARM 模板中的资源迭代教程:使用 ARM 模板创建多个资源实例

创建资源组和资源

若要创建资源组并向其部署资源,请使用嵌套模板。 嵌套模板定义要部署到资源组的资源。 将嵌套模板设置为依赖于资源组,确保资源组存在,然后再部署资源。 最多可部署到 800 个资源组。

以下示例将创建一个资源组,并向该资源组部署存储帐户。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "rgName": {
      "type": "string"
    },
    "rgLocation": {
      "type": "string"
    },
    "storagePrefix": {
      "type": "string",
      "maxLength": 11
    }
  },
  "variables": {
    "storageName": "[concat(parameters('storagePrefix'), uniqueString(subscription().id, parameters('rgName')))]"
  },
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2021-04-01",
      "name": "[parameters('rgName')]",
      "location": "[parameters('rgLocation')]",
      "properties": {}
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "storageDeployment",
      "resourceGroup": "[parameters('rgName')]",
      "dependsOn": [
        "[resourceId('Microsoft.Resources/resourceGroups/', parameters('rgName'))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "type": "Microsoft.Storage/storageAccounts",
              "apiVersion": "2021-04-01",
              "name": "[variables('storageName')]",
              "location": "[parameters('rgLocation')]",
              "sku": {
                "name": "Standard_LRS"
              },
              "kind": "StorageV2"
            }
          ],
          "outputs": {}
        }
      }
    }
  ],
  "outputs": {}
}

Azure Policy

分配策略定义

以下示例将现有的策略定义分配到订阅。 如果策略定义使用参数,请将参数作为对象提供。 如果策略定义不使用参数,请使用默认的空对象。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "policyDefinitionID": {
      "type": "string"
    },
    "policyName": {
      "type": "string"
    },
    "policyParameters": {
      "type": "object",
      "defaultValue": {}
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Authorization/policyAssignments",
      "apiVersion": "2020-03-01",
      "name": "[parameters('policyName')]",
      "properties": {
        "scope": "[subscription().id]",
        "policyDefinitionId": "[parameters('policyDefinitionID')]",
        "parameters": "[parameters('policyParameters')]"
      }
    }
  ]
}

若要使用 Azure CLI 部署此模板,请使用:

# Built-in policy definition that accepts parameters
definition=$(az policy definition list --query "[?displayName=='Allowed locations'].id" --output tsv)

az deployment sub create \
  --name demoDeployment \
  --location chinaeast \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/policyassign.json" \
  --parameters policyDefinitionID=$definition policyName=setLocation policyParameters="{'listOfAllowedLocations': {'value': ['chinanorth']} }"

若要使用 PowerShell 部署此模板,请使用:

$definition = Get-AzPolicyDefinition | Where-Object { $_.Properties.DisplayName -eq 'Allowed locations' }

$locations = @("chinanorth", "chinanorth2")
$policyParams =@{listOfAllowedLocations = @{ value = $locations}}

New-AzSubscriptionDeployment `
  -Name policyassign `
  -Location chinaeast `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/policyassign.json" `
  -policyDefinitionID $definition.PolicyDefinitionId `
  -policyName setLocation `
  -policyParameters $policyParams

创建和分配策略定义

可在同一模板中定义和分配策略定义。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {},
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Authorization/policyDefinitions",
      "apiVersion": "2020-03-01",
      "name": "locationpolicy",
      "properties": {
        "policyType": "Custom",
        "parameters": {},
        "policyRule": {
          "if": {
            "field": "location",
            "equals": "chinaeast2"
          },
          "then": {
            "effect": "deny"
          }
        }
      }
    },
    {
      "type": "Microsoft.Authorization/policyAssignments",
      "apiVersion": "2020-03-01",
      "name": "location-lock",
      "dependsOn": [
        "locationpolicy"
      ],
      "properties": {
        "scope": "[subscription().id]",
        "policyDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/policyDefinitions', 'locationpolicy')]"
      }
    }
  ]
}

若要在订阅中创建策略定义,然后将其分配到订阅,请使用以下 CLI 命令:

az deployment sub create \
  --name demoDeployment \
  --location chinaeast \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/policydefineandassign.json"

若要使用 PowerShell 部署此模板,请使用:

New-AzSubscriptionDeployment `
  -Name definePolicy `
  -Location chinaeast `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/policydefineandassign.json"

Azure 蓝图

创建蓝图定义

可通过模板创建蓝图定义。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "blueprintName": {
      "defaultValue": "sample-blueprint",
      "type": "String",
      "metadata": {
        "description": "The name of the blueprint definition."
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Blueprint/blueprints",
      "apiVersion": "2018-11-01-preview",
      "name": "[parameters('blueprintName')]",
      "properties": {
        "targetScope": "subscription",
        "description": "Blueprint with a policy assignment artifact.",
        "resourceGroups": {
          "sampleRg": {
            "description": "Resource group to add the assignment to."
          }
        },
        "parameters": {
          "listOfResourceTypesNotAllowed": {
            "type": "array",
            "metadata": {
              "displayName": "Resource types to pass to the policy assignment artifact."
            },
            "defaultValue": [
              "Citrix.Cloud/accounts"
            ]
          }
        }
      }
    },
    {
      "type": "Microsoft.Blueprint/blueprints/artifacts",
      "apiVersion": "2018-11-01-preview",
      "name": "[concat(parameters('blueprintName'), '/policyArtifact')]",
      "kind": "policyAssignment",
      "dependsOn": [
        "[parameters('blueprintName')]"
      ],
      "properties": {
        "displayName": "Blocked Resource Types policy definition",
        "description": "Block certain resource types",
        "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policyDefinitions', '6c112d4e-5bc7-47ae-a041-ea2d9dccd749')]",
        "resourceGroup": "sampleRg",
        "parameters": {
          "listOfResourceTypesNotAllowed": {
            "value": "[[parameters('listOfResourceTypesNotAllowed')]"
          }
        }
      }
    }
  ]
}

若要在订阅中创建蓝图定义,请使用以下 CLI 命令:

az deployment sub create \
  --name demoDeployment \
  --location chinaeast \
  --template-uri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/subscription-deployments/blueprints-new-blueprint/azuredeploy.json"

若要使用 PowerShell 部署此模板,请使用:

New-AzSubscriptionDeployment `
  -Name demoDeployment `
  -Location chinaeast `
  -TemplateUri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/subscription-deployments/blueprints-new-blueprint/azuredeploy.json"

访问控制

若要了解如何分配角色,请参阅使用 Azure 资源管理器模板分配 Azure 角色

以下示例创建一个资源组,对其应用锁定,并为主体分配一个角色。

{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.4.1.14562",
      "templateHash": "17666923867108240565"
    }
  },
  "parameters": {
    "rgName": {
      "type": "string",
      "metadata": {
        "description": "Name of the resourceGroup to create"
      }
    },
    "rgLocation": {
      "type": "string",
      "metadata": {
        "description": "Location for the resourceGroup"
      }
    },
    "principalId": {
      "type": "string",
      "metadata": {
        "description": "principalId of the user that will be given contributor access to the resourceGroup"
      }
    },
    "roleDefinitionId": {
      "type": "string",
      "defaultValue": "b24988ac-6180-42a0-ab88-20f7382dd24c",
      "metadata": {
        "description": "roleDefinition to apply to the resourceGroup - default is contributor"
      }
    },
    "roleAssignmentName": {
      "type": "string",
      "defaultValue": "[guid(parameters('principalId'), parameters('roleDefinitionId'), parameters('rgName'))]",
      "metadata": {
        "description": "Unique name for the roleAssignment in the format of a guid"
      }
    }
  },
  "functions": [],
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2019-10-01",
      "name": "[parameters('rgName')]",
      "location": "[parameters('rgLocation')]",
      "tags": {
        "Note": "subscription level deployment"
      },
      "properties": {}
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "name": "applyLock",
      "resourceGroup": "[parameters('rgName')]",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "mode": "Incremental",
        "parameters": {
          "principalId": {
            "value": "[parameters('principalId')]"
          },
          "roleDefinitionId": {
            "value": "[parameters('roleDefinitionId')]"
          },
          "roleAssignmentName": {
            "value": "[parameters('roleAssignmentName')]"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "metadata": {
            "_generator": {
              "name": "bicep",
              "version": "0.4.1.14562",
              "templateHash": "12740078983609655962"
            }
          },
          "parameters": {
            "principalId": {
              "type": "string",
              "metadata": {
                "description": "principalId of the user that will be given contributor access to the resourceGroup"
              }
            },
            "roleDefinitionId": {
              "type": "string",
              "metadata": {
                "description": "roleDefinition to apply to the resourceGroup - default is contributor"
              }
            },
            "roleAssignmentName": {
              "type": "string",
              "metadata": {
                "description": "Unique name for the roleAssignment in the format of a guid"
              }
            }
          },
          "functions": [],
          "resources": [
            {
              "type": "Microsoft.Authorization/locks",
              "apiVersion": "2016-09-01",
              "name": "DontDelete",
              "properties": {
                "level": "CanNotDelete",
                "notes": "Prevent deletion of the resourceGroup"
              }
            },
            {
              "type": "Microsoft.Authorization/roleAssignments",
              "apiVersion": "2020-04-01-preview",
              "name": "[guid(parameters('roleAssignmentName'))]",
              "properties": {
                "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))]",
                "principalId": "[parameters('principalId')]"
              }
            }
          ]
        }
      },
      "dependsOn": [
        "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('rgName'))]"
      ]
    }
  ]
}

后续步骤