Udostępnij za pośrednictwem


PowerShell: Jak używać programu Packer do tworzenia obrazów maszyn wirtualnych na platformie Azure

Dotyczy: ✔️ maszyny wirtualne z systemem Windows

Każda maszyna wirtualna na platformie Azure jest tworzona na podstawie obrazu definiującego dystrybucję systemu Windows i wersję systemu operacyjnego. Obrazy mogą zawierać wstępnie zainstalowane aplikacje i konfiguracje. Witryna Azure Marketplace udostępnia wiele obrazów pierwszej i innej firmy dla najczęściej używanych środowisk systemu operacyjnego i aplikacji. Możesz też tworzyć własne niestandardowe obrazy dostosowane do Twoich potrzeb. W tym artykule szczegółowo opisano sposób używania narzędzia open source Packer do definiowania i kompilowania obrazów niestandardowych na platformie Azure.

Ten artykuł został ostatnio przetestowany w dniu 5.08.2020 r. przy użyciu narzędzia Packer w wersji 1.8.1.

Uwaga

Platforma Azure ma teraz usługę Azure Image Builder do definiowania i tworzenia własnych obrazów niestandardowych. Usługa Azure Image Builder jest oparta na programie Packer, dzięki czemu możesz nawet używać istniejących skryptów aprowizacji powłoki Packer. Aby rozpocząć pracę z usługą Azure Image Builder, zobacz Tworzenie maszyny wirtualnej z systemem Windows przy użyciu narzędzia Azure Image Builder.

Tworzenie grupy zasobów platformy Azure

Podczas procesu kompilacji program Packer tworzy tymczasowe zasoby platformy Azure podczas kompilowania źródłowej maszyny wirtualnej. Aby przechwycić źródłową maszynę wirtualną do użycia jako obraz, należy zdefiniować grupę zasobów. Dane wyjściowe z procesu kompilacji Packer są przechowywane w tej grupie zasobów.

Utwórz grupę zasobów za pomocą polecenia New-AzResourceGroup. Poniższy przykład tworzy grupę zasobów o nazwie myPackerGroup w lokalizacji eastus :

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

Tworzenie poświadczeń platformy Azure

Narzędzie Packer uwierzytelnia się na platformie Azure przy użyciu jednostki usługi. Jednostka usługi platformy Azure to tożsamość zabezpieczeń, której można używać z aplikacjami, usługami i narzędziami automatyzacji, takimi jak Packer. Kontrolujesz i definiujesz uprawnienia dotyczące operacji, które jednostka usługi może wykonywać na platformie Azure.

Utwórz jednostkę usługi za pomocą polecenia New-AzADServicePrincipal. Wartość parametru -DisplayName musi być unikatowa. Zastąp wartość własną zgodnie z potrzebami.

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

Następnie wprowadź hasło i identyfikator aplikacji.

$plainPassword
$sp.AppId

Aby przeprowadzić uwierzytelnianie na platformie Azure, musisz również uzyskać identyfikatory dzierżawy i subskrypcji platformy Azure za pomocą polecenia Get-AzSubscription:

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

Definiowanie szablonu programu Packer

Aby utworzyć obrazy, należy utworzyć szablon jako plik JSON. W szablonie definiuje się konstruktorów i aprowizatorów, które wykonują rzeczywisty proces kompilacji. Narzędzie Packer ma konstruktora dla platformy Azure, który umożliwia definiowanie zasobów platformy Azure , takich jak poświadczenia jednostki usługi utworzone w poprzednim kroku.

Utwórz plik o nazwie windows.json i wklej następującą zawartość. Wprowadź własne wartości dla następujących elementów:

Parametr Gdzie uzyskać
client_id Wyświetlanie identyfikatora jednostki usługi za pomocą polecenia $sp.AppId
client_secret Wyświetlanie automatycznie wygenerowanego hasła za pomocą polecenia $plainPassword
tenant_id Dane wyjściowe polecenia $sub.TenantId
subscription_id Dane wyjściowe polecenia $sub.SubscriptionId
managed_image_resource_group_name Nazwa grupy zasobów utworzonej w pierwszym kroku
managed_image_name Nazwa utworzonego obrazu dysku zarządzanego
{
  "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 } }"
    ]
  }]
}

Możesz również utworzyć plik o nazwie windows.pkr.hcl i wkleić następującą zawartość z własnymi wartościami używanymi w powyższej tabeli parametrów.

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 } }"]
  }

}

Ten szablon tworzy maszynę wirtualną z systemem Windows Server 2016, instaluje usługi IIS, a następnie uogólnia maszynę wirtualną za pomocą narzędzia Sysprep. Instalacja usług IIS pokazuje, jak można użyć programu PowerShell provisioner do uruchamiania dodatkowych poleceń. Końcowy obraz packer zawiera następnie wymaganą instalację i konfigurację oprogramowania.

Agent gościa systemu Windows uczestniczy w procesie Sysprep. Agent musi być w pełni zainstalowany, zanim maszyna wirtualna będzie mogła być sysprep'ed. Aby upewnić się, że jest to prawdą, wszystkie usługi agenta muszą być uruchomione przed wykonaniem sysprep.exe. Powyższy fragment kodu JSON przedstawia jeden ze sposobów wykonania tej czynności w aprowizatorze programu PowerShell. Ten fragment kodu jest wymagany tylko wtedy, gdy maszyna wirtualna jest skonfigurowana do zainstalowania agenta, co jest ustawieniem domyślnym.

Obraz programu Build Packer

Jeśli nie masz jeszcze zainstalowanego narzędzia Packer na komputerze lokalnym, postępuj zgodnie z instrukcjami instalacji narzędzia Packer.

Skompiluj obraz, otwierając wiersz polecenia i określając plik szablonu narzędzia Packer w następujący sposób:

packer build windows.json

Obraz można również skompilować, określając plik windows.pkr.hcl w następujący sposób:

packer build windows.pkr.hcl

Przykładowe dane wyjściowe z poprzednich poleceń są następujące:

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

Utworzenie maszyny wirtualnej, uruchomienie aprowizacji i wyczyszczenie wdrożenia trwa kilka minut.

Tworzenie maszyny wirtualnej na podstawie obrazu narzędzia Packer

Teraz możesz utworzyć maszynę wirtualną na podstawie obrazu za pomocą polecenia New-AzVM. Pomocnicze zasoby sieciowe są tworzone, jeśli jeszcze nie istnieją. Po wyświetleniu monitu wprowadź nazwę użytkownika i hasło administracyjne do utworzenia na maszynie wirtualnej. Poniższy przykład tworzy maszynę wirtualną o nazwie myVM z obrazu myPackerImage:

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

Jeśli chcesz utworzyć maszyny wirtualne w innej grupie zasobów lub regionie niż obraz programu Packer, określ identyfikator obrazu, a nie nazwę obrazu. Identyfikator obrazu można uzyskać za pomocą polecenia Get-AzImage.

Utworzenie maszyny wirtualnej na podstawie obrazu narzędzia Packer zajmuje kilka minut.

Testowanie maszyny wirtualnej i serwera internetowego

Uzyskaj publiczny adres IP maszyny wirtualnej za pomocą polecenia Get-AzPublicIPAddress. W poniższym przykładzie uzyskano utworzony wcześniej adres IP myPublicIP:

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

Aby wyświetlić maszynę wirtualną, która obejmuje instalację usług IIS z usługi Packer provisioner, wprowadź publiczny adres IP w przeglądarce internetowej.

Domyślna witryna usług IIS

Następne kroki

Możesz również użyć istniejących skryptów inicjowania obsługi administracyjnej pakietu za pomocą narzędzia Azure Image Builder.