我已经开发了ARM模板,它将并行构建多个VM。每台计算机都有一个OS磁盘和一个vNIC。我可以使用PowerShell部署ARM模板,也可以使用Azure门户的“部署自定义模板”功能上载ARM模板并进行部署。
但是我似乎不太能正确地使用复制循环在JsonADDomainExtension中添加语法,以便所有计算机都以相同的模板添加到我的域中。
目前,我所有的资源都在一个资源组中。我已经预先部署了带有子网和存储帐户的vNET。
下面是可同时部署多台计算机的ARM模板。
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters":
{
"adminUsername":
{
"type": "string",
"metadata": {"description": "Administrator username for the Virtual Machine."}
},
"adminPassword":
{
"type": "securestring",
"metadata": {"description": "Password for the Virtual Machine.Should contain any 3 of: 1 Lower Case, 1 Upper Case, 1 Number and 1 Special character."}
},
"numberOfInstances":
{
"type": "int",
"defaultValue": 3,
"minValue": 2,
"maxValue": 5,
"metadata": {"description": "Number of VMs to deploy, limit 5 since this sample is using a single storage account."}
},
"StartOfCount":
{
"type": "int",
"defaultValue": 1,
"metadata": {"description": "Number that you want to start the machine name numbering from, EG to create 5 VMs with the name starting at 045 (W2016SRV-045-vm) you would enter 45 here, or to start at 1 just enter 1 here, this wil give you a machine name like 'W2016SRV-001-vm'."}
},
"vmNamePrefix":
{
"type": "string",
"defaultValue": "W2016SRV-",
"maxLength": 9,
"metadata": {"description": "The VM name prefix maximum 9 characters. This allows for three digits in the name and trailing '-vm'. EG: 'W2016SRV-045-vm'."}
},
"vmSize":
{
"type": "string",
"defaultValue": "Standard_B2ms",
"metadata":
{
"description": "The size(T-shirt) for the VM. (Standard_D8s_v3)",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Compute/virtualMachines/vmSize"}
}
},
"vmLocation":
{
"type": "string",
"defaultValue": "AustraliaSoutheast",
"metadata":
{
"description": "Location or datacenter where the VM will be placed.",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Azure/region"}
}
},
"domainToJoin":
{
"type": "string",
"metadata": {"description": "The FQDN of the AD domain"}
},
"domainUsername":
{
"type": "string",
"metadata": {"description": "Username of the account on the domain"}
},
"domainPassword":
{
"type": "securestring",
"metadata": {"description": "Password of the account on the domain"}
},
"ouPath":
{
"type": "string",
"metadata": {"description": "Specifies an organizational unit (OU) for the domain account. Enter the full distinguished name of the OU in quotation marks. Example: 'OU=testOU; DC=domain; DC=Domain; DC=com"}
},
"sizeOfDiskInGB":
{
"type": "int",
"defaultValue": 200,
"metadata": {"description": "The disk size for the OS drive in the VM, in GBs. Default Value is 500"}
},
"existingBootDiagStorageResourceGroup":
{
"type": "string",
"metadata": {"description": "Storage account resource group name where boot diagnistics will be stored"}
},
"existingBootDiagStorageName":
{
"type": "string",
"metadata":
{
"description": "Storage account name where boot diagnistics will be stored. It should be at the same location as the VM.",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Storage/storageAccounts"}
}
},
"existingvNetResourceGroup":
{
"type": "string",
"metadata":
{
"description": "Resource Group of the Existing Virtual Network.",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Resources/resourceGroups"}
}
},
"existingvNetName":
{
"type": "string",
"metadata":
{
"description": "Existing Virtual Network to connect to Network Interface to.It should be at the same location as the VM.",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Network/virtualNetworks"}
}
},
"subnetName":
{
"type": "string",
"metadata":
{
"description": "The Subnet for the VM.",
"SNC::Parameter::Metadata": {"referenceType": "Microsoft.Network/subNets"}
}
}
},
"variables":
{
"storageAccountType": "Standard_LRS",
"vnetID": "[resourceId(parameters('existingvNetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('existingvNetName'))]",
"subnetRef": "[concat(variables('vnetID'),'/subnets/', parameters('subnetName'))]",
"StartOfCountString": "[String(Parameters('StartOfCount'))]"
},
"resources":
[
{
"apiVersion": "[providers('Microsoft.Network','networkInterfaces').apiVersions[0]]",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm-vNic')]",
"location": "[parameters('vmLocation')]",
"copy": {
"name": "nicLoop",
"count": "[parameters('numberOfInstances')]"
},
"properties":
{
"ipConfigurations":
[
{
"name": "Prod",
"properties":
{
"privateIPAllocationMethod": "Dynamic",
"subnet": {"id": "[variables('subnetRef')]"}
}
}
]
}
},
{
"apiVersion": "[providers('Microsoft.Compute','virtualMachines').apiVersions[0]]",
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm')]",
"location": "[parameters('vmLocation')]",
"copy": {
"name": "vmLoop",
"count": "[parameters('numberOfInstances')]"
},
"dependsOn": ["nicLoop"],
"tags":
{
"Project": "***"
},
"properties":
{
"hardwareProfile": {"vmSize": "[parameters('vmSize')]"},
"osProfile":
{
"computerName": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]",
"windowsConfiguration": {"enableAutomaticUpdates": false}
},
"storageProfile":
{
"imageReference": {
"id": "/subscriptions/***/resourceGroups/***/providers/Microsoft.Compute/images/***"
},
"osDisk":
{
"name": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm-osDisk')]",
"createOption": "FromImage",
"diskSizeGB": "[parameters('sizeOfDiskInGB')]",
"caching": "ReadWrite",
"managedDisk": {"storageAccountType": "[variables('storageAccountType')]"}
}
},
"networkProfile": {"networkInterfaces": [{"id": "[resourceId('Microsoft.Network/networkInterfaces',concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm-vNic'))]"}]},
"diagnosticsProfile":
{
"bootDiagnostics":
{
"enabled": true,
"storageUri": "[reference(resourceId(parameters('existingBootDiagStorageResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('existingBootDiagStorageName')), '2015-06-15').primaryEndpoints['blob']]"
}
}
}
}
]
}
但是,如果我将其添加到底部的资源中,那么它将无法正常工作。
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(variables('StartOfCountString')),3, '0'), '/JoinDomain')]",
"location": "[resourceGroup().location]",
"copy": {
"name": "DomainJoinLoop",
"count": "[parameters('numberOfInstances')]"
},
"dependsOn": "[concat('Microsoft.Compute/virtualMachines/', concat(parameters('vmNamePrefix'), padLeft(copyIndex(variables('StartOfCountString')),3, '0')))]",
"properties": {
"publisher": "Microsoft.Compute",
"type": "JsonADDomainExtension",
"typeHandlerVersion": "1.3",
"autoUpgradeMinorVersion": true,
"settings": {
"Name": "[parameters('domainToJoin')]",
"User": "[concat(parameters('domainToJoin'), '\\', parameters('domainUsername'))]",
"OUPath": "[parameters('ouPath')]",
"Restart": "true",
"Options": "3"
},
"protectedsettings": {
"Password": "[parameters('domainPassword')]"
}
}
}
在代码的copyIndex部分中,我尝试了变量和参数来设置copyIndex的偏移量。我也尝试过硬编码。我不断收到这样的错误。
{“ telemetryId”:“ 649e0a7f-2c22-41f9-bede-c13618f5053a”, “ bladeInstanceId”:“ Blade_b45c7efadff74340820345aa2e9d76c1_26_0”, “ galleryItemId”:“ Microsoft.Template”,“ createBlade”:“ DeployToAzure”, “ code”:“ InvalidRequestContent”,“ message”:“请求内容为 无效,无法反序列化:'转换值时出错 \“ [concat('Microsoft.Compute / virtualMachines /', concat(参数('vmNamePrefix'), padLeft(copyIndex(variables('StartOfCountString')),3,'0'))))\“至 输入“ System.String []”。路径 'properties.template.resources [1] .resources [0] .dependsOn',第259行, 位置171。'。“}
我要为复制索引设置偏移量的原因是,我可以构建10台机器,例如W2016SRV-001、002,... 010,然后再构建更多从011,012开始的机器, 013,等等。
还有其他解决方法,但我确实希望能够在ARM模板中做到这一点,但我在进行了广泛的搜索之后仍不知道为什么不可行。
............................................... ................................
好的,因此在按照@ 4c74356b41的建议编辑模板后,当我尝试通过门户部署模板时,我现在遇到了一个全新的错误。
{"telemetryId":"649e0a7f-2c22-41f9-bede-c13618f5053a",
"bladeInstanceId":"Blade_b45c7efadff74340820345aa2e9d76c1_26_0",
"galleryItemId":"Microsoft.Template","createBlade":"DeployToAzure",
"code":"InvalidTemplate",
"message":"Deployment template validation failed: 'The template resource
'[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'),
'-vm/JoinDomain')]'
at line '250' column '13' is not valid. Copying nested resources is not supported.
Please see https://aka.ms/arm-copy/#looping-on-a-nested-resource for usage details.'."}
因此,按照错误消息中的链接进行操作,然后阅读更多内容……我需要做的是将Domain Join Extension作为VM的子级删除,并将其作为顶级资源。哇,它奏效了。
所以现在我的ARM模板的结尾看起来像这样。
*** VM bits are here ***
}
}
}, <-- end of the VM bits.
{
"apiVersion": "2016-03-30",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm/JoinDomain')]",
"location": "[resourceGroup().location]",
"copy": {
"name": "DomainJoinLoop",
"count": "[parameters('numberOfInstances')]"
},
"dependsOn": [ "vmLoop" ],
"properties":
{
"publisher": "Microsoft.Compute",
"type": "JsonADDomainExtension",
"typeHandlerVersion": "1.3",
"autoUpgradeMinorVersion": true,
"settings":
{
"Name": "[parameters('domainToJoin')]",
"User": "[concat(parameters('domainToJoin'), '\\', parameters('domainUsername'))]",
"OUPath": "[parameters('ouPath')]",
"Restart": "true",
"Options": "3"
},
"protectedsettings": {"Password": "[parameters('domainPassword')]"}
}
}
],
"outputs":
{}
}
并行部署的多个VM都已毫无问题地加入了域。
所以,我的经验教训是这些,我希望它们将来能对其他人有所帮助。
答案 0 :(得分:0)
比较您的虚拟机名称和扩展名:
concat(parameters('vmNamePrefix'), padLeft(copyIndex(parameters('StartOfCount')),3, '0'), '-vm')
concat(parameters('vmNamePrefix'), padLeft(copyIndex(variables('StartOfCountString')),3, '0'), '/JoinDomain')
除了您使用不必要的变量之外,您还缺少-vm
。扩展名的格式必须为parent_name/extension_name
,否则它将不知道此扩展属于哪个父资源(必须始终属于某个虚拟机)。
您的dependsOn
也错了,您可以将其简化为:
"dependsOn": [ "vmLoop" ]