Packer (2)

En esta lección se muestran algunas posibilidades de Packer con máquinas virtuales de VirtualBox.

Ejemplo 1: Actualización de la máquina virtual mediante comandos

En este ejemplo se muestra cómo Packer puede crear una máquina virtual a partir de un fichero .OVA, poner en marcha la máquina virtual, ejecutar comandos en ella y finalmente crear un fichero .OVA con el resultado. Concretamente, en este ejemplo los comandos actualizan el sistema operativo de la máquina virtual.

Para ello necesitamos:

Si el proceso termina correctamente, Packer creará el directorio packer-2-1 y creará en él el fichero packer-2-1-ubuntu-22-04-2-server.ova.

Plantilla de actualización de la máquina virtual (packer-2-1.pkr.hcl)

Documentación de packer: Shells provisioners

Esta podría ser la plantilla de actualización de la máquina virtual:

source "virtualbox-ovf" "mclibre-2-1" {
  source_path          = "packer-1-1/packer-1-1-ubuntu-22-04-2-server.ova"
  guest_additions_mode = "disable"
  boot_wait            = "30s"
  ssh_password         = "mclibre"
  ssh_username         = "mclibre"
  shutdown_command     = "echo 'mclibre' | sudo -S shutdown -h now"
  output_directory     = "packer-2-1"
  vm_name              = "packer-2-1-ubuntu-22-04-2-server"
  format               = "ova"
}

build {
  sources = ["source.virtualbox-ovf.mclibre-2-1"]

  provisioner "shell" {
    execute_command = "echo 'mclibre' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
    inline = [
      "apt update",
      "DEBIAN_FRONTEND=noninteractive apt -yq full-upgrade"
    ]
  }
}

Comentarios:

Ejemplo 2: Instalación de VirtualBox Guest Additions mediante un script

En este ejemplo se muestra cómo Packer puede crear una máquina virtual a partir de un fichero .OVA, poner en marcha la máquina virtual, ejecutar un script en ella y finalmente crear un fichero .OVA con el resultado. Concretamente, en este ejemplo el script actualiza el sistema operativo e instala las VirtualBox Guest Additions en la máquina virtual.

Para ello necesitamos:

Si el proceso termina correctamente, Packer creará el directorio packer-2-2 y creará en él el fichero packer-2-2-ubuntu-22-04-2-server.ova.

Plantilla de instalación de VirtualBox Guest Additions (packer-2-2.pkr.hcl)

Documentación de packer: Shells provisioners

Esta podría ser la plantilla de instalación de Virtual Guest Additions:

source "virtualbox-ovf" "mclibre-2-2" {
  source_path          = "packer-1-1/packer-1-1-ubuntu-22-04-2-server.ova"
  guest_additions_mode = "attach"
  boot_wait            = "30s"
  ssh_password         = "mclibre"
  ssh_username         = "mclibre"
  shutdown_command     = "echo 'mclibre' | sudo -S shutdown -h now"
  output_directory     = "packer-2-2"
  vm_name              = "packer-2-2-ubuntu-22-04-2-server"
  format               = "ova"
}

build {
  sources = ["source.virtualbox-ovf.mclibre-2-2"]

  provisioner "shell" {
    execute_command = "echo 'mclibre' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
    pause_before    = "10s"
    script          = "packer-2-2-script.sh"
  }
}

Este podría ser el script packer-2-2-script.sh de instalación de las VirtualBox Guest Additions (basado en las instrucciones que se comentan en la lección VirtualBox).

sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -yq full-upgrade
sudo DEBIAN_FRONTEND=noninteractive apt -yq install dkms build-essential linux-headers-$(uname -r)
sudo mkdir /mnt/cdrom
sudo mount ./VBoxGuestAdditions.iso /mnt/cdrom
sudo sh /mnt/cdrom/VBoxLinuxAdditions.run --nox11
sudo umount /mnt/cdrom
sudo rm ./VBoxGuestAdditions.iso

Comentario:

Ejemplo 3: Modificación final de la máquina virtual

En este ejemplo se muestra cómo Packer puede modificar las características de una máquina virtual, es decir, crear la máquina virtual a partir de un fichero .OVA, poner en marcha la máquina virtual, modificar las características de la máquina virtual y finalmente crear un fichero .OVA con el resultado. Concretamente, en este ejemplo se modifica el adaptador de red de la máquina virtual.

Para ello necesitamos:

Si el proceso termina correctamente, Packer creará el directorio packer-2-3 y creará en él el fichero packer-2-3-ubuntu-22-04-2-server.ova.

Plantilla de modificación final de la máquina virtual (packer-2-3.pkr.hcl)

Documentación de packer: VirtualBox Builders

Las modificaciones de la máquina virtual se pueden realizar con la propiedad vboxmanage o con la propiedad vboxmanage_post. En este ejemplo vamos a modificar el tipo de adaptador de red (de nat a bridged). Esta modificación debe realizarse con vboxmanage_post, ya que packer parece necesitar que el adaptador sea NAT para poder realizar la conexión SSH con la que comprueba que la máquina es funcional (la comprobación se hace después de realizar las modificaciones de la máquina indicadas en vboxmanage pero antes de las indicadas en vboxmanage_post).

El nombre del adaptador dependerá de la tarjeta de red del ordenador en el que esté instalado VirtualBox, así que es necesario comprobar el nombre del adaptador en cualquier máquina virtual que tenga configurada la red con adaptador puente.

Esta podría ser la plantilla de modificación final de la máquina virtual:

source "virtualbox-ovf" "mclibre-2-3" {
  source_path          = "packer-2-2/packer-2-2-ubuntu-22-04-2-server.ova"
  guest_additions_mode = "disable"
  boot_wait            = "30s"
  ssh_password         = "mclibre"
  ssh_username         = "mclibre"
  shutdown_command     = "echo 'mclibre' | sudo -S shutdown -h now"
  post_shutdown_delay  = "120s"
  vboxmanage_post = [
    ["modifyvm", "{{ .Name }}", "--nic1", "bridged"],
    ["modifyvm", "{{ .Name }}", "--bridgeadapter1", "Realtek PCIe GBE Family Controller"]
  ]
  output_directory = "packer-2-3"
  vm_name          = "packer-2-3-ubuntu-22-04-2-server"
  format           = "ova"
}

build {
  sources = ["source.virtualbox-ovf.mclibre-2-3"]
}

Notas:

Ejemplo 4: Instalación de Docker mediante un script

En este ejemplo, similar al ejemplo 2, se muestra cómo Packer puede crear una máquina virtual a partir de un fichero .OVA, poner en marcha la máquina virtual, ejecutar un script en ella y finalmente crear un fichero .OVA con el resultado. Concretamente, en este ejemplo el script instala Docker en la máquina virtual.

Este ejemplo trabaja a partir de la máquina virtual obtenida en el ejercicio 2 y crea una nueva máquina virtual. Los pasos de instalación de Docker se realizan mediante un script y está basado en el ejercicio 1 de la lección de Docker (1).

Plantilla de instalación de Docker (packer-2-4.pkr.hcl)

Esta podría ser la plantilla de instalación de Docker:

source "virtualbox-ovf" "mclibre-2-4" {
  source_path          = "packer-2-2/packer-2-2-ubuntu-22-04-2-server.ova"
  guest_additions_mode = "disable"
  boot_wait            = "30s"
  ssh_password         = "mclibre"
  ssh_username         = "mclibre"
  shutdown_command     = "echo 'mclibre' | sudo -S shutdown -h now"
  output_directory     = "packer-2-4"
  vm_name              = "packer-2-4-ubuntu-22-04-2-server"
  format               = "ova"
}

build {
  sources = ["source.virtualbox-ovf.mclibre-2-4"]

  provisioner "shell" {
    execute_command = "echo 'mclibre' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
    pause_before    = "10s"
    script          = "packer-2-4-script.sh"
  }
}

Este podría ser el script packer-2-4-script.sh de instalación de Docker (basado en las instrucciones que se comentan en la lección Docker. Ejercicios (1)).

# fuente: https://docs.docker.com/engine/install/ubuntu/
sudo apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get -yq full-upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get -yq install ca-certificates curl gnupg
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get policy docker-ce # simplemente para ver que se va a instalar del repositorio de Docker para Ubuntu 22.04
sudo DEBIAN_FRONTEND=noninteractive apt-get -yq install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl status docker # simplemente para comprobar que docker está activo
sudo apt-get -yq clean
sudo apt-get -yq autoremove

Ejemplo 5: Compresión de imagen OVA de Ubuntu

La forma recomendada de comprimir una máquina virtual Ubuntu de VirtualBox es grabar ceros en las partes no utilizadas del disco mediante la utilidad zerofree y después exportar, clonar o compactar el disco con VirtualBox o la utilidad VBoxManage. Como la utilidad zerofree no funciona sobre unidades montadas, debemos arrancar la máquina virtual con un LiveCD de otra distribución y desde ahí aplicar zerofree a la partición de disco.

En este ejemplo de automatización con Packer, vamos a realizar la compresión utilizando la distribución SystemRescueCD.

Actualmente (marzo de 2023), la última versión disponible de SystemRescueCD es la versión 10.00, publicada el 19 de marzo de 2023. En cdlibre.org hay una sección dedicada a Utilidades de disco, desde la que se puede descargar la última versión disponible.

También puede descargar SystemRescueCD 10.00 de mclibre: SystemRescueCD 10.00 (19/03/23, 747 MB).

Los elementos necesarios para realizar la compresión son los siguientes:

Ejecute la plantilla para obtener la image OVA comprimida:

packer build packer-2-5.pkr.hcl

Si el proceso termina correctamente, Packer creará el directorio packer-2-5 y creará en él el fichero packer-2-5-ubuntu-18-04-3-server.ova.

Plantilla de compresión de la máquina virtual (packer-2-5.pkr.hcl)

Esta podría ser la plantilla de compresión de la máquina virtual:

source "virtualbox-ovf" "mclibre-2-5" {
  source_path          = "packer-2-2/packer-2-2-ubuntu-22-04-2-server.ova"
  guest_additions_mode = "disable"
  vboxmanage = [
    ["showvminfo", "{{ .Name }}"],
    ["storageattach", "{{ .Name }}", "--storagectl", "IDE Controller", "--port", "0", "--device", "1", "--type", "dvddrive", "--medium", "SystemRescueCD-10-00-amd64.iso"],
    ["modifyvm", "{{ .Name }}", "--boot1", "dvd", "--boot2", "disk", "--boot3", "none", "--boot4", "none"]
  ]
  boot_wait = "20s"
  boot_command = [
    "<enter><wait40>",
    "sudo zerofree -v /dev/mapper/ubuntu--vg-ubuntu--lv<enter><wait50s>"
  ]
  communicator            = "none"
  virtualbox_version_file = ""
  shutdown_command        = ""
  vboxmanage_post = [
    ["storageattach", "{{ .Name }}", "--storagectl", "IDE Controller", "--port", "0", "--device", "1", "--type", "dvddrive", "--medium", "none"],
    ["modifyvm", "{{ .Name }}", "--boot1", "disk", "--boot2", "dvd", "--boot3", "none", "--boot4", "none"]
  ]
  output_directory = "packer-2-5"
  vm_name          = "packer-2-5-ubuntu-22-04-2-server"
  format           = "ova"
}

build {
  sources = ["source.virtualbox-ovf.mclibre-2-5"]
}

Comentarios:

Nota: