创建资源组并部署资源

Create Resource Group and Deploy Resource

根据Microsoft Documentation,现在可以创建资源组并将资源部署到新创建的资源组。不过有一个小问题,在一开始,我们有这个免责声明 -

Subscription level deployment is different from resource group deployment in the following aspects:

Schema and commands

The schema and commands you use for subscription-level deployments are different than resource group deployments.

For the schema, use https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#

这引发了一个主要问题,azuredeploy.json 不再被识别为部署模板,因为它没有使用资源部署架构(https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json# ).

因此,另一种选择是将资源组创建为 嵌套模板 并放置 dependsOn 对于将要创建的子资源,这现在允许我 Deploy/Validate 文件。但是,这有一个新问题。即使 dependsOn 指示创建资源组,它仍然无法识别这一点并返回错误 - 找不到资源组,因此无法部署资源。我尝试使用链接模板(我知道这没有任何区别,但仍然如此)

有人成功做到了吗?

添加我的代码。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "North Europe"
    },
    "FirstResourceGroupName": {
      "type": "string",
      "defaultValue": "myFirstRG"
    },
    "FirstBlobStorageName": {
      "type": "string",
      "defaultValue": "North Europe"
    }
  },
  "variables": {
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2018-05-01",
      "name": "ResourceGroupDeployment",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
          "contentVersion": "1.0.0.1",
          "resources": [
            {
              "type": "Microsoft.Resources/resourceGroups",
              "apiVersion": "2018-05-01",
              "location": "[parameters('location')]",
              "name": "[parameters('FirstResourceGroupName')]",
              "properties": {}
            }
          ],
          "outputs" : {}
        }
      }
    },
    {
      //ResourceDeployment
      "type": "Microsoft.Resources/deployments",
      "name": "StorageDeployment",
      "apiVersion": "2017-05-10",
      "dependsOn": [
        "[concat('Microsoft.Resources/deployments/', 'ResourceGroupDeployment')]"
        //"ResourceGroupDeployment"
      ],
      "resourceGroup": "[parameters('FirstResourceGroupName')]",
      "properties": {
        "mode": "Incremental",
        "template": {
            "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "parameters": {},
            "variables": {},
            "resources": [
                {
                    "type": "Microsoft.Storage/storageAccounts",
                    "apiVersion": "2017-10-01",
                    "name": "[parameters('FirstBlobStorageName')]",
                    "location": "[parameters('location')]",
                    "kind": "StorageV2",
                    "sku": {
                        "name": "Standard_LRS"
                    }
                }
            ],
            "outputs": {}
        }
      }
    } 
  ],
  "outputs": {}
}

取自官方文档的示例:

{
    "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
    "contentVersion": "1.0.0.1",
    "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": "2018-05-01",
            "location": "[parameters('rgLocation')]",
            "name": "[parameters('rgName')]",
            "properties": {}
        },
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2018-05-01",
            "name": "storageDeployment",
            "resourceGroup": "[parameters('rgName')]",
            "dependsOn": [
                "[resourceId('Microsoft.Resources/resourceGroups/', parameters('rgName'))]"
            ],
            "properties": {
                "mode": "Incremental",
                "template": {
                    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.0",
                    "parameters": {},
                    "variables": {},
                    "resources": [
                        {
                            "type": "Microsoft.Storage/storageAccounts",
                            "apiVersion": "2017-10-01",
                            "name": "[variables('storageName')]",
                            "location": "[parameters('rgLocation')]",
                            "kind": "StorageV2",
                            "sku": {
                                "name": "Standard_LRS"
                            }
                        }
                    ]
                }
            }
        }
    ]
}

正是您所需要的。

https://docs.microsoft.com/en-us/azure/azure-resource-manager/deploy-to-subscription#create-resource-group-and-deploy-resources

当您不使用 Visual Studio 或 Portal 进行部署时,MS 提出的解决方案很好。我的主要问题是模板的验证再次不适用于订阅级部署,因为它使用的模式未被识别为 ARM。

可能通过任何其他方式如@4c74356b41建议的那样工作,即cli\sdks\restapi,但我没有走那条路。

我的另一个解决方案是通过在 Azure DevOps 管道上添加一个步骤来 运行 一个 powershell 脚本。这是我最接近完成这项工作的一次,但再次验证以检查我的部署是否会成功,仍然悬而未决。我不希望我的发布管道因为模板无效而失败。

这是我收集到的信息,验证失败的原因(即使部署了 RG 并使用 dependsOn)是因为资源组不会被创建,直到您部署模板。模板部署不会发生,除非它通过验证,因为资源组不存在。所以我们陷入了一个循环。这两个选项要么在验证之前在门户网站上手动创建它们(这违背了自动化的要点),要么在验证它们之前使用简单的 powershell 步骤。后者是我所经历的。我知道这是非正统的,但有效……并且还验证了我的模板。

注意 - 解决方案与原始问题不同,因为我使用了多个资源组创建。根据 MS 文档,您最多可以通过这种方式部署 5 个 RG。

首先,创建一个资源组文件,用于保存您要创建的资源组。它只是一个简单的 JSON 文件,例如

{
  "rgNames": 
  {
    "rg1": { "rg": "resource-group-main" },
    "rg2": { "rg": "resource-group-backup" }
  }
}

使用您添加到此文件的相同值作为参数,因此您可以使用它们将资源部署到。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
      "ResourceGroups": {
          "type": "object",
          //If you are changing this value !!!! Please make sure you are also updating the same in the ResourceGroups.ARM.json !!!!
          "allowedValues": [
            {
              "rgNames": 
              {
                "rg1": { "rg": "resource-group-main" },
                "rg2": { "rg": "resource-group-backup" }
              }
            }
          ]
        }
    } 

其次,更改PS 脚本以包含循环遍历需要部署的资源组列表的代码。

# Set '$RGTemplateFile' parameter to be the name of the file you added to your project 
$rgFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $RGTemplateFile))

$rgString = Get-Content -Raw -Path $rgFile | ConvertFrom-Json

# helper to turn PSCustomObject into a list of key/value pairs
function Get-ObjectMembers {
   [CmdletBinding()]
   Param(
       [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
       [PSCustomObject]$obj
   )
   $obj | Get-Member -MemberType NoteProperty | ForEach-Object {
       $key = $_.Name
       [PSCustomObject]@{Key = $key; Value = $obj."$key"}
   }
}

$rgValues = $jsonParam | Get-ObjectMembers | foreach {
   $_.Value | Get-ObjectMembers | foreach {
       [PSCustomObject]@{
           RGName = $_.value.rgNames | select -First 1
       }
   }
}

foreach ($values in $rgValues)
{
   New-AzureRmResourceGroup -Name $values.RGName -Location $ResourceGroupLocation -Verbose -Force
}

在执行验证之前添加上面的代码 -

if ($ValidateOnly) {
    $ErrorMessages = Format-ValidationOutput (Test-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroupName `
                                                                                  -TemplateFile $TemplateFile `
                                                                                  -TemplateParameterFile $TemplateParametersFile `
                                                                                  @OptionalParameters)
:

最后,更改部署模板文件(azuredeploy.json)以执行嵌套模板部署或链接模板以在您声明的 RG 上部署资源。 (我用过Linked,因为它看起来更整洁)

  "variables": {
    "rg1Name": "[parameters('ResourceGroups')['rgNames']['rg1'].rg]",
    "rg2Name": "[parameters('ResourceGroups')['rgNames']['rg2'].rg]",
    "blob1Name": "[parameters('blob1')]",
    "blob2Name": "[parameters('blob2')]",
    "arm1": "[concat(parameters('_artifactsLocation'), 'rg1/rg1.ARM.json', parameters('_artifactsLocationSasToken'))]",
    "arm2": "[concat(parameters('_artifactsLocation'), 'rg2/rg2.ARM.json', parameters('_artifactsLocationSasToken'))]"
  },
  "resources": [
    {
      //RG1 Resources Deployment
      "type": "Microsoft.Resources/deployments",
      "name": "RG1Resources",
      "apiVersion": "2017-05-10",
      "resourceGroup": "[variables('rg1Name')]",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[variables('arm1')]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "blob1Name": {
            "value": "[variables('blob1Name')]"
          }
        }
      }
    },
    {
      //RG2 Resources Deployment
      "type": "Microsoft.Resources/deployments",
      "name": "RG2Resources",
      "apiVersion": "2017-05-10",
      "resourceGroup": "[variables('rg2Name')]",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[variables('arm2')]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "blobName": {
            "value": "[variables('blob2Name')]"
          }
        }
      }
    }
  ],
  "outputs": {}
}

您的 rg1.ARM.json 和 rg2.ARM.json 文件看起来很像,显然一个文件可以拥有多个资源。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {    
    "blobName": {
      "type": "string"
    }
  },
  "variables": {
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[parameters('blobName')]",
      "kind": "StorageV2",
      "apiVersion": "2018-07-01",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard_LRS"
      },
      "properties": {}
    }
  ],
  "outputs": {
  }
}

设置完成后,您将能够验证文件,因为 PS 脚本会在文件通过验证之前为您创建 RG。