如何在 Azure 中使用 Packer 來建立 Linux 虛擬機器映像How to use Packer to create Linux virtual machine images in Azure

Azure 中的每個虛擬機器 (VM) 都是透過映像所建立,而映像則會定義 Linux 散發套件和作業系統版本。Each virtual machine (VM) in Azure is created from an image that defines the Linux distribution and OS version. 映像中可包含預先安裝的應用程式與組態。Images can include pre-installed applications and configurations. Azure Marketplace 提供了許多第一方和第三方映像,這些映像適用於最常見的散發套件和應用程式環境,而您也可以建立自己自訂的映像,以符合您的需求。The Azure Marketplace provides many first and third-party images for most common distributions 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.

注意

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 影像產生器,請參閱使用 Azure 映射產生器建立 LINUX VMTo get started with Azure Image Builder, see Create a Linux 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.

使用 az group create 來建立資源群組。Create a resource group with az group create. 下列範例會在 eastus 位置建立名為 myResourceGroup 的資源群組:The following example creates a resource group named myResourceGroup in the eastus location:

az group create -n myResourceGroup -l eastus

建立 Azure 認證Create Azure credentials

Packer 會使用服務主體來向 Azure 驗證。Packer authenticates with Azure using a service principal. Azure 服務主體是安全性識別,可供您與應用程式、服務及諸如 Packer 等自動化工具搭配使用。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.

使用 az ad sp create-for-rbac 建立服務主體,並將 Packer 所需的認證輸出:Create a service principal with az ad sp create-for-rbac and output the credentials that Packer needs:

az ad sp create-for-rbac --query "{ client_id: appId, client_secret: password, tenant_id: tenant }"

上述命令的輸出範例如下所示:An example of the output from the preceding commands is as follows:

{
    "client_id": "f5b6a5cf-fbdf-4a9f-b3b8-3c2cd00225a4",
    "client_secret": "0e760437-bf34-4aad-9f8d-870be799c55d",
    "tenant_id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}

若要向 Azure 驗證,您也需要使用 az account show 取得 Azure 訂用帳戶識別碼:To authenticate to Azure, you also need to obtain your Azure subscription ID with az account show:

az account show --query "{ subscription_id: id }"

您將在下一個步驟中使用這兩個命令的輸出。You use the output from these two commands in the next step.

定義 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 provisioner for Azure that allows you to define Azure resources, such as the service principal credentials created in the preceding step.

建立名為 ubuntu.json** 的檔案,並貼入下列內容。Create a file named ubuntu.json and paste the following content. 針對下列參數輸入您自己的值︰Enter your own values for the following:

參數Parameter 取得位置Where to obtain
client_idclient_id az ad sp 建立命令所產生之輸出的第一行 - appId**First line of output from az ad sp create command - appId
client_secretclient_secret az ad sp 建立命令所產生之輸出的第二行 - password**Second line of output from az ad sp create command - password
tenant_idtenant_id az ad sp 建立命令所產生之輸出的第三行 - tenant**Third line of output from az ad sp create command - tenant
subscription_idsubscription_id az account show 命令所產生的輸出Output from az account show 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": "f5b6a5cf-fbdf-4a9f-b3b8-3c2cd00225a4",
    "client_secret": "0e760437-bf34-4aad-9f8d-870be799c55d",
    "tenant_id": "72f988bf-86f1-41af-91ab-2d7cd011db47",
    "subscription_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",

    "managed_image_resource_group_name": "myResourceGroup",
    "managed_image_name": "myPackerImage",

    "os_type": "Linux",
    "image_publisher": "Canonical",
    "image_offer": "UbuntuServer",
    "image_sku": "16.04-LTS",

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

    "location": "East US",
    "vm_size": "Standard_DS2_v2"
  }],
  "provisioners": [{
    "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'",
    "inline": [
      "apt-get update",
      "apt-get upgrade -y",
      "apt-get -y install nginx",

      "/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync"
    ],
    "inline_shebang": "/bin/sh -x",
    "type": "shell"
  }]
}

此範本會建置 Ubuntu 16.04 LTS 映像、安裝 NGINX,然後取消佈建 VM。This template builds an Ubuntu 16.04 LTS image, installs NGINX, then deprovisions the VM.

注意

如果您擴充此範本來佈建使用者認證,請將取消佈建 Azure 代理程式的佈建程式命令調整為讀取 -deprovision 而不是 deprovision+userIf you expand on this template to provision user credentials, adjust the provisioner command that deprovisions the Azure agent to read -deprovision rather than deprovision+user. +user 旗標會從來源 VM 中移除所有使用者帳戶。The +user flag removes all user accounts from the source VM.

建置 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 specifying your Packer template file as follows:

./packer build ubuntu.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-swtxmqm7ly’
==> azure-arm:  -> Location          : ‘East US’
==> azure-arm:  -> Tags              :
==> azure-arm:  ->> dept : Engineering
==> azure-arm:  ->> task : Image deployment
==> azure-arm: Validating deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> DeploymentName    : ‘pkrdpswtxmqm7ly’
==> azure-arm: Deploying deployment template ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> DeploymentName    : ‘pkrdpswtxmqm7ly’
==> azure-arm: Getting the VM’s IP address ...
==> azure-arm:  -> ResourceGroupName   : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> PublicIPAddressName : ‘packerPublicIP’
==> azure-arm:  -> NicName             : ‘packerNic’
==> azure-arm:  -> Network Connection  : ‘PublicEndpoint’
==> azure-arm:  -> IP Address          : ‘40.76.218.147’
==> azure-arm: Waiting for SSH to become available...
==> azure-arm: Connected to SSH!
==> azure-arm: Provisioning with shell script: /var/folders/h1/ymh5bdx15wgdn5hvgj1wc0zh0000gn/T/packer-shell868574263
    azure-arm: WARNING! The waagent service will be stopped.
    azure-arm: WARNING! Cached DHCP leases will be deleted.
    azure-arm: WARNING! root password will be disabled. You will not be able to login as root.
    azure-arm: WARNING! /etc/resolvconf/resolv.conf.d/tail and /etc/resolvconf/resolv.conf.d/original will be deleted.
    azure-arm: WARNING! packer account and entire home directory will be deleted.
==> azure-arm: Querying the machine’s properties ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> ComputeName       : ‘pkrvmswtxmqm7ly’
==> azure-arm:  -> Managed OS Disk   : ‘/subscriptions/guid/resourceGroups/packer-Resource-Group-swtxmqm7ly/providers/Microsoft.Compute/disks/osdisk’
==> azure-arm: Powering off machine ...
==> azure-arm:  -> ResourceGroupName : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> ComputeName       : ‘pkrvmswtxmqm7ly’
==> azure-arm: Capturing image ...
==> azure-arm:  -> Compute ResourceGroupName : ‘packer-Resource-Group-swtxmqm7ly’
==> azure-arm:  -> Compute Name              : ‘pkrvmswtxmqm7ly’
==> 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-swtxmqm7ly’
==> 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.

從 Azure 映像建立 VMCreate VM from Azure Image

您現在可以使用 az vm create 從您的映像建立 VM。You can now create a VM from your Image with az vm create. 指定您使用 --image 參數所建立的映像。Specify the Image you created with the --image parameter. 下列範例會從 myPackerImage** 建立名為 myVM** 的 VM,並產生 SSH 金鑰 (如果您還未擁有這些金鑰的話)︰The following example creates a VM named myVM from myPackerImage and generates SSH keys if they do not already exist:

az vm create \
    --resource-group myResourceGroup \
    --name myVM \
    --image myPackerImage \
    --admin-username azureuser \
    --generate-ssh-keys

如果想要在不同於您 Packer 映像的資源群組或區域中建立 VM,請指定映像識別碼,而非映像名稱。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. 您可以使用 az image show 取得映像識別碼。You can obtain the image ID with az image show.

建立 VM 需要幾分鐘的時間。It takes a few minutes to create the VM. 在 VM 建立好之後,請記下 Azure CLI 所顯示的 publicIpAddressOnce the VM has been created, take note of the publicIpAddress displayed by the Azure CLI. 此位址可用來透過 Web 瀏覽器存取 NGINX 網站。This address is used to access the NGINX site via a web browser.

若要讓 Web 流量到達您的 VM,請使用 az vm open-port 從網際網路開啟通訊埠 80:To allow web traffic to reach your VM, open port 80 from the Internet with az vm open-port:

az vm open-port \
    --resource-group myResourceGroup \
    --name myVM \
    --port 80

測試 VM 和 NGINXTest VM and NGINX

現在,您可以開啟 Web 瀏覽器,並在網址列輸入 http://publicIpAddressNow you can open a web browser and enter http://publicIpAddress in the address bar. 提供您自己從 VM 建立程序中取得的公用 IP 位址。Provide your own public IP address from the VM create process. 預設 NGINX 網頁即會顯示,如下列範例所示:The default NGINX page is displayed as in the following example:

預設 NGINX 網站

後續步驟Next steps

您也可以使用現有的 Packer 佈建指令碼與 Azure Image Builder 搭配使用。You can also use existing Packer provisioner scripts with Azure Image Builder.