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.
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.