Automatizar la creación de las plantillas de tus máquinas virtuales de Azure con HCP Packer

Durante el mes de Octubre, la empresa HashiCorp, creadores de Terraform, anunciaron la beta pública de un nuevo servicio llamado Packer. La idea de este es que podamos automatizar también la generación de las imágenes para las máquinas virtuales que tenemos en las diferentes plataformas. Si bien es cierto que a día de hoy solo existen tutoriales para AWS y Docker en la página oficial, en este artículo te cuento cómo usarlo con Microsoft Azure.

Instalar HCP Packer en tu máquina

Para probar esta nueva herramienta, lo primero que necesitas es instalarla. Esta está disponible para Linux, Mac y Windows. En mi caso la voy a instalar en MacOs con Homebrew:

brew tap hashicorp/tap
brew install hashicorp/tap/packer

Para el resto de plataformas puedes echar un vistazo aquí. Una vez instalado ya podemos empezar a jugar 😊

Definición de una plantilla para un Windows Server 2022 Azure Edition con IIS instalado

El objetivo en este artículo va a ser crear una imagen con Windows Server 2022, Azure Edition, en la que ya tengamos instalado el servidor web, para que veas cómo sería tanto la definición como la ejecución de los comandos que hacen que nuestra imagen esté a punto.

Antes de ello, necesitas tener un service principal con el que la herramienta pueda interactuar con la suscripción de Azure en cuestión. Si todavía no tienes uno, puedes generarlo con el siguiente comando:

az ad sp create-for-rbac --name hcp-packer --role Contributor

El resultado de este la guardaremos en un archivo llamado variables.pkr.hcl como el siguiente:

variable "client_id" {
  type = string
  #   default = "${env("ARM_CLIENT_ID")}"
  default = "<CLIENT_ID>"
}

variable "client_secret" {
  type = string
  #   default = "${env("ARM_CLIENT_SECRET")}"
  default = "<CLIENT_SECRET>"
}

variable "subscription_id" {
  type = string
  # default = "${env("ARM_SUBSCRIPTION_ID")}"
  default = "<SUBSCRIPTION_ID>"
}

variable "tenant_id" {
  type = string
  # default = "${env("ARM_TENANT_ID")}"
  default = "<TENANT_ID>"
}

variable "resource_group" {
  type    = string
  # default = "${env("ARM_RESOURCE_GROUP_NAME")}"
  default = "hcp-packer-demos"
}

variable "location" {
  type    = string
  default = "North Europe"
}

En él te he dejado dos formas de almacenar la información: o bien en texto plano para esta demo, o utilizando variables de entorno (recomendado).

Por último, crea otro archivo con el nombre azure-windows.pkr.hcl donde definiremos cómo será la plantilla de esta nueva imagen:

source "azure-arm" "windows" {

  client_id       = "${var.client_id}"
  client_secret   = "${var.client_secret}"
  subscription_id = "${var.subscription_id}"
  tenant_id       = "${var.tenant_id}"

  location                          = "${var.location}"
  managed_image_resource_group_name = "${var.resource_group}"
  managed_image_name                = "WinSrvWithIIS"
  os_type                           = "Windows"

  vm_size = "Standard_DS1_v2"

  image_offer     = "WindowsServer"
  image_publisher = "MicrosoftWindowsServer"
  image_sku       = "2022-datacenter-azure-edition"
  image_version   = "latest"


  communicator   = "winrm"
  winrm_use_ssl  = "true"
  winrm_insecure = "true"
  winrm_timeout  = "3m"
  winrm_username = "packer"

}

build {

  sources = ["source.azure-arm.windows"]

  provisioner "powershell" {

    inline = [

      # Install IIS with PowerShell
      "Install-WindowsFeature -name Web-Server -IncludeManagementTools",

      "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit /mode:vm",
      "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 } }"
    ]

  }
}

Como ves, la estructura es la misma que en Terraform, y puedes definir tanto el tipo de imagen como los comandos que quieres que se lancen en la misma, para configurarla a tu gusto. En este ejemplo he utilizado un Windows Server 2022 Azure Edition al que le he instalado el servicio de Internet Information Services a través de PowerShell.

Ok, ahora ¿qué hacemos con esto?

Generar la plantilla con HCP Packer

Ahora que ya tienes la plantilla con lo que quieres, generarla es tan sencillo como ejecutar el siguiente comando:

packer build .

Lo que va a hacer es crearse una máquina virtual temporal, con las características definidas en este archivo, y va a lanzar todos los comandos que hayas elegido para su configuración.

packer build .

Una vez que finalice el proceso borrará el grupo de recursos donde había creado dicha máquina y podremos ver el resultado en el grupo de recursos, que has nombrado en la propiedad managed_image_resource_group_name:

Imagen resultante de la herramienta packer

Como te puedes imaginar, esto nos permite versionar las distintas características y servicios/software que necesitamos para un tipo de máquina virtual en concreto y actualizar de forma sencilla estas plantillas sin tener que hacer trabajo manual para ello.

¡Saludos!