Packer を使用して Azure に Windows 仮想マシンのイメージを作成する方法How to use Packer to create Windows virtual machine images in Azure

Azure の各仮想マシン (VM) は、Windows ディストリビューションと OS のバージョンを定義するイメージから作成されます。Each virtual machine (VM) in Azure is created from an image that defines the Windows distribution and OS version. イメージには、プリインストールされているアプリケーションと構成を含めることができます。Images can include pre-installed applications and configurations. Azure Marketplace には、ほとんどの OS およびアプリケーション環境用の自社製およびサード パーティ製のイメージが数多く用意されています。また、ニーズに合わせて独自のイメージを作成することもできます。The Azure Marketplace provides many first and third-party images for most common OS' and application environments, or you can create your own custom images tailored to your needs. この記事では、オープン ソース ツール Packer を使用して Azure に独自のイメージを定義およびビルドする方法について、詳しく説明します。This article details how to use the open-source tool Packer to define and build custom images in Azure.

この記事は、2019 年 2 月 21 日に Az PowerShell モジュール バージョン 1.3.0 と Packer バージョン 1.3.4 を使用して最後にテストされました。This article was last tested on 2/21/2019 using the Az PowerShell module version 1.3.0 and Packer version 1.3.4.

注意

Azure では、お客様独自のカスタム イメージを定義して作成できるサービス (Azure Image Builder (プレビュー)) が提供されるようになっています。Azure now has a service, Azure Image Builder (preview), for defining and creating your own custom images. Azure Image Builder は Packer が基になっているため、既存の Packer シェル プロビジョナー スクリプトを使うこともできます。Azure Image Builder is built on Packer, so you can even use your existing Packer shell provisioner scripts with it. Azure Image Builder の概要については、「Azure Image Builder で Windows VM を作成する」をご覧ください。To get started with Azure Image Builder, see Create a Windows VM with Azure Image Builder.

Azure リソース グループを作成するCreate Azure resource group

ビルド プロセス中、Packer はソース VM をビルドする際に一時的な Azure リソースを作成します。During the build process, Packer creates temporary Azure resources as it builds the source VM. イメージとして使用するためにそのソース VM をキャプチャするには、リソース グループを定義する必要があります。To capture that source VM for use as an image, you must define a resource group. Packer のビルド プロセスからの出力は、このリソース グループに格納されます。The output from the Packer build process is stored in this resource group.

New-AzResourceGroup を使用して Azure リソース グループを作成します。Create a resource group with New-AzResourceGroup. 次の例では、myResourceGroup という名前のリソース グループを eastus に作成します。The following example creates a resource group named myResourceGroup in the eastus location:

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

Azure 資格情報の作成Create Azure credentials

Packer はサービス プリンシパルを使用して Azure で認証されます。Packer authenticates with Azure using a service principal. Azure のサービス プリンシパルは、アプリケーション、サービス、および Packer などのオートメーション ツールで使用できるセキュリティ ID です。An Azure service principal is a security identity that you can use with apps, services, and automation tools like Packer. Azure でサービス プリンシパルが実行できる操作を設定するアクセス許可の制御と定義を行います。You control and define the permissions as to what operations the service principal can perform in Azure.

New-AzADServicePrincipal を使用してサービス プリンシパルを作成し、そのサービス プリンシパルにアクセス許可を割り当て、New-AzRoleAssignment を使用してリソースを作成および管理します。Create a service principal with New-AzADServicePrincipal and assign permissions for the service principal to create and manage resources with New-AzRoleAssignment. -DisplayName の値は一意である必要があります。必要に応じて独自の値に置き換えてください。The value for -DisplayName needs to be unique; replace with your own value as needed.

$sp = New-AzADServicePrincipal -DisplayName "PackerServicePrincipal"
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp.Secret)
$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
New-AzRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $sp.ApplicationId

その後、パスワードとアプリケーション ID を出力します。Then output the password and application ID.

$plainPassword
$sp.ApplicationId

Azure に対して認証するには、Get-AzSubscription を使用して Azure のテナントとサブスクリプション ID も取得する必要があります。To authenticate to Azure, you also need to obtain your Azure tenant and subscription IDs with Get-AzSubscription:

Get-AzSubscription

Packer テンプレートを定義するDefine Packer template

イメージをビルドするには、テンプレートを JSON ファイルとして作成します。To build images, you create a template as a JSON file. テンプレートでは、実際のビルド プロセスを実行するビルダーとプロビジョナーを定義します。In the template, you define builders and provisioners that carry out the actual build process. Packer には Azure 用のビルダーが用意されており、前の手順で作成したサービス プリンシパルの資格情報などの Azure リソースを定義できます。Packer has a builder for Azure that allows you to define Azure resources, such as the service principal credentials created in the preceding step.

windows.json というファイルを作成し、次のコンテンツを貼り付けます。Create a file named windows.json and paste the following content. 次に対応する実際の値を入力します。Enter your own values for the following:

パラメーターParameter 入手場所Where to obtain
client_idclient_id $sp.applicationId でサービス プリンシパル ID を表示しますView service principal ID with $sp.applicationId
client_secretclient_secret $plainPassword を使用して自動生成されたパスワードを表示しますView the auto-generated password with $plainPassword
tenant_idtenant_id $sub.TenantId コマンドからの出力Output from $sub.TenantId command
subscription_idsubscription_id $sub.SubscriptionId コマンドからの出力Output from $sub.SubscriptionId command
managed_image_resource_group_namemanaged_image_resource_group_name 最初の手順で作成したリソース グループの名前Name of resource group you created in the first step
managed_image_namemanaged_image_name 作成されるマネージド ディスク イメージの名前Name for the managed disk image that is created
{
  "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": "myResourceGroup",
    "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"
    },

    "location": "East US",
    "vm_size": "Standard_DS2_v2"
  }],
  "provisioners": [{
    "type": "powershell",
    "inline": [
      "Add-WindowsFeature Web-Server",
      "& $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 } }"
    ]
  }]
}

このテンプレートは、Windows Server 2016 VM を作成し、IIS をインストールした後、Sysprep で VM を一般化します。This template builds a Windows Server 2016 VM, installs IIS, then generalizes the VM with Sysprep. IIS のインストールでは、PowerShell プロビジョナーを使用して追加のコマンドを実行する方法が示されます。The IIS install shows how you can use the PowerShell provisioner to run additional commands. 最終的な Packer イメージには、必要なソフトウェアのインストールと構成が含まれます。The final Packer image then includes the required software install and configuration.

Packer イメージをビルドするBuild Packer image

まだローカル コンピューターに Packer がインストールされていない場合は、手順に従って Packer をインストールしてくださいIf you don't already have Packer installed on your local machine, follow the Packer installation instructions.

コマンド プロンプトを開き、次のように Packer テンプレート ファイルを指定して、イメージをビルドします。Build the image by opening a cmd prompt and specifying your Packer template file as follows:

./packer build windows.json

上記のコマンドの出力例は、次のとおりです。An example of the output from the preceding commands is as follows:

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

Packer が VM をビルド、プロビジョナーを実行、およびデプロイメントをクリーンアップするのに数分かかります。It takes a few minutes for Packer to build the VM, run the provisioners, and clean up the deployment.

Packer イメージから VM を作成するCreate a VM from the Packer image

New-AzVM を使用して、イメージから VM を作成できるようになりました。You can now create a VM from your Image with New-AzVM. これらが存在しない場合は、サポート ネットワーク リソースが作成されます。The supporting network resources are created if they do not already exist. 入力を求められたら、VM で作成された管理用のユーザー名とパスワードを入力します。When prompted, enter an administrative username and password to be created on the VM. 次の例では、myPackerImage から myVM という名前の VM を作成します。The following example creates a VM named myVM from myPackerImage:

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

自分の Packer イメージとは異なるリソース グループまたはリージョンで VM を作成する場合は、イメージ名ではなく、イメージ ID を指定します。If you wish to create VMs in a different resource group or region than your Packer image, specify the image ID rather than image name. Get-AzImage を使用してイメージ ID を取得できます。You can obtain the image ID with Get-AzImage.

Packer イメージから VM を作成するには数分かかります。It takes a few minutes to create the VM from your Packer image.

VM と Web サーバーのテストTest VM and webserver

VM のパブリック IP アドレスを取得するには、Get-AzPublicIPAddress を使用します。Obtain the public IP address of your VM with Get-AzPublicIPAddress. 次の例では、先ほど作成した myPublicIP の IP アドレスを取得しています。The following example obtains the IP address for myPublicIP created earlier:

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

Packer プロビジョナーからの IIS インストールを含む VM が動いていることを確認するには、Web ブラウザーにでパブリック IP アドレスを入力します。To see your VM, that includes the IIS install from the Packer provisioner, in action, enter the public IP address in to a web browser.

IIS の既定のサイト

次の手順Next steps

Azure Image Builder では既存の Packer プロビジョナー スクリプトを使うこともできます。You can also use existing Packer provisioner scripts with Azure Image Builder.