Crea todo un entorno de máquinas virtuales con un solo comando, gracias a Vagrant

6
127231

Creación: 06-12-2013

Tutorial dedicado a @OtogamiCOM por su tremenda
y contagiosa ilusión, por ser los inspiradores gracias al «Hacking Day» que organizaron el 06-12-2013, y por ser, sin
lugar a dudas, la mejor forma de encontrar videojuegos al mejor precio.

Índice de contenidos

1. Introducción
2. Entorno
3. Instalación
4. Creando nuestro primer proyecto
4.1. El descriptor
4.2. El box
4.3. Usando el box
4.4. Levantando y entrando en nuestra máquina virtual
4.5. ¿Algún problema con las Guest Addittions?
4.6. Entrando por SSH en nuestra máquina virtual
5. ¿Cómo instalo software de forma que lo vean mis compañeros?
6. Configurando la red de la máquina virtual
7. Despedida y cierre
8. Apendice I – El Vagrantfile
9. Conclusiones
10. Sobre el autor

1. Introducción

Este tutorial trata de máquinas virtuales, nubes, servicios y pereza. ¿Pereza?!?!?! ¿WTF?!?!?! Sí, sí,
pereza, y sino decirme si os sentís identificados con alguna de estas preguntas o similares:

  • ¿Cuántas veces nos hemos visto con la necesidad de instalar tal o cual servicio, base de datos o aplicación en general,
    pero, o no estaba disponible para nuestro sistema operativo, o simplemente nos daba pereza ensuciar nuestro entorno?
  • ¿Cuántas veces hemos tenido que hacer un desarrollo que se integra con otros sistemas, nos los hemos instalado en nuestra
    máquina, y cuando nuestros compañeros se han bajado el código del proyecto no han sido capaces de instalar y configurar
    de igual manera al sistema de terceros, por lo que no les funcionan los tests de integración?
  • ¿Cuántas veces hemos configurado un entorno de máquinas virtuales y nos ha quedado niquelao, y ha llegado alguien y nos
    ha dicho que lo teníamos que replicar en otro sitio, y casi nos da un pasmo al pensar todo el trabajo que tenemos que
    repetir?

Si no te sientes identificado con estas preguntas, o no sabes ni siquiera de qué te estoy hablando, puedes irte
tranquilamente a YouTube a seguir viendo tontunas. Pero si eres de los que las
preguntas anteriores les duelen un poquito, te recomiendo que sigas leyendo hasta el final, porque
Vagrant te va a simplificar muuuuuuuucho todos tus problemas.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2.3 GHz Intel i7, 16GB 1600 Mhz DDR3, 500GB Flash Storage).
  • NVIDIA GeForce G7 750M
  • Sistema Operativo: Mac OS X Lion 10.9
  • Vagrant 1.4.3

3. Instalación

¡Pero bueno! ¿Qué es ese dichoso Vagrant? Vagrant es un sistema que nos permite montar entornos (máquinas virtuales)
fácilmente replicables y configurables. ¿Y qué significa esto? Que podemos preparar un script que cuando lo
ejecuten nuestros compañeros, se encontrarán con el mismo entorno replicado a la perfección. Y por si esto
fuera poco, las máquinas que creamos con Vagrants las podemos desplegar en VirtualBox, VMware,
AWS (Amazon Web Services), u otros proveedores. Con lo que podemos usarlas tanto en desarrollo como
luego llevarlas a producción.

Vagrant por defecto trabaja con VirtualBox, así que como
requisito debemos instalarlo primero.

Para instalar Vagrant basta con ir a su página http://www.vagrantup.com/
y pinchar sobre su enorme botón de Download.

Una vez descargado el archivo (en mi caso Vagrant-1.4.3.dmg), hacemos doble click para abrirlo, y luego hacemos
doble click sobre el instalador, y seguiremos sus instrucciones.

4. Creando nuestro primer proyecto

4.1. El descriptor

Un proyecto se define por el fichero de configuración Vagrantfile. Este fichero define:

  • Dónde se encuentra el directorio base del proyecto.
  • Describe el tipo de máquina y recursos que necesitamos para ejecutar nuestro proyecto, así como el software
    que necesitamos instalar y cómo queremos acceder a él.

Para crear este fichero en el directorio donde nos encontremos podemos ejecutar el comando: $ vagrant init

 

4.2. El box

Ahora para crear la máquina virtual vamos a utilizar lo que Vagrant denomina un box. En vez de
crear la máquina virtual desde cero, lo que sería lento y tedioso, Vagrant usa una imagen de base, que puede clonar rápidamente.
A estas imágenes que se utilizan como base es a lo que se denominan boxes.

Vamos a añadir un box con el comando: $ vagrant box add precise64 http://files.vagrantup.com/precise64.box

Veremos como en pocos minutos se descarga el box de Internet. Esta descarga se hace una sola vez, ya que
que estas imágenes se comparten entre todos los proyectos. Es decir cada proyecto hace referencia a un box por
su nombre, en nuestro caso precise64 (NOTA: precise es el nombre de la
distribución de Ubuntu
que estamos usando como box), pero los proyectos en ningún caso modifican esta imagen de base,
por lo que se puede compartir sin problema.

En esta página https://github.com/mitchellh/vagrant/wiki/Available-Vagrant-Boxes
podemos encontrar una lista de boxes oficiales que provee el propio Vagrant, así como una referencia a una lista de
boxes que provee la comunidad (la recomendación sería usarlos sólo si tienes suficiente confianza en el proveedor que lo
proporciona, o sino mejor hacerte tu propio box).

4.3. Usando el box

Por ahora sólo hemos descargado el box en nuestro ordenador, pero ahora tenemos que decirle a nuestro proyecto que se
base en él para crear la máquina virtual. Para ello editamos el fichero Vagrantfile, y buscamos la línea

    config.vm.box = "base"

y la cambiamos por:

    config.vm.box = "precise64"

indicando así que queremos usar el como base el box de nombre precise64.

4.4. Levantando y entrando en nuestra máquina virtual

Para arrancar la máquina virtual, basta con ejecutar el comando: $ vagrant up

4.5. ¿Algún problema con las Guest Addittions?

En mi caso se puede ver como aparece un mensaje de alerta en amarillo, indicando que la versión del
Guest Addittions de la máquina virtual que estamos generando (4.2.0) no coincide con la versión
de VirutalBox que tengo instalada en mi sistema (4.3). Esta alerta es relativamente normal ya que tanto los boxes como el
propio VirtualBox, se van actualizando. Para arreglar este problema y evitar posibles complicaciones futuras con el
Guest Addittions (es un software que corre en la máquina virtual y que permite mejorar la interoperatividad con la
máquina real, por ejemplo para uso de USB, compartición de directorios, …) vamos ejecutar el siguiente comando:
$ vagrant plugin install vagrant-vbguest

Con esto hemos instalado un plugin de Vagrant que se encarga de,
cada vez que arrancamos nuestra máquina virtual, comprobar la versión de los Guest Addittions de VirtualBox, y si no es correcta,
instalar la que corresponde
. Para ver cómo funciona vamos a parar nuestra máquina virtual y la vamos a volver a arrancar:

    $ vagrant halt
    $ vagrant up

Vemos como esta vez se pone a instalar varias cosas, … le dejamos trabajar hasta que termine 😉

Si ahora volvemos a hacer una parada y de nuevo levantamos la máquina virtual, deberíamos ver un arranque limpio:

    $ vagrant halt
    $ vagrant up

 

4.6. Entrando por SSH en nuestra máquina virtual

Ya tenemos la máquina virtual creada y arrancada, pero ahora habrá que entrar en ella para hacer cosas, porque sino
todo esto no valdría de nada. Vagrant ha pensado en todo y basta con ejecutar el comando:
$ vagrant ssh

Ya estamos dentro y podemos hacer lo que queramos. Cabe destacar que el directorio /vagrant
de nuestra máquina virtual es un directorio compartido con el directorio de nuestro proyecto en la máquina física.
De hecho si ahora mismo hacemos un $ ls /vagrant, veremos el fichero Vagrantfile.
Así que cuidado con borrar este directorio, porque esto tendrá repercusiones en nuestra máquina física y la podemos llegar
a liar parda!

5. ¿Cómo instalo software de forma que lo vean mis compañeros?

Hasta ahora prácticamente lo que hemos hecho es ejecutar tres comandos, y eso está bien porque hace que conseguir
nuevas máquinas virtuales sea muy sencillo. Pero ¿Para qué queremos máquinas virtuales vacías? Si cada vez que alguien del
equipo quiere instalar dentro un Apache Web Server, o un PostgreSQL, … lo tiene que hacer a mano, no habremos ganado mucho.
Pero tranquilos porque de nuevo Vagrant viene al rescate.

Lo primero que vamos a hacer es crear en el directorio base del proyecto (al lado del fichero Vagrantfile)
el script bootstrap.sh (el nombre da igual, si no os gusta este podéis ponerle otro), con el
siguiente contenido:

    #!/usr/bin/env bash

    apt-get update
    apt-get install -y apache2
    rm -rf /var/www
    ln -fs /vagrant /var/www

Se trata de un script de Unix donde estamos diciendo al sistema de paquetes que instale un Apache Web Server, y que el
directorio que tiene que servir como contenido web es nuestro direcotorio compartido /vagrant.

Ahora editamos el fichero Vagrantfile, añadimos al final (antes del end):

    config.vm.provision :shell, :path => "bootstrap.sh"

Con esto estamos indicando que en el arranque de la máquina virtual queremos que se ejecute este script. Para que este
cambio tenga efecto ejecutamos el comando: $ vagrant up, o si la máquina virtual ya está arrancada podemos
ejecutar el comando $ vagrant reload --provisioning

Vemos como al hacer el reload se pone a instalar los paquetes necesarios. Igual que antes,
le dejamos trabajar por nosotros 😉

Cuando termine, para comprobar que todo ha ido bien podemos ejecutar:

    $ vagrant ssh
    ...
    vagrant@precise64:~$ wget -qO- 127.0.0.1

y deberíamos ver la salida por defecto del Apache, mostrando el contenido del directorio /vagrant.

Con esto hemos visto una manera sencilla de crear scripts de configuración de la máquina virtual. Ya que estos scrips
estarán en el repositorio, permiten que cualquier compañero que haga el vagrant up obtenga su propia
máquina virtual configurada exactamente igual.

Si queremos complicar más el proceso de instalación y configuración del software de nuestra máquina virtual sería
recomendable apoyarnos en otras herramientas como Puppet
o Chef, que se integran perfectamente con Vagrant (podemos ver algún ejemplo
dentro de nuestro Vagrantfile).

6. Configurando la red de la máquina virtual

Hemos visto en el apartado anterior que, para acceder al Servidor Web Apache que hemos instalado, tenemos que hacerlo
desde dentro de la propia máquina virtual. Esto no parece demasiado cómodo, así que vamos a editar el fichero
Vagrantfile y vamos a buscar las opciones de configuración del estilo:
config.vm.network

Veremos que están todas comentadas (tiene una # delante), pero que tenemos tres opciones:

  • port forwarding – hacer un mapeo de puertos para que el tráfico que llega a un puerto del host
    (máquina física) se redirija a un puerto del guest (máquina virtual).
  • private network – crear otra red privada que sólo es accesible desde el host.
  • bridged network – hacer que el guest se comporte como otra máquina más dentro de la red del host.

Vamos a probar la tercera, para lo que simplemente descomentamos la línea:

    # config.vm.network :public_network

dejando:

    config.vm.network :public_network

Y ahora recargamos a la máquina virtual con el comando: $ vagrant reload

Vemos como nos pregunta qué interfaz de red del host queremos usar para el guest. En mi caso elijo 1)
para que se enganche a la Wi-Fi.

Ahora podemos entrar en máquina virtual con $ vagrant ssh y hacer un $ ifconfig para ver
la IP que tiene el guest.

Ahora desde cualquier máquina de la red deberíamos poder acceder a esa IP. Por ejemplo ejecutando en el host el comando:
$ curl 192.168.1.41, deberíamos obtener la misma salida que cuando antes hicimos el wget.

7. Despedida y cierre

Ya para terminar simplemente vamos a ver las distintas formas de apagar nuestra máquina virtual:

  • vagrant suspend – sería el equivalente a cerrar la tapa de nuestro portatil,
    quedando el ordenador suspendido. La ventaja es que es más rápido y se queda guardado el estado todos los programas
    y memoria en ese justo memento. El inconveniente es que consume más espacio en disco de nuestro host.
  • vagrant halt – es como apagar el ordenador. Es un poco más lento que el
    método anterior, y cuando arrancamos de nuevo la máquina virtual todos los servicios se vuelven a arrancar de cero,
    pero consume menos disco duro de nuestro host.
  • vagrant destroy – borra todo rastro de la máquina virtual de nuestro host,
    ahorrando así espacio en disco, pero al volver arrancar tiene que volver a hacer todo el proceso de configuración,
    y tarda mucho más. No sería recomendable salvo que sea un proyecto con el que ya no vamos a trabajar.

En cualquier caso, el método de arranque siempre es el comando: $ vagrant up.

8. Apendice I – El Vagrantfile

Así queda el Vagrantfile después de los cambios que hemos ido haciendo:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # All Vagrant configuration is done here. The most common configuration
  # options are documented and commented below. For a complete reference,
  # please see the online documentation at vagrantup.com.

  # Every Vagrant virtual environment requires a box to build off of.
  config.vm.box = "precise64"

  # The url from where the 'config.vm.box' box will be fetched if it
  # doesn't already exist on the user's system.
  # config.vm.box_url = "http://domain.com/path/to/above.box"

  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # config.vm.network :forwarded_port, guest: 80, host: 8080

  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network :private_network, ip: "192.168.33.10"

  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  config.vm.network :public_network

  # If true, then any SSH connections made will enable agent forwarding.
  # Default value: false
  # config.ssh.forward_agent = true

  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"

  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  # config.vm.provider :virtualbox do |vb|
  #   # Don't boot with headless mode
  #   vb.gui = true
  #
  #   # Use VBoxManage to customize the VM. For example to change memory:
  #   vb.customize ["modifyvm", :id, "--memory", "1024"]
  # end
  #
  # View the documentation for the provider you're using for more
  # information on available options.

  # Enable provisioning with Puppet stand alone.  Puppet manifests
  # are contained in a directory path relative to this Vagrantfile.
  # You will need to create the manifests directory and a manifest in
  # the file base.pp in the manifests_path directory.
  #
  # An example Puppet manifest to provision the message of the day:
  #
  # # group { "puppet":
  # #   ensure => "present",
  # # }
  # #
  # # File { owner => 0, group => 0, mode => 0644 }
  # #
  # # file { '/etc/motd':
  # #   content => "Welcome to your Vagrant-built virtual machine!
  # #               Managed by Puppet.n"
  # # }
  #
  # config.vm.provision :puppet do |puppet|
  #   puppet.manifests_path = "manifests"
  #   puppet.manifest_file  = "site.pp"
  # end

  # Enable provisioning with chef solo, specifying a cookbooks path, roles
  # path, and data_bags path (all relative to this Vagrantfile), and adding
  # some recipes and/or roles.
  #
  # config.vm.provision :chef_solo do |chef|
  #   chef.cookbooks_path = "../my-recipes/cookbooks"
  #   chef.roles_path = "../my-recipes/roles"
  #   chef.data_bags_path = "../my-recipes/data_bags"
  #   chef.add_recipe "mysql"
  #   chef.add_role "web"
  #
  #   # You may also specify custom JSON attributes:
  #   chef.json = { :mysql_password => "foo" }
  # end

  # Enable provisioning with chef server, specifying the chef server URL,
  # and the path to the validation key (relative to this Vagrantfile).
  #
  # The Opscode Platform uses HTTPS. Substitute your organization for
  # ORGNAME in the URL and validation key.
  #
  # If you have your own Chef Server, use the appropriate URL, which may be
  # HTTP instead of HTTPS depending on your configuration. Also change the
  # validation key to validation.pem.
  #
  # config.vm.provision :chef_client do |chef|
  #   chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
  #   chef.validation_key_path = "ORGNAME-validator.pem"
  # end
  #
  # If you're using the Opscode platform, your validator client is
  # ORGNAME-validator, replacing ORGNAME with your organization name.
  #
  # If you have your own Chef Server, the default validation client name is
  # chef-validator, unless you changed the configuration.
  #
  #   chef.validation_client_name = "ORGNAME-validator"

  config.vm.provision :shell, :path => "bootstrap.sh"
end

9. Conclusiones

El tutorial ha quedado un poco largo, pero creo que merece la pena, ya que nos va a simplicar muchísimo la forma de
crear máquinas virtuales y sobre todo nos aporta la capacidad de compartirlas y replicar su configuarción exacta entre
todos los miembros del equipo.

Os animo a que sigáis investigando sus opciones de configuración, por ejemplo para definir cuánta memoria o recursos
debe tener el guest, y le saquéis así el máximo partido para vuestros proyectos.

10. Sobre el autor

Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y Certified ScrumMaster

Socio fundador de Autentia (Desarrollo de software, Consultoría, Formación)

mailto:alejandropg@autentia.com

Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»

http://www.autentia.com

 

Alejandro Pérez García
Alejandro es socio fundador de Autentia y nuestro experto en Java EE, Linux y optimización de aplicaciones empresariales. Ingeniero en Informática y Certified ScrumMaster. Seguir @alejandropgarci Si te gusta lo que ves, puedes contratarle para darte ayuda con soporte experto, impartir cursos presenciales en tu empresa o para que realicemos tus proyectos como factoría (Madrid). Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.

6 COMENTARIOS

    • Para compartirlo puedes hacerlo usando cualquier repositorio de código, por ejemplo GitHub o Bitbucket. Y bastaría con subir los ficheros (Vagrantfile, bootstrap.sh, y en general cualquier fichero que hayas usado para crear la máquina virtual) al repositorio para que luego se los bajen los compañeros y ejecuten el ‘vagrant up’

  1. Hola Alejandro, muy buena explicación gracias por haberte tomado el tiempo para hacerlo.
    Tengo un proglema, el archivo «bootstrap.sh» no se está ejecutando qué puede ser?

    • Siento no poder ayudarle, para eso habría que ver como está montado todo el entorno, y no dispongo del tiempo para poder atender todas las peticiones de este tipo.

      Le animo a que cuando lo resuelva escriba un tutorial y lo comparta con nosotros para ayudar a otros que tengan el mismo problema.

  2. Hola, muy bueno el tutorial! Quería saber cómo puedo hacer para configurar el DNS via vagrant script, ya que necesito que mi máquina virtual quede asociada a una dirección de dominio. Muchas gracias.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad