如何在 ARM 模板中多次 运行 相同的脚本?

How to run same script multiple times in ARM template?

我有一个 powershell 脚本可以在 ARM 模板中安装 VSTS Build Agent。此模板基于 Azure 快速入门模板 here

我想多次使用 "copy" 函数来 运行 脚本,因为我想在部署 VM 时安装 10 个代理。当我尝试部署我的模板时出现此错误:

Error: Code=InvalidTemplate; Message=Deployment template validation failed: 
'The template resource 'CustomScript' at line '247' column '13' is not valid. Copying nested resources is not supported.

我的问题是,如何安装 10 个具有 copy 功能的构建代理,以便我拥有 vsts-agent-1, vsts-agent-2, etc

这是模板的相关片段:

{
      "name": "[parameters('vmName')]",
      "type": "Microsoft.Compute/virtualMachines",
      "location": "[parameters('location')]",
      "apiVersion": "2017-03-30",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
        "[concat('Microsoft.Network/networkInterfaces/', variables('vmNicName'))]"
      ],
      "tags": {
        "displayName": "VM01"
      },
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('vmAdminUserName')]",
          "adminPassword": "[parameters('vmAdminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "[variables('vmImagePublisher')]",
            "offer": "[variables('vmImageOffer')]",
            "sku": "[parameters('vmVisualStudioVersion')]",
            "version": "latest"
          },
          "osDisk": {
            "name": "[concat(parameters('vmName'),'_OSDisk')]",
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('vmNicName'))]"
            }
          ]
        }
      },
      "resources": [
        {
          "name": "CustomScript",
          "type": "extensions",
          "location": "[parameters('location')]",
          "apiVersion": "2015-05-01-preview",
          "dependsOn": [
            "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
          ],
          "properties": {
            "publisher": "Microsoft.Compute",
            "type": "CustomScriptExtension",
            "typeHandlerVersion": "1.4",
            "settings": {
              "fileUris": [
                "[concat(parameters('_artifactsLocation'),'/InstallVSTSAgent.ps1')]"
              ],
              "commandToExecute": "[concat('powershell.exe -ExecutionPolicy Unrestricted -Command .\InstallVSTSAgent.ps1 -vstsAccount ', parameters('vstsAccount'), ' -personalAccessToken ', parameters('personalAccessToken'), ' -AgentName ', parameters('vstsAccount'), ' -PoolName ', parameters('poolName'), ' -runAsAutoLogon ', parameters('enableAutologon'), ' -vmAdminUserName ', parameters('vmAdminUserName'), ' -vmAdminPassword ', parameters('vmAdminPassword'))]"
            }
          }
        }
      ]

EDIT1

我已经更新了模板并将子资源移出,以便子资源与父资源处于同一级别。此部分现在看起来像这样:

{
  "name": "CustomScript",
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "location": "[parameters('location')]",
  "apiVersion": "2015-05-01-preview",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"
  ],
  "copy": {
    "name": "customScriptGroup",
    "count": "[parameters('agentCount')]"
  },
  "properties": {
    "publisher": "Microsoft.Compute",
    "type": "CustomScriptExtension",
    "typeHandlerVersion": "1.4",
    "protectedSettings": {
      "fileUris": [
        "[concat(parameters('_artifactsLocation'),'/InstallVSTSAgent.ps1')]"
      ],
      "commandToExecute": "[concat('powershell.exe -ExecutionPolicy Unrestricted -Command .\InstallVSTSAgent.ps1 -vstsAccount ', parameters('vstsAccount'), ' -personalAccessToken ', parameters('personalAccessToken'), ' -AgentName ', parameters('vstsAccount')[copyIndex(1)], ' -PoolName ', parameters('poolName'), ' -runAsAutoLogon ', parameters('enableAutologon'), ' -vmAdminUserName ', parameters('vmAdminUserName'), ' -vmAdminPassword ', parameters('vmAdminPassword'))]"
    }
  }
}

但是,当我尝试部署时出现此错误:

Error: Code=InvalidTemplate; Message=Deployment template validation failed: The template resource 'CustomScript' for type 'Microsoft.Compute/virtualMachines/extensions' at line '247' and column '9' has incorrect segment lengths. A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name.

我相信您要找的就在这里: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple

您可以在其中使用 copyIndex() 函数在循环中迭代以创建多个资源。

上面的 link 有很好的示例和简洁的方法,但是对于上面的模板,如果您希望命名约定也保持一致,则需要对大部分模板进行一些更改使用您的 NIC 等

像这样的东西应该可以帮助你开始:

{
   "name" : "[concat(parameters('vmName'), copyIndex())]",
   "copy": {
      "name" : "vmCopy",
      "count": 10
   }
   ...
   ...
   ...
   "osProfile" : "[concat(parameters('vmName'), copyIndex())]"
   ...
   ...
}

这里的"copy" 属性设置了复制循环的名称和循环次数。上面的例子 link 也说明了如何做到这一点。

希望对您有所帮助!

干杯, 拉奇

我已经能够使用这个脚本在服务器上安装多个代理:

Get-ExecutionPolicy

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser

for($i=0; $i -le 9;  $i++)
{
    $suffix=$i.ToString('00')
    $folder="vsts-agent-win-x64-2.144.2-$suffix"
    $agent="myagent-$suffix"

    "$PSScriptRoot$folder"
    #note: folder needs to be copied for each instance
    #'vsts-agent-win-x64-2.144.2' is the folder after downloading and unzipping agent -manually.
    Copy-Item "$PSScriptRoot\vsts-agent-win-x64-2.144.2" "$PSScriptRoot$folder" -Recurse

    cd $PSScriptRoot$folder
 #.\config.cmd --unattended --url https://myaccount.visualstudio.com --auth pat --token myToken --pool 
#default --agent myAgent --runAsAutoLogon --windowsLogonAccount myDomain\myUserName 
#--windowsLogonPassword myPassword
    Write-Host "vsts-agent-win-x64-2.144.2-$suffix"

     .\config.cmd    --unattended `
                    --url "https://devops.my.org/org/" ` #(url of tfs)
                    --auth "pat" `
                    --token "u7s2mbna5v7heqzyfmz5ufrnvlektessebs7flfaf2ll4efzuj7q" `  (tfs token)
                    --pool "foiaModernization" `
                    --agent $agent `
                    --replace `
                    --acceptTeeEula `
                    --runAsService `
                    --windowsLogonAccount "xxx\yyy" `  #not sure if these lines are needed
                    --windowsLogonPassword "JJJJJlllll!!11" #not sure if these lines are 

}