ARM - 将多个VM添加到Recovery Services Vault(copyIndex)

时间:2017-11-20 17:20:20

标签: azure templates azure-resource-manager

我尝试使用恢复服务,我可以通过ARM模板自动将VM添加到Azure备份。我已经在单个计算机部署上成功完成了此操作,但是我尝试在部署多个VM时导入它。

以下是我的帮助: https://www.francoisdelport.com/2017/03/automating-azure-vm-backups-using-arm-templates/

Azure ARM JSON template - Add VM to Recovery Services Vault in different Resource Group

以下是我工作的单个部署的片段

{
  "apiVersion": "2017-05-10",
  "name": "nestedTemplate",
  "type": "Microsoft.Resources/deployments",
  "resourceGroup": "Env1",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
  ],
  "properties": {
    "mode": "Incremental",
    "template": {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {},
      "variables": {},
      "resources": [
        {
          "apiVersion": "2016-06-01",
          "name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', parameters('vmPrefix'), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', parameters('vmPrefix'))]",
          "location": "[resourceGroup().location]",
          "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
          "properties": {
            "protectedItemType": "Microsoft.Compute/virtualMachines",
            "policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
            "sourceResourceId": "[resourceId(subscription().subscriptionId, parameters('vmRsg'), 'Microsoft.Compute/virtualMachines', parameters('vmPrefix'))]"
          }
        }
      ]
    }
  }
}

现在我尝试在copyIndex表单中使用它来进行VM部署,这是我正在测试的代码:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminUsername": {
      "type": "string",
      "minLength": 1,
      "metadata": {
        "description": "Username for the Virtual Machine."
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Password for the Virtual Machine."
      }
    },
    "dnsNameForPublicIP": {
      "type": "string",
      "minLength": 1,
      "metadata": {
        "description": "Globally unique DNS Name for the Public IP used to access the Virtual Machine."
      }
    },
    "windowsOSVersion": {
      "type": "string",
      "defaultValue": "2012-R2-Datacenter",
      "allowedValues": [
        "2008-R2-SP1",
        "2012-Datacenter",
        "2012-R2-Datacenter"
      ],
      "metadata": {
        "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."
      }
    },
    "vmCount": {
      "type": "int",
      "defaultValue": 1
    },
    "virtualNetworkName": {
      "type": "string"
    },
    "dataDiskCount": {
      "type": "int",
      "defaultValue": 1
    },
    "recoveryVault": {
      "type": "string",
      "metadata": {
        "description": "Backup vault name"
      }
    },
    "recoveryPolicy": {
      "type": "string",
      "metadata": {
        "description": "Backcup policy name"
      }
    },
    "vmPrefix": {
      "type": "string",
      "metadata": {
        "description": "Prefix for VM names, used with vmCount to build the VM names"
      }
    },
    "vmRsg": {
      "type": "string",
      "metadata": {
        "description": "Resource group where VMs reside"
      }
    }
  },
  "variables": {
    "imagePublisher": "MicrosoftWindowsServer",
    "imageOffer": "WindowsServer",
    "OSDiskName": "osdiskforwindowssimple",
    "nicName": "myVMNic",
    "subnetName": "Subnet",
    "vhdStorageType": "Standard_LRS",
    "publicIPAddressName": "myPublicIP",
    "publicIPAddressType": "Dynamic",
    "vhdStorageContainerName": "vhds",
    "vmName": "MWindowsVM",
    "vmSize": "Standard_A2",
    "virtualNetworkName": "MyVNET",
    "vnetId": "[resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetId'), '/subnets/', variables('subnetName'))]"
  },
  "resources": [
    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[concat(variables('publicIPAddressName'), copyIndex(1))]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "PublicIPAddress"
      },
      "properties": {
        "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
        "dnsSettings": {
          "domainNameLabel": "[concat(parameters('dnsNameForPublicIP'), copyIndex(1))]"
        }
      },
      "copy": {
        "name": "publicIpCopy",
        "count": "[parameters('vmCount')]"
      }
    },
    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(variables('nicName'), copyIndex(1))]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "NetworkInterface"
      },
      "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/', concat(variables('publicIPAddressName'), copyIndex(1)))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "[concat('ipconfig', copyIndex(1))]",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddressName'), copyIndex(1)))]"
              },
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      },
      "copy": {
        "name": "nicCopy",
        "count": "[parameters('vmCount')]"
      }
    },
    {
      "apiVersion": "2017-03-30",
      "copy": {
        "name": "nodeCopy",
        "count": "[parameters('vmCount')]"
      },
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[concat(variables('vmName'), copyIndex(1))]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "VirtualMachine"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces/', concat(variables('nicName'), copyIndex(1)))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[variables('vmSize')]"
        },
        "osProfile": {
          "computerName": "[concat(variables('vmName'), copyIndex(1))]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "[variables('imagePublisher')]",
            "offer": "[variables('imageOffer')]",
            "sku": "[parameters('windowsOSVersion')]",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage"
          },
          "copy": [
            {
              "name": "dataDisks",
              "count": "[parameters('dataDiskCount')]",
              "input": {
                "diskSizeGB": 1023,
                "lun": "[copyIndex('dataDisks')]",
                "createOption": "Empty"
              }
            }
          ]
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'), copyIndex(1)))]"
            }
          ]
        }
      }
    },
    {
      "apiVersion": "2017-05-10",
      "name": "nestedTemplate",
      "type": "Microsoft.Resources/deployments",
      "resourceGroup": "Env1",
      "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'), copyIndex(1)))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "copy": {
                "name": "protectedItemsCopy",
                "count": "[parameters('vmCount')]"
              },
              "apiVersion": "2017-03-30",
              "name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', parameters('vmPrefix'), copyIndex(1), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', parameters('vmPrefix'), copyIndex(1))]",
              "location": "[resourceGroup().location]",
              "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
              "properties": {
                "protectedItemType": "Microsoft.Compute/virtualMachines",
                "policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
                "sourceResourceId": "[resourceId(subscription().subscriptionId ,parameters('vmRsg'),'Microsoft.Compute/virtualMachines', concat(parameters('vmPrefix'), copyIndex(1)) )]"
              }
            }
          ]
        }
      }
    }
  ]
}

可悲的是,它在尝试部署时报告错误,我无法弄清楚原因,因为它似乎是正确的。

Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The template resource 'nestedTemplate' at line '198' and column '10' is not valid: The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified. Please see https://aka.ms/arm-copy for usage details.. Please see https://aka.ms/arm-template-expressions for usage details.'.
The deployment validation failed

仅供参考,第198行是"name": "nestedTemplate",

请问任何想法?

2 个答案:

答案 0 :(得分:1)

要扩展@ 4c74356b41,我错过了父模板上"index":{ "value": "[copyIndex()]"内的所有重要"Microsoft.Resources/deployments"

对于想要了解更多信息的人,请查看:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple

确保您在需要复制的项目旁边有('index')参数,例如"[concat(parameters('WHATEVER'), parameters('index'))]"

我最终在我的链接模板中有一个嵌套的源代码,用于我正在寻找的整体设计。

所以我的父模板有一个链接(子)模板(到另一个文件):

name": "[concat('nestings', copyIndex(1))]",
"type": "Microsoft.Resources/deployments", ...

我的子模板包含具有参数('index')的VM的所有常规建筑物,以确保正确命名重复的项目。

最后在子模板的底部我有一个嵌套的模板源,所以我可以将VM备份到另一个资源组(必须嵌套,否则你不能做多个资源组),看起来像这样:

{
      "apiVersion": "2017-05-10",
      "name": "[concat('nestedTemplate', parameters('index'))]",
      "type": "Microsoft.Resources/deployments",
      "resourceGroup": "Env1",
      "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'), parameters('index')))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "apiVersion": "2016-06-01",
              "name": "[concat( parameters('recoveryVault'), '/Azure/', 'iaasvmcontainer;iaasvmcontainerv2;', parameters('vmRsg') , ';', concat(parameters('vmPrefix'), parameters('index')), '/vm;iaasvmcontainerv2;', parameters('vmRsg'),';', concat(parameters('vmPrefix'), parameters('index')))]",
              "location": "[resourceGroup().location]",
              "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
              "properties": {
                "protectedItemType": "Microsoft.Compute/virtualMachines",
                "policyId": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('recoveryVault'), parameters('recoveryPolicy'))]",
                "sourceResourceId": "[resourceId(subscription().subscriptionId, parameters('vmRsg'), 'Microsoft.Compute/virtualMachines', concat(parameters('vmPrefix'), parameters('index')))]"
              }
            }
          ]
        }
      }
    }

答案 1 :(得分:0)

所以它告诉你你不应该在那个地方使用copyIndex()函数。现在为什么会发生这种情况我不知道,但我知道内联模板是一团糟(例如他们使用父模板参数,而不是嵌套模板),我很确定你是否将该模板转换为真正的嵌套模板模板(所以链接的模板,完全独立的文件)上面的语法将起作用。

另外,我是以另外的方式处理这个问题。我为每个VM使用了一个单独的嵌套部署,因此我在部署资源上使用副本,而不是备份资源。