使用 Terraform 從 Packer 自訂映像建立 Azure 虛擬機器擴展集Use Terraform to create an Azure virtual machine scale set from a Packer custom image

在本教學課程中,您要使用 Terraform (英文) 建立和部署一個 Azure 虛擬機器擴展集,此擴展集是使用 Packer 產生的自訂映像,以及使用 HashiCorp 設定語言 (HCL) (英文) 的受控磁碟所建立。In this tutorial, you use Terraform to create and deploy an Azure virtual machine scale set created with a custom image produced using Packer with managed disks using the HashiCorp Configuration Language (HCL).

在本教學課程中,您了解如何:In this tutorial, you learn how to:

  • 設定 Terraform 部署Set up your Terraform deployment
  • 針對 Terraform 部署使用變數和輸出Use variables and outputs for Terraform deployment
  • 建立和部署網路基礎結構Create and deploy a network infrastructure
  • 使用 Packer 建立自訂虛擬機器映像Create a custom virtual machine image using Packer
  • 使用自訂映像建立和部署虛擬機器擴展集Create and deploy a virtual machine scale set using the custom image
  • 建立和部署 JumpboxCreate and deploy a jumpbox

如果您沒有 Azure 訂用帳戶,請在開始前建立 免費帳戶If you don't have an Azure subscription, create a free account before you begin.

開始之前Before you begin

建立檔案結構Create the file structure

在空白目錄中建立使用下列三個名稱的新檔案:Create three new files in an empty directory with the following names:

  • variables.tf:此檔案會保留範本中所使用的變數值。variables.tf This file holds the values of the variables used in the template.
  • output.tf:此檔案描述在部署後顯示的設定。output.tf This file describes the settings that display after deployment.
  • vmss.tf:此檔案包含您要部署之基礎結構的程式碼。vmss.tf This file contains the code of the infrastructure that you are deploying.

建立變數Create the variables

在此步驟中,您要定義可自訂 Terraform 所建立資源的變數。In this step, you define variables that customize the resources created by Terraform.

編輯 variables.tf 檔案,複製下列程式碼,然後儲存變更。Edit the variables.tf file, copy the following code, then save the changes.

variable "location" {
  description = "The location where resources are created"
  default     = "East US"
}

variable "resource_group_name" {
  description = "The name of the resource group in which the resources are created"
  default     = ""
}

注意

resource_group_name 變數的預設值未設定,請定義您自己的值。The default value of the resource_group_name variable is unset, define your own value.

儲存檔案。Save the file.

當您部署 Terraform 範本時,需要取得用來存取應用程式的完整網域名稱。When you deploy your Terraform template, you want to get the fully qualified domain name that is used to access the application. 使用 Terraform 的 output 資源類型,並取得資源的 fqdn 屬性。Use the output resource type of Terraform, and get the fqdn property of the resource.

編輯 output.tf 檔案並複製下列程式碼,以公開虛擬機器的完整網域名稱。Edit the output.tf file, and copy the following code to expose the fully qualified domain name for the virtual machines.

output "vmss_public_ip" {
    value = "${azurerm_public_ip.vmss.fqdn}"
}

在範本中定義網路基礎結構Define the network infrastructure in a template

在此步驟中,您要在新的 Azure 資源群組中建立下列網路基礎結構:In this step, you create the following network infrastructure in a new Azure resource group:

  • 一個具有 10.0.0.0/16 位址空間的 VNETOne VNET with the address space of 10.0.0.0/16
  • 一個具有 10.0.2.0/24 位址空間的子網路One subnet with the address space of 10.0.2.0/24
  • 兩個公用 IP 位址。Two public IP addresses. 其中一個是用於虛擬機器擴展集負載平衡器,另一個用於連線到 SSH JubmoxOne used by the virtual machine scale set load balancer; the other used to connect to the SSH jumpbox

您也需要建立所有資源的資源群組。You also need a resource group where all the resources are created.

編輯並複製 vmss.tf 中的下列程式碼:Edit and copy the following code in the vmss.tf file:


resource "azurerm_resource_group" "vmss" {
  name     = "${var.resource_group_name}"
  location = "${var.location}"

  tags {
    environment = "codelab"
  }
}

resource "azurerm_virtual_network" "vmss" {
  name                = "vmss-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "${var.location}"
  resource_group_name = "${azurerm_resource_group.vmss.name}"

  tags {
    environment = "codelab"
  }
}

resource "azurerm_subnet" "vmss" {
  name                 = "vmss-subnet"
  resource_group_name  = "${azurerm_resource_group.vmss.name}"
  virtual_network_name = "${azurerm_virtual_network.vmss.name}"
  address_prefix       = "10.0.2.0/24"
}

resource "azurerm_public_ip" "vmss" {
  name                         = "vmss-public-ip"
  location                     = "${var.location}"
  resource_group_name          = "${azurerm_resource_group.vmss.name}"
  public_ip_address_allocation = "static"
  domain_name_label            = "${azurerm_resource_group.vmss.name}"

  tags {
    environment = "codelab"
  }
}

注意

我們建議標記要在 Azure 中部署的資源,以方便日後識別。We recommended tagging the resources being deployed in Azure to facilitate their identification in the future.

建立網路基礎結構Create the network infrastructure

在建立 .tf 檔案的目錄中執行下列命令,以初始化 Terraform 環境:Initialize the Terraform environment by running the following command in the directory where you created the .tf files:

terraform init 

提供者外掛程式會從 Terraform 登錄,下載到您執行命令所在之目錄中的 .terraform 資料夾。The provider plugins download from the Terraform registry into the .terraform folder in the directory where you ran the command.

執行下列命令,以在 Azure 中部署基礎結構。Run the following command to deploy the infrastructure in Azure.

terraform apply

確認公用 IP 位址的完整網域名稱對應到您的設定。Verify that the fully qualified domain name of the public IP address corresponds to your configuration.

公用 IP 位址的虛擬機器擴展集 Terraform 完整網域名稱

資源群組包含下列資源:The resource group contains the following resources:

虛擬機器擴展集 Terraform 網路資源

使用 Packer 建立 Azure 映像Create an Azure image using Packer

使用如何在 Azure 中使用 Packer 來建立 Linux 虛擬機器映像教學課程中所述的步驟,建立自訂的 Linux 映像。Create a custom Linux image using the steps outlined in the tutorial, How to use Packer to create Linux virtual machine images in Azure.

按照本教學課程建立已安裝 NGINX 之取消佈建的 Ubuntu 映像。Follow the tutorial to create a deprovisioned Ubuntu image with NGINX installed.

建立 Packer 映像之後,您就會有映像

注意

基於這個教學課程的目的,在 Packer 映像中會執行命令以安裝 nginx。For purposes of this tutorial, in the Packer image, a command is run to installs nginx. 您也可以在建立時執行自己的指令碼。You can also run your own script while creating.

編輯基礎結構以新增虛擬機器擴展集Edit the infrastructure to add the virtual machine scale set

在此步驟中,您可以在先前部署的網路上建立下列資源:In this step, you create the following resources on the network that was previously deployed:

  • 用來服務應用程式的 Azure 負載平衡器,並且將負載平衡器連接到在步驟 4 中部署的公用 IP 位址Azure load balancer to serve the application and attach it to the public IP address that was deployed in step 4
  • 一個 Azure 負載平衡器和服務應用程式的規則,並且將負載平衡器連接到稍早設定的公用 IP 位址。One Azure load balancer and rules to serve the application and attach it to the public IP address configured earlier.
  • Azure 後端位址集區,並將它指派給負載平衡器Azure backend address pool and assign it to the load balancer
  • 應用程式所使用且在負載平衡器上設定的健康情況探查連接埠A health probe port used by the application and configured on the load balancer
  • 位在負載平衡器幕後的虛擬機器擴展集,在稍早部署的 VNet 上執行A virtual machine scale set sitting behind the load balancer, running on the vnet deployed earlier
  • 在虛擬機器擴展集節點上從自訂映像安裝的 Nginx (英文)Nginx on the nodes of the virtual machine scale installed from custom image

vmss.tf 檔案的結尾加入下列程式碼。Add the following code to the end of the vmss.tf file.



resource "azurerm_lb" "vmss" {
  name                = "vmss-lb"
  location            = "${var.location}"
  resource_group_name = "${azurerm_resource_group.vmss.name}"

  frontend_ip_configuration {
    name                 = "PublicIPAddress"
    public_ip_address_id = "${azurerm_public_ip.vmss.id}"
  }

  tags {
    environment = "codelab"
  }
}

resource "azurerm_lb_backend_address_pool" "bpepool" {
  resource_group_name = "${azurerm_resource_group.vmss.name}"
  loadbalancer_id     = "${azurerm_lb.vmss.id}"
  name                = "BackEndAddressPool"
}

resource "azurerm_lb_probe" "vmss" {
  resource_group_name = "${azurerm_resource_group.vmss.name}"
  loadbalancer_id     = "${azurerm_lb.vmss.id}"
  name                = "ssh-running-probe"
  port                = "${var.application_port}"
}

resource "azurerm_lb_rule" "lbnatrule" {
  resource_group_name            = "${azurerm_resource_group.vmss.name}"
  loadbalancer_id                = "${azurerm_lb.vmss.id}"
  name                           = "http"
  protocol                       = "Tcp"
  frontend_port                  = "${var.application_port}"
  backend_port                   = "${var.application_port}"
  backend_address_pool_id        = "${azurerm_lb_backend_address_pool.bpepool.id}"
  frontend_ip_configuration_name = "PublicIPAddress"
  probe_id                       = "${azurerm_lb_probe.vmss.id}"
}

data "azurerm_resource_group" "image" {
  name = "myResourceGroup"
}

data "azurerm_image" "image" {
  name                = "myPackerImage"
  resource_group_name = "${data.azurerm_resource_group.image.name}"
}

resource "azurerm_virtual_machine_scale_set" "vmss" {
  name                = "vmscaleset"
  location            = "${var.location}"
  resource_group_name = "${azurerm_resource_group.vmss.name}"
  upgrade_policy_mode = "Manual"

  sku {
    name     = "Standard_DS1_v2"
    tier     = "Standard"
    capacity = 2
  }

  storage_profile_image_reference {
    id="${data.azurerm_image.image.id}"
  }

  storage_profile_os_disk {
    name              = ""
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  storage_profile_data_disk {
    lun          = 0
    caching        = "ReadWrite"
    create_option  = "Empty"
    disk_size_gb   = 10
  }

  os_profile {
    computer_name_prefix = "vmlab"
    admin_username       = "azureuser"
    admin_password       = "Passwword1234"
  }

  os_profile_linux_config {
    disable_password_authentication = true

    ssh_keys {
      path     = "/home/azureuser/.ssh/authorized_keys"
      key_data = "${file("~/.ssh/id_rsa.pub")}"
    }
  }

  network_profile {
    name    = "terraformnetworkprofile"
    primary = true

    ip_configuration {
      name                                   = "IPConfiguration"
      subnet_id                              = "${azurerm_subnet.vmss.id}"
      load_balancer_backend_address_pool_ids = ["${azurerm_lb_backend_address_pool.bpepool.id}"]
    }
  }
  
  tags {
    environment = "codelab"
  }
}

將下列程式碼加入 variables.tf 來自訂部署:Customize the deployment by adding the following code to variables.tf:

variable "application_port" {
    description = "The port that you want to expose to the external load balancer"
    default     = 80
}

variable "admin_password" {
    description = "Default password for admin"
    default = "Passwwoord11223344"
}

在 Azure 中部署虛擬機器擴展集Deploy the virtual machine scale set in Azure

執行下列命令以視覺化虛擬機器擴展集部署:Run the following command to visualize the virtual machine scale set deployment:

terraform plan

命令的輸出看起來如下圖:The output of the command looks like the following image:

Terraform 新增虛擬機器擴展集方案

在 Azure 中部署其他資源:Deploy the additional resources in Azure:

terraform apply 

資源群組的內容看起來如下圖︰The content of the resource group looks like the following image:

Terraform 虛擬機器擴展集資源群組

開啟瀏覽器並連線到命令傳回的完整網域名稱。Open a browser and connect to the fully qualified domain name that was returned by the command.

將 Jumpbox 新增到現有的網路Add a jumpbox to the existing network

此選用步驟可以使用 Jumpbox 以 SSH 存取虛擬機器擴展集的執行個體。This optional step enables SSH access to the instances of the virtual machine scale set by using a jumpbox.

在您現有的部署中新增下列資源:Add the following resources to your existing deployment:

  • 連線到與虛擬機器擴展集相同子網路的網路介面A network interface connected to the same subnet than the virtual machine scale set
  • 具有此網路介面的虛擬機器A virtual machine with this network interface

vmss.tf 檔案的結尾加入下列程式碼:Add the following code to the end of the vmss.tf file:

resource "azurerm_public_ip" "jumpbox" {
  name                         = "jumpbox-public-ip"
  location                     = "${var.location}"
  resource_group_name          = "${azurerm_resource_group.vmss.name}"
  public_ip_address_allocation = "static"
  domain_name_label            = "${azurerm_resource_group.vmss.name}-ssh"

  tags {
    environment = "codelab"
  }
}

resource "azurerm_network_interface" "jumpbox" {
  name                = "jumpbox-nic"
  location            = "${var.location}"
  resource_group_name = "${azurerm_resource_group.vmss.name}"

  ip_configuration {
    name                          = "IPConfiguration"
    subnet_id                     = "${azurerm_subnet.vmss.id}"
    private_ip_address_allocation = "dynamic"
    public_ip_address_id          = "${azurerm_public_ip.jumpbox.id}"
  }

  tags {
    environment = "codelab"
  }
}

resource "azurerm_virtual_machine" "jumpbox" {
  name                  = "jumpbox"
  location              = "${var.location}"
  resource_group_name   = "${azurerm_resource_group.vmss.name}"
  network_interface_ids = ["${azurerm_network_interface.jumpbox.id}"]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }

  storage_os_disk {
    name              = "jumpbox-osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "jumpbox"
    admin_username = "azureuser"
    admin_password = "Password1234!"
  }

  os_profile_linux_config {
    disable_password_authentication = true

    ssh_keys {
      path     = "/home/azureuser/.ssh/authorized_keys"
      key_data = "${file("~/.ssh/id_rsa.pub")}"
    }
  }

  tags {
    environment = "codelab"
  }
}

編輯 outputs.tf 以新增下列程式碼,以在部署完成時顯示 Jumpbox 的主機名稱:Edit outputs.tf to add the following code that displays the hostname of the jumpbox when the deployment completes:

output "jumpbox_public_ip" {
    value = "${azurerm_public_ip.jumpbox.fqdn}"
}

部署 JumpboxDeploy the jumpbox

部署 Jumpbox。Deploy the jumpbox.

terraform apply 

部署完成之後,資源群組的內容看起來如下圖:Once the deployment has completed, the content of the resource group looks like the following image:

Terraform 虛擬機器擴展集資源群組

注意

Jumpbox 和您所部署虛擬機器擴展集已停用使用密碼登入的功能。Login with a password is disabled on the jumpbox and the virtual machine scale set that you deployed. 請使用 SSH 登入來存取 VM。Log in with SSH to access the VMs.

清理環境Clean up the environment

下列命令會刪除此教學課程中建立的資源:The following commands delete the resources created in this tutorial:

terraform destroy

系統要求確認是否刪除資源時,輸入 yesType yes when asked to confirm for the deletion of the resources. 解構程序可能需要幾分鐘的時間才能完成。The destruction process can take a few minutes to complete.

後續步驟Next steps

在本教學課程中,您使用 Terraform 在 Azure 上部署了虛擬機器擴展集和 Jumpbox。In this tutorial, you deployed a virtual machine scale set and a jumpbox on Azure using Terraform. 您已了解如何︰You learned how to:

  • 初始化 Terraform 部署Initialize Terraform deployment
  • 針對 Terraform 部署使用變數和輸出Use variables and outputs for Terraform deployment
  • 建立和部署網路基礎結構Create and deploy a network infrastructure
  • 使用 Packer 建立自訂虛擬機器映像Create a custom virtual machine image using Packer
  • 使用自訂映像建立和部署虛擬機器擴展集Create and deploy a virtual machine scale set using the custom image
  • 建立和部署 JumpboxCreate and deploy a jumpbox