Dela via


PowerShell: Använda Packer för att skapa avbildningar av virtuella datorer i Azure

Gäller för: ✔️ Virtuella Windows-datorer

Varje virtuell dator (VM) i Azure skapas från en avbildning som definierar Windows-distributionen och os-versionen. Avbildningar kan innehålla förinstallerade program och konfigurationer. Azure Marketplace innehåller många avbildningar från första och tredje part för de vanligaste operativsystem- och programmiljöerna, eller så kan du skapa egna anpassade avbildningar som är skräddarsydda för dina behov. Den här artikeln beskriver hur du använder verktyget Packer med öppen källkod för att definiera och skapa anpassade avbildningar i Azure.

Den här artikeln testades senast den 2020-08-05 med Packer version 1.8.1.

Kommentar

Azure har nu en tjänst, Azure Image Builder, för att definiera och skapa egna anpassade avbildningar. Azure Image Builder bygger på Packer, så du kan även använda dina befintliga Packer shell provisioner-skript med det. Information om hur du kommer igång med Azure Image Builder finns i Skapa en virtuell Windows-dator med Azure Image Builder.

Skapa En Azure-resursgrupp

Under byggprocessen skapar Packer tillfälliga Azure-resurser när den skapar den virtuella källdatorn. Om du vill avbilda den virtuella källdatorn för användning som en avbildning måste du definiera en resursgrupp. Utdata från Packer-byggprocessen lagras i den här resursgruppen.

Skapa en resursgrupp med New-AzResourceGroup. I följande exempel skapas en resursgrupp med namnet myPackerGroup på platsen eastus :

$rgName = "myPackerGroup"
$location = "East US"
New-AzResourceGroup -Name $rgName -Location $location

Skapa Azure-autentiseringsuppgifter

Packer autentiserar med Azure med hjälp av tjänstens huvudnamn. Ett Huvudnamn för Azure-tjänsten är en säkerhetsidentitet som du kan använda med appar, tjänster och automatiseringsverktyg som Packer. Du styr och definierar behörigheterna för vilka åtgärder tjänstens huvudnamn kan utföra i Azure.

Skapa ett huvudnamn för tjänsten med New-AzADServicePrincipal. Värdet för -DisplayName måste vara unikt. Ersätt med ditt eget värde efter behov.

$sp = New-AzADServicePrincipal -DisplayName "PackerPrincipal" -role Contributor -scope /subscriptions/yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy
$plainPassword = (New-AzADSpCredential -ObjectId $sp.Id).SecretText

Mata sedan ut lösenordet och program-ID:t.

$plainPassword
$sp.AppId

Om du vill autentisera till Azure måste du också hämta dina Azure-klient- och prenumerations-ID:t med Get-AzSubscription:

$subName = "mySubscriptionName"
$sub = Get-AzSubscription -SubscriptionName $subName

Definiera Packer-mall

Skapa avbildningar genom att skapa en mall som en JSON-fil. I mallen definierar du byggare och etablerare som utför själva byggprocessen. Packer har en byggare för Azure som gör att du kan definiera Azure-resurser, till exempel autentiseringsuppgifterna för tjänstens huvudnamn som skapades i föregående steg.

Skapa en fil med namnet windows.json och klistra in följande innehåll. Ange dina egna värden för följande:

Parameter Var du kan hämta
client_id Visa tjänstens huvudnamns-ID med $sp.AppId
client_secret Visa det automatiskt genererade lösenordet med $plainPassword
tenant_id Utdata från $sub.TenantId kommandot
subscription_id Utdata från $sub.SubscriptionId kommandot
managed_image_resource_group_name Namnet på resursgruppen som du skapade i det första steget
managed_image_name Namn på den hanterade diskbild som skapas
{
  "builders": [{
    "type": "azure-arm",

    "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "client_secret": "ppppppp-pppp-pppp-pppp-ppppppppppp",
    "tenant_id": "zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
    "subscription_id": "yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy",

    "managed_image_resource_group_name": "myPackerGroup",
    "managed_image_name": "myPackerImage",

    "os_type": "Windows",
    "image_publisher": "MicrosoftWindowsServer",
    "image_offer": "WindowsServer",
    "image_sku": "2016-Datacenter",

    "communicator": "winrm",
    "winrm_use_ssl": true,
    "winrm_insecure": true,
    "winrm_timeout": "5m",
    "winrm_username": "packer",

    "azure_tags": {
        "dept": "Engineering",
        "task": "Image deployment"
    },

    "build_resource_group_name": "myPackerGroup",
    "vm_size": "Standard_D2_v2"
  }],
  "provisioners": [{
    "type": "powershell",
    "inline": [
      "Add-WindowsFeature Web-Server",
      "while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
      "while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
      "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit",
      "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10  } else { break } }"
    ]
  }]
}

Du kan också skapa en fil med namnet windows.pkr.hcl och klistra in följande innehåll med dina egna värden som används för tabellen ovan.

source "azure-arm" "autogenerated_1" {
  azure_tags = {
    dept = "Engineering"
    task = "Image deployment"
  }
  build_resource_group_name         = "myPackerGroup"
  client_id                         = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
  client_secret                     = "ppppppp-pppp-pppp-pppp-ppppppppppp"
  communicator                      = "winrm"
  image_offer                       = "WindowsServer"
  image_publisher                   = "MicrosoftWindowsServer"
  image_sku                         = "2016-Datacenter"
  managed_image_name                = "myPackerImage"
  managed_image_resource_group_name = "myPackerGroup"
  os_type                           = "Windows"
  subscription_id                   = "yyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyy"
  tenant_id                         = "zzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"
  vm_size                           = "Standard_D2_v2"
  winrm_insecure                    = true
  winrm_timeout                     = "5m"
  winrm_use_ssl                     = true
  winrm_username                    = "packer"
}

build {
  sources = ["source.azure-arm.autogenerated_1"]

  provisioner "powershell" {
    inline = ["Add-WindowsFeature Web-Server", "while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }", "while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }", "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit", "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10  } else { break } }"]
  }

}

Den här mallen skapar en virtuell Windows Server 2016-dator, installerar IIS och generaliserar sedan den virtuella datorn med Sysprep. IIS-installationen visar hur du kan använda PowerShell-etableringsverktyget för att köra ytterligare kommandon. Den sista Packer-avbildningen innehåller sedan nödvändig programinstallation och konfiguration.

Windows-gästagenten deltar i Sysprep-processen. Agenten måste vara helt installerad innan den virtuella datorn kan sysprep'ed. För att säkerställa att detta är sant måste alla agenttjänster köras innan du kör sysprep.exe. Föregående JSON-kodfragment visar ett sätt att göra detta i PowerShell-etableringen. Det här kodfragmentet krävs endast om den virtuella datorn är konfigurerad för att installera agenten, vilket är standard.

Build Packer-avbildning

Om du inte redan har Packer installerat på den lokala datorn följer du installationsanvisningarna för Packer.

Skapa avbildningen genom att öppna en cmd-prompt och ange Packer-mallfilen på följande sätt:

packer build windows.json

Du kan också skapa avbildningen genom att ange filen windows.pkr.hcl enligt följande:

packer build windows.pkr.hcl

Ett exempel på utdata från föregående kommandon är följande:

azure-arm output will be in this color.

==> azure-arm: Running builder ...
    azure-arm: Creating Azure Resource Manager (ARM) client ...
==> azure-arm: Creating resource group ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> Location          : ‘East US’
==> azure-arm:  -> Tags              :
==> azure-arm:  ->> task : Image deployment
==> azure-arm:  ->> dept : Engineering
==> azure-arm: Validating deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Deploying deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Getting the certificate’s URL ...
==> azure-arm:  -> Key Vault Name        : ‘pkrkvpq0mthtbtt’
==> azure-arm:  -> Key Vault Secret Name : ‘packerKeyVaultSecret’
==> azure-arm:  -> Certificate URL       : ‘https://pkrkvpq0mthtbtt.vault.azure.net/secrets/packerKeyVaultSecret/8c7bd823e4fa44e1abb747636128adbb'
==> azure-arm: Setting the certificate’s URL ...
==> azure-arm: Validating deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Deploying deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> DeploymentName    : ‘pkrdppq0mthtbtt’
==> azure-arm: Getting the VM’s IP address ...
==> azure-arm:  -> ResourceGroupName   : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> PublicIPAddressName : ‘packerPublicIP’
==> azure-arm:  -> NicName             : ‘packerNic’
==> azure-arm:  -> Network Connection  : ‘PublicEndpoint’
==> azure-arm:  -> IP Address          : ‘40.76.55.35’
==> azure-arm: Waiting for WinRM to become available...
==> azure-arm: Connected to WinRM!
==> azure-arm: Provisioning with Powershell...
==> azure-arm: Provisioning with shell script: /var/folders/h1/ymh5bdx15wgdn5hvgj1wc0zh0000gn/T/packer-powershell-provisioner902510110
    azure-arm: #< CLIXML
    azure-arm:
    azure-arm: Success Restart Needed Exit Code      Feature Result
    azure-arm: ------- -------------- ---------      --------------
    azure-arm: True    No             Success        {Common HTTP Features, Default Document, D...
    azure-arm: <Objs Version=“1.1.0.1” xmlns=“http://schemas.microsoft.com/powershell/2004/04"><Obj S=“progress” RefId=“0"><TN RefId=“0”><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N=“SourceId”>1</I64><PR N=“Record”><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>
==> azure-arm: Querying the machine’s properties ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> ComputeName       : ‘pkrvmpq0mthtbtt’
==> azure-arm:  -> Managed OS Disk   : ‘/subscriptions/guid/resourceGroups/packer-Resource-Group-pq0mthtbtt/providers/Microsoft.Compute/disks/osdisk’
==> azure-arm: Powering off machine ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> ComputeName       : ‘pkrvmpq0mthtbtt’
==> azure-arm: Capturing image ...
==> azure-arm:  -> Compute ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm:  -> Compute Name              : ‘pkrvmpq0mthtbtt’
==> azure-arm:  -> Compute Location          : ‘East US’
==> azure-arm:  -> Image ResourceGroupName   : ‘myResourceGroup’
==> azure-arm:  -> Image Name                : ‘myPackerImage’
==> azure-arm:  -> Image Location            : ‘eastus’
==> azure-arm: Deleting resource group ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-pq0mthtbtt’
==> azure-arm: Deleting the temporary OS disk ...
==> azure-arm:  -> OS Disk : skipping, managed disk was used...
Build ‘azure-arm’ finished.

==> Builds finished. The artifacts of successful builds are:
--> azure-arm: Azure.ResourceManagement.VMImage:

ManagedImageResourceGroupName: myResourceGroup
ManagedImageName: myPackerImage
ManagedImageLocation: eastus

Det tar några minuter för Packer att skapa den virtuella datorn, köra etableringarna och rensa distributionen.

Skapa en virtuell dator från Packer-avbildningen

Nu kan du skapa en virtuell dator från avbildningen med New-AzVM. De stödjande nätverksresurserna skapas om de inte redan finns. När du uppmanas till det anger du ett administrativt användarnamn och lösenord som ska skapas på den virtuella datorn. I följande exempel skapas en virtuell dator med namnet myVM från myPackerImage:

New-AzVm `
    -ResourceGroupName $rgName `
    -Name "myVM" `
    -Location $location `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -OpenPorts 80 `
    -Image "myPackerImage"

Om du vill skapa virtuella datorer i en annan resursgrupp eller region än din Packer-avbildning anger du avbildnings-ID:t i stället för bildnamnet. Du kan hämta avbildnings-ID:t med Get-AzImage.

Det tar några minuter att skapa den virtuella datorn från Packer-avbildningen.

Testa virtuell dator och webbserver

Hämta den offentliga IP-adressen för den virtuella datorn med Get-AzPublicIPAddress. I följande exempel hämtas IP-adressen för myPublicIP som skapades tidigare:

Get-AzPublicIPAddress `
    -ResourceGroupName $rgName `
    -Name "myPublicIPAddress" | select "IpAddress"

Om du vill se den virtuella datorn, som innehåller IIS-installationen från Packer-etableringsverktyget, anger du i praktiken den offentliga IP-adressen i en webbläsare.

Standardwebbplatsen i IIS

Nästa steg

Du kan också använda befintliga Packer-etableringsskript med Azure Image Builder.