Kom i kontakt med oss!

Kontakta vår support!

VSTS Build Agent + nodejs – Del 2

Del två | I min förra bloggpost gick vi igenom hur vi med hjälp av DSC kan konfigurera våran VM till att vara en VSTS byggagent med stöd för node.js. Vi kommer nu att fortsätta att titta vidare på hur vi kan automatisera utrullningen till Azure. 

ARM mall

Börja med att skapa ett nytt tomt ”Azure Resoruce Group” Projekt i Visual Studio. Skapa sedan en mapp döpt ”DSC” under projektet. I DSC mappen lägger du sedan DSC filen som vi skapade i del 1 och döper denna till ”BuildAgentConfig.ps1”.

Kopiera följande JSON dokument och ersätt allt innehåll i ”azuredeploy.json” (ARM template filen i ditt projekt).


{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminPassword": {
      "type": "securestring",
      "defaultValue": "Y0urS3curePassw0rd!"
    },
    "numberOfInstances": {
      "type": "int",
      "minValue": 1,
      "defaultValue": 2
    },
    "_artifactsLocation": {
      "type": "string",
      "metadata": {
        "description": "Auto-generated container in staging storage account to receive post-build staging folder upload"
      }
    },
    "_artifactsLocationSasToken": {
      "type": "securestring",
      "metadata": {
        "description": "Auto-generated token to access _artifactsLocation"
      }
    }
  },
  "variables": {
    "BuildAgentConfigArchiveFolder": "DSC",
    "BuildAgentConfigArchiveFileName": "BuildAgentConfig.zip",
    "environment": "Dev",
    "SystemPrefix": "Agent",
    "NamePrefix": "[concat(variables('SystemPrefix'),variables('environment'))]",
    "VMNicPostFix": "[concat(variables('environment'),'-nic')]",
    "availabilitySetName": "[concat(variables('namePrefix'),'-avset')]",
    "VnetName": "[concat(variables('namePrefix'),'-vnet')]",
    "vnetId": "[resourceId('Microsoft.Network/virtualNetworks', variables('VnetName'))]",
    "virtualNetworkSubnetName": "BackendSubnet",
    "subnetRef": "[concat(variables('vnetId'), '/subnets/', variables('virtualNetworkSubnetName'))]"
  },
  "resources": [
    {
      "apiVersion": "2017-03-30",
      "type": "Microsoft.Compute/availabilitySets",
      "name": "[variables('availabilitySetName')]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "AvailabilitySet"
      },
      "properties": {
        "PlatformUpdateDomainCount": 3,
        "PlatformFaultDomainCount": 2
      },
      "sku": {
        "name": "Aligned"
      }
    },
    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[variables('VnetName')]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "VirtualNetwork"
      },
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "[variables('virtualNetworkSubnetName')]",
            "properties": {
              "addressPrefix": "10.0.2.0/24"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2016-03-30",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(variables('NamePrefix'), copyindex(),variables('VMNicPostFix'))]",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "NetworkInterface"
      },
      "copy": {
        "name": "nicLoop",
        "count": "[parameters('numberOfInstances')]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks/', variables('VnetName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2016-04-30-preview",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[concat(variables('NamePrefix'), copyindex())]",
      "copy": {
        "name": "virtualMachineLoop",
        "count": "[parameters('numberOfInstances')]"
      },
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "VSTS Build Agent"
      },
      "dependsOn": [
        "nicLoop",
        "[resourceId('Microsoft.Compute/availabilitySets/', variables('availabilitySetName'))]"
      ],
      "properties": {
        "availabilitySet": {
          "id": "[resourceId('Microsoft.Compute/availabilitySets', variables('availabilitySetName'))]"
        },
        "hardwareProfile": {
          "vmSize": "Standard_B2s"
        },
        "osProfile": {
          "computerName": "[concat(variables('NamePrefix'), copyindex())]",
          "adminUsername": "azadmin",
          "adminPassword": "[parameters('adminPassword')]",
          "windowsConfiguration": {
            "provisionVmAgent": "true"
          }
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftVisualStudio",
            "offer": "VisualStudio",
            "sku": "VS-2017-Ent-Latest-WS2016",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "fromImage",
            "managedDisk": {
              "storageAccountType": "Premium_LRS"
            }
          },
          "dataDisks": []
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('NamePrefix'), copyindex(),variables('VMNicPostFix')))]"
            }
          ]
        }
      },
      "resources": [
        {
          "name": "Microsoft.Powershell.DSC",
          "type": "extensions",
          "location": "[resourceGroup().location]",
          "apiVersion": "2016-03-30",
          "dependsOn": [
            "[resourceId('Microsoft.Compute/virtualMachines', concat(variables('NamePrefix'), copyindex()))]"
          ],
          "tags": {
            "displayName": "BuildAgentConfig"
          },
          "properties": {
            "publisher": "Microsoft.Powershell",
            "type": "DSC",
            "typeHandlerVersion": "2.9",
            "autoUpgradeMinorVersion": true,
            "settings": {
              "configuration": {
                "url": "[concat(parameters('_artifactsLocation'), '/', variables('BuildAgentConfigArchiveFolder'), '/', variables('BuildAgentConfigArchiveFileName'))]",
                "script": "BuildAgentConfig.ps1",
                "function": "Main"
              },
              "configurationArguments": {
                "nodeName": "[concat(variables('NamePrefix'), copyindex())]"
              }
            },
            "protectedSettings": {
              "configurationUrlSasToken": "[parameters('_artifactsLocationSasToken')]"
            }
          }
        }
      ]
    }
  ]
}

Deployment

För att testa mallen kan vi göra en deployment via VS.

  1. Kontrollera så at PAT nyckeln och VSTS informationen i DSC filen är korrekt
  2. Högerklicka på projektet i Visual Studio och välj Deploy, New…
  3. Logga in och välj rätt Azure prenumeration
  4. Skapa en ny resursgrupp
  5. Klicka på Edit Parameters…
  6. Sätt ett admin lösenord, antal instanser och sedan spara
  7. Klicka på Deploy för att starta utrullningen

Efter ca 10min borde servern vara igång och agenten installerad. Logga in i VSTS för att kontrollera att Agenten är online.

Key take away

Namnstandard
Mallen kommer att skapa samtliga resurser med en namnstandard som är baserad på Microsoft best practices https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions

Artifacts
Eftersom våran DSC är en fristående fil så måste vi använda oss av sk. artifacts för att ARM ska hitta filen. _artifactsLocation och _artifactsLocationSasToken sätts automatiskt av Visual Studio vid deployment, men i sista steget när vi går över till VSTS måste vi sätta dessa parametrar själva.

_artifactsLocation är en URL till en Azure blob storage och _artifactsLocationSasToken är en tidsbegränsad åtkomstnyckel till denna plats.

VS Version
Notera att ARM mallen är inställd på att använda en Visual Studio 2017 Enterprise image till våran IaaS VM. Denna image kan tex ersättas med ”VS-2017-Ent-Latest-Preview-WS2016” för att få åtkomst till den senaste preview versionen av Visual Studio 2017.
”offer”: ”VisualStudio”,
”sku”: ”VS-2017-Ent-Latest-WS2016”,
”version”: ”latest”

PAT Nyckel
I del 1 konfigurerade vi DSC mallen med en PAT nyckel för VSTS, var noga med att denna också finns med i detta projekt.

Artifacts Location
Istället för att låta Visual Studio skapa ett storage account, se över din infrastruktur och ta fram ett lagringskonto som kan användas i framtiden med VSTS.

Skicka kommentar

E-postadressen publiceras inte. Obligatoriska fält är märkta *