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.

Packer es un software libre publicado bajo la licencia MPL 2.0 y cuyo desarrollo puede seguirse en GitHub.

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.3.3 para Windows 64 bits, publicada el 5 de diciembre de 2018.

Si no encuentra esta versión en la web del programa, puede descargarla desde la página de Descarga de aplicaciones.

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.3.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 o Windows 10, puede añadir estas variables de dos maneras:

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 en cada prueba de instalación de aplicaciones. La instalación es un proceso que tarda más de 10 minutos y que sólo necesitaremos hacer una vez.

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 (packer-1-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 debería ser siempre algo superior al cronometrado.

En caso de que los tiempos de ejecución sean mayores que los tiempos de espera, Packer enviará las pulsaciones antes de tiempo y la instalación no podrá completarse correctamente. Se aconseja seguir con atención la instalación que realiza Packer e identificar el paso en que se produce el problema y es necesario aumentar el tiempo. Si la instalación no se está realizando correctamente, pulse Ctrl+c en la ventana de Símbolo de sistema para interrumpirla. Packer cerrará en su caso la ventana de VirtualBox y borrará los archivos temporales creados. Si por cualquier motivo Packer no puede cerrar la ventana de VirtualBox, ciérrela manualmente y borre los ficheros temporales que hayan quedado en la carpeta de VirtualBox (en Windows, C:\Users\NombreUsuario\VirtualBox VMs).

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": "e8264fa4c417216f4304079bd94f895e",
      "iso_checksum_type": "md5",
      "disk_size": "25000",
      "vboxmanage": [
        ["modifyvm", "{{.Name}}", "--memory", "1024"],
        ["modifyvm", "{{.Name}}", "--vram", "64"]
      ],
      "boot_wait": "10s",
      "boot_command": [
        "<down><down><wait5><enter><wait5>",
        "<enter><wait10>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<down><down><down><down><down><wait5><enter><wait60s>",
        "<tab><wait5><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><wait5><enter><wait5>",
        "<enter><wait10>",
        "<enter><wait5>",
        "<enter><wait5>",
        "<tab><wait5><enter><wait10>",
        "<tab><wait5><enter><wait10>",
        "<tab><wait5><enter><wait90s>",
        "<tab><wait5><enter><wait40s>",
        "<enter><wait10>",
        "<down><down><down><down><down><down><spacebar><wait5><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ínea 9: La máquina virtual tendrá un disco duro de 25 GB.
  • 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). En el ejemplo, la máquina virtual tendrá 1 GB de RAM y la tarjeta de vídeo tendrá 64 MB.
  • 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 pulsando suprimir (<bs>) varias veces(bartolome).
  • Líneas 27-28: En algunos casos, Ubuntu no puede localizar un servidor de horas y muestra una pantalla adicional que solicita confirmar la zona horaria. En ese caso, habría que añadir una línea simplemente pulsando Intro:
            {"<left><wait5><enter><wait5>",
            "<enter><wait10>",
            "<enter><wait10>",
    
  • Línea 36: Tras instalar el sistema operativo, Packer comprueba que puede conectarse con la máquina mediante SSH (y la orden de apagado se envía también por SSH). Por eso en la instalación de Ubuntu es necesario elegir 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 (packer-1-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",
        "DEBIAN_FRONTEND=noninteractive apt-get -yq upgrade"
      ]
    }
  ]
}

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: En vez de apt-get upgrade se usa el comando DEBIAN_FRONTEND=noninteractive apt-get -yq upgrade porque Packer no es un entorno interactivo y no podemos contestar a peticiones de los instaladores. Con esta opción le decimos automáticamente a todo que sí.

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.


Nota: En Windows, Packer 1.2.3 requería que los scripts de shell tuvieran los finales de línea de Unix [packer issue 6151], pero Packer 1.3 ya no tiene esta limitación

Plantilla de instalación de VirtualBox Guest Additions (packer-1-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 las VirtualBox Guest Additions.

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 DEBIAN_FRONTEND=noninteractive apt-get -yq upgrade
sudo apt-get -y install dkms build-essential linux-headers-4.15.0-29-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-29-generic #31-Ubuntu SMP Tue Jul 17 ...

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 (packer-1-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",
      "shutdown_command": "echo 'barto' | sudo -S shutdown -P now",
      "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

Docker está disponible en Ubuntu 18.04 desde junio de 2018. En este ejemplo se instala la versión más reciente de Docker mediante un script.

Este ejemplo trabaja a partir de la máquina virtual obtenida en el ejercicio 4 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-1-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 DEBIAN_FRONTEND=noninteractive apt-get -yq upgrade
sudo apt-get -y install 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 DEBIAN_FRONTEND=noninteractive apt-get -yq upgrade
sudo apt-cache policy docker-ce > info-policy.txt
sudo apt-get -y install 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.
    • info-fingerprint."txt":
      pub   rsa4096 2017-02-22 [SCEA]
          9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
               [desconocida] Docker Release (CE deb) <docker@docker.com>
      sub   rsa4096 2017-02-22 [S]
      
    • info-policy."txt":
      docker-ce:
        Instalados: (ninguno)
        Candidato: 5:18.09.0~ce-0~ubuntu-bionic
        Tabla de versión:
          5:18.09.0~3-0~ubuntu-bionic 500
                500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
          18.06.1~ce~3-0~ubuntu 500
                500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
          ...
      
  • Línea 6: En vez de la versión stable, se pueden probar las versiones edge y nightly.