Packer

Esta lección es una introducción al uso de packer, la herramienta de creación de máquinas virtuales. Como ejemplo, se explica cómo crear una máquina virtual de VirtualBox en la que se instala el sistema operativo Ubuntu Server y posteriormente se instala Docker en ella.

Qué es Packer

Packer es una herramienta de creación de máquinas virtuales. La primera versión se publicó en junio de 2013 y la versión 1.0 se publicó en abril de 2017.

packer Actualizado 16-09-2018 2013 2014 2015 2016 2017 2018 2019 0.1 0.5 0.6 0.7 0.8 0.9 0.10 0.11 0.12 1.0 1.1 1.2 1.3

Listado de novedades en cada versión de Packer.


Packer trabaja a partir de plantillas. Las plantillas son ficheros JSON que le dicen a Packer qué tipo de máquina virtual se quiere crear, los pasos a realizar para instalar el sistema operativo y los comandos o scripts a ejecutar tras la instalación.

Una vez hemos creado la plantilla, Packer permite crear automáticamente tantas máquinas virtuales como necesitemos. Lógicamente, cuantas más máquinas virtuales creemos a partir de una plantilla, más rentabilizaremos el tiempo empleado en la elaboración de la plantilla, pero, aún en el caso de que sólo creemos una vez la máquina virtual, la plantilla nos servirá como documentación y especificación del proceso.

Instalación en Windows

En Windows, packer se distribuye en forma de fichero zip (página de descarga de packer).

Esta lección se ha elaborado con la versión packer 1.2.3 para Windows 64 bits.

Packer no necesita instalación. Simplemente, hay que descomprimir el fichero zip en una carpeta para obtener el programa packer.exe.

Para ejecutar packer, abra una ventana de Símbolo de sistema y ejecute la orden packer con los parámetros adecuados. Por ejemplo, para conocer la versión de packer, ejecute:

C:\packer>packer --version
1.2.3

Para que packer cree un archivo de log del proceso de creación de la plantilla, que nos será muy útil para identificar los errores del proceso, en Windows es necesario establecer dos variables de entorno.

En Windows 7, puede añadir estas variables:

Ejemplos de creación de máquinas virtuales y configuración posterior

Packer permite crear máquinas virtuales para muchos sistemas de virtualización e instalar y configurar en ellas el sistema operativo que queramos.

Las plantillas de packer admiten muchas posiblidades, que se detallan en la documentación oficial de packer.

En esta lección veremos cuatro ejemplos de creación de máquinas virtuales y posterior instalación de aplicaciones en la máquinas:

Una de las ventajas de preparar primero la imagen básica es ahorrarnos la instalación del sistema operativo, un proceso que tarda más de 10 minutos, en cada prueba de instalación de aplicaciones.

Ejemplo 1: Creación de una máquina virtual de VirtualBox con Ubuntu Server 18.04.1 LTS

Para crear la máquina virtual, necesitamos:

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

Plantilla de creación de la máquina virtual (plantilla-1.json)

Documentación de packer: Builders en VirtualBox

En una plantilla de packer, la sección que define la creación de la máquina se denomina constructor (en inglés builder).

Packer instala el sistema operativo en la máquina virtual reproduciendo el proceso manual que realizamos nosotros cuando instalamos el sistema operativo en una máquina virtual.

Así, la plantilla de creación de una máquina virtual e instalación de un sistema operativo contiene tanto la descripción de la máquina virtual que queremos como las entradas de teclado a realizar para la instalación del sistema operativo.

Para obtener las entradas de teclado es necesario primero hacer una instalación manual y anotar cuidadosamente las opciones elegidas y también cronometrar lo que tarda en realizarse cada uno de los pasos de la instalación, ya que en la plantilla debemos indicar también el tiempo que packer debe esperar entre entrada y entrada de teclado. Si el tiempo de espera es demasiado corto, packer enviará las pulsaciones de teclado demasiado pronto y la instalación no se realizará correctamente.

En la lección Instalación de Ubuntu se muestra un ejemplo de instalación de Ubuntu Server 18.04.1 LTS. La página muestra los sucesivos pasos del proceso de instalación y las entradas de teclado y tiempos de espera correspondientes. Por precaución, el tiempo de espera indicado a packer es siempre algo superior al cronometrado.

Esta podría ser la plantilla de creación de la máquina virtual con Ubuntu:

{
  "builders": [
    {
      "type": "virtualbox-iso",
      "guest_os_type": "Ubuntu_64",
      "iso_url": "ubuntu-18.04.1-server-amd64.iso",
      "iso_checksum": "1413c9797dbfa1e57fabfb5c91cfb96f",
      "iso_checksum_type": "md5",
      "disk_size": "25000",
      "vboxmanage": [
        ["modifyvm", "{{.Name}}", "--memory", "1024"],
        ["modifyvm", "{{.Name}}", "--vram", "64"]
      ],
      "boot_wait": "10s",
      "boot_command": [
        "<down><down><enter><wait5>",
        "<enter><wait10>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<down><down><down><down><down><down><enter><wait60s>",
        "<tab><enter><wait5>",
        "Bartolome Sintes<tab><wait5><enter><wait5>",
        "<bs><bs><bs><bs><tab><wait5><enter><wait5>",
        "barto<tab><spacebar><tab><wait5><enter><wait5>",
        "barto<tab><spacebar><tab><wait5><enter><wait5>",
        "<left><enter><wait5>",
        "<enter><wait10>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<tab><enter><wait10>",
        "<tab><enter><wait10>",
        "<tab><enter><wait90s>",
        "<tab><enter><wait40s>",
        "<down><enter><wait10>",
        "<down><down><down><down><down><down><spacebar><tab><enter><wait3m30s>",
        "<enter><wait40s>",
        "<enter><wait40s>"
      ],
      "ssh_username": "barto",
      "ssh_password": "barto",
      "shutdown_command": "echo 'barto' | sudo -S shutdown -P now",
      "output_directory": "packer-1-1",
      "vm_name": "packer-1-1-ubuntu-18-04-1-server",
      "format": "ova"
    }
  ]
}

Comentarios:

  • Líneas 10 a 13: La propiedad vboxmanage indica las características de la máquina virtual. Las características posibles se encuentran en el Manual de VirtualBox: VBoxManage. Algunas características se deben modificar mediante la propiedad vboxmanage_post (véase el ejemplo 4).
  • Línea 24: Ubuntu propone un nombre de usuario a partir del nombre de usuario completo escrito en la pantalla anterior. Dependiendo del nombre propuesto habrá que borrar más o menos caracteres o añadir otros. En el ejemplo simplemente se borran los cuatro últimos caracteres del nombre propuesto por Ubuntu.
  • Línea 36: Tras instalar el sistema operativo, Packer comprueba que puede conectarse con la máquina con SSH (y la orden de apagado se envía también por SSH). Por eso en la instalación de Ubuntu se elige instalar el servidor OpenSSH. La conexión SSH utiliza el usuario administrador creado en la máquina durante la instalación.
  • Línea 42: La propiedad shutdown_command se puede omitir, pero entonces packer apaga la máquina de golpe. Como el comando de apagado requiere el uso del comando sudo, la máquina solicitará la contraseña del usuario. Para enviarla se utiliza el "truco" de incluir el comando echo con la contraseña del usuario.
  • Linea 45: La máquina virtual se guarda en formato ova para que conste de un único fichero.

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

Para actualizar la máquina virtual necesitamos:

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

Plantilla de actualización de la máquina virtual (plantilla-2.json)

Documentación de packer: Shells provisioners

En una plantilla de packer, la sección que define la instalación y configuración de la máquina virtual se denomina proveedor (en inglés provisioner).

En la sección del constructores le indicamos a packer que utilice la imagen creada en el ejemplo anterior y el usuario creado en ella.

En la sección de proveedores le indicemos a packer que ejecute un par de comandos para actualizar el sistema.

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

{
  "builders": [
    {
      "type": "virtualbox-ovf",
      "source_path": "packer-1-1/packer-1-1-ubuntu-18-04-1-server.ova",
      "guest_additions_mode": "disable",
      "boot_wait": "30s",
      "ssh_username": "barto",
      "ssh_password": "barto",
      "shutdown_command": "echo 'barto' | sudo -S shutdown -P now",
      "output_directory": "packer-1-2",
      "vm_name": "packer-1-2-ubuntu-18-04-1-server",
      "format": "ova"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "execute_command": "echo 'barto' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'",
      "inline": [
        "apt-get update",
        "apt-get upgrade -y"
      ]
    }
  ]
}

Comentarios:

  • Línea 6: De forma predeterminada, Packer transfiere la imagen .iso de las VirtualBox Guest Additions a la máquina virtual. En este caso se ha deshabilitado esta transferencia puesto que ya se ha transferido a la imagen inicial creada en el ejemplo 1.
  • Línea 22: Al comando apt upgrade le añadimos la opción -y porque no es un entorno interactivo.

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

Para instalar las VirtualBox Guest Addtions en la máquina virtual necesitamos:

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


¡Atención!Packer 1.2.3 no es capaz de enviar el script si este tiene los finales de línea de Windows [packer issue 6151]. Es necesario asegurarse de que el script tenga finales de línea de Unix.

Plantilla de instalación de VirtualBox Guest Additions (plantilla-3.json)

Documentación de packer: Shells provisioners

En una plantilla de packer, la sección que define la instalación y configuración de la máquina virtual se denomina proveedor (en inglés provisioner).

En la sección del constructores le indicamos a packer que utilice la imagen creada en el ejemplo anterior y el usuario creado en ella.

En la sección de proveedores le indicamos a packer que ejecute un scripts con todos los comandos necesarios para actualizar el sistema e instalar Docker.

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

{
  "builders": [
    {
      "type": "virtualbox-ovf",
      "source_path": "packer-1-1/packer-1-1-ubuntu-18-04-1-server.ova",
      "guest_additions_mode": "disable",
      "boot_wait": "30s",
      "ssh_username": "barto",
      "ssh_password": "barto",
      "shutdown_command": "echo 'barto' | sudo -S shutdown -P now",
      "output_directory": "packer-1-3",
      "vm_name": "packer-1-3-ubuntu-18-04-1-server",
      "format": "ova"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "execute_command": "echo 'barto' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'",
      "script": "script-3.sh",
      "pause_before": "10s"
    }
  ]
}

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

sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install dkms build-essential linux-headers-4.15.0-20-generic
sudo mkdir /mnt/cdrom
sudo mount ~/VBoxGuestAdditions.iso /mnt/cdrom
sudo sh /mnt/cdrom/VBoxLinuxAdditions.run --nox11
sudo umount /mnt/cdrom
rm ~/VBoxGuestAdditions.iso

Comentario:

  • Línea 3: la versión del kernel se puede obtener mediante la orden:
    uname -a

    La respuesta indica la versión del kernel:

    Linux ubuntu 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 ...

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

Para modificar la máquina virtual necesitamos:

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

Plantilla de modificación final de la máquina virtual (plantilla-4.json)

Documentación de packer: VirtualBox Builders

En una plantilla de packer, la sección que define la creación de la máquina se denomina constructor (en inglés builder).

En la sección del constructores le indicamos a packer que utilice la imagen creada en el ejemplo anterior y el usuario creado en ella.

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.

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

{
  "builders": [
    {
      "type": "virtualbox-ovf",
      "source_path": "packer-1-3/packer-1-3-ubuntu-18-04-1-server.ova",
      "guest_additions_mode": "disable",
      "boot_wait": "30s",
      "ssh_username": "barto",
      "ssh_password": "barto",
      "vboxmanage_post": [
        ["modifyvm", "{{.Name}}", "--nic1", "bridged"],
        ["modifyvm", "{{.Name}}", "--bridgeadapter1", "Realtek PCIe GBE Family Controller"]
      ],
      "output_directory": "packer-1-4",
      "vm_name": "packer-1-4-ubuntu-18-04-1-server",
      "format": "ova"
    }
  ]
}

Notas:

  • Línea 12: El nombre del adaptador 1 depende del ordenador en el que esté instalado VirtualBox.

Otros ejemplos

Ejemplo 5: Instalación de Docker mediante un script

Actualmente (mayo de 2018) todavía no hay disponible una versión de docker estable para Ubuntu 18.04.1, aunque sí que está disponible una versión nightly.

Plantilla de instalación de Docker (plantilla-5.json)

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

{
  "builders": [
    {
      "type": "virtualbox-ovf",
      "source_path": "packer-1-1/packer-1-1-ubuntu-18-04-1-server.ova",
      "guest_additions_mode": "disable",
      "boot_wait": "30s",
      "ssh_username": "barto",
      "ssh_password": "barto",
      "shutdown_command": "echo 'barto' | sudo -S shutdown -P now",
      "output_directory": "packer-1-5",
      "vm_name": "packer-1-5-ubuntu-18-04-1-server",
      "format": "ova"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "execute_command": "echo 'barto' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'",
      "script": "script-5.sh",
      "pause_before": "10s"
    }
  ]
}

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

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88 > info-fingerprint.txt
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-cache policy docker-ce > info-policy.txt
sudo apt install -y docker-ce

Comentario:

  • Líneas 5 y 9: El resultado de las comprobaciones de la clave GPG oficial de Docker (línea 5) y de que el comando apt está utilizando el repositorio correcto (línea 9) se guardan en dos ficheros .txt para su comprobación posterior.
  • Línea 6: En vez de la versión stable, se pueden probar las versiones edge y nightly.