Despliegue de Sistemas Heterogéneos con Vagrant¶
Justificación¶
Actualmente el auge del desarrollo de aplicaciones en sistemas virtualizados requiere del despliegue, conectividad y flexibilidad de sistemas heterogéneos en escenarios de desarrollo de trabajo y producción.
Una de las herramientas más utilizadas por los SRE (Site Reliability Engineer) es Vagrant, para conseguir el objetivo principal de crear sistemas de software altamente confiables y escalables. Vagrant es una herramienta para la creación y configuración de entornos de desarrollo virtualizados que cubre las necesidades comentadas.
Motivado por dicha relevancia a continuación se introduce la herramienta de Devops Vagrant.
Introducción Vagrant¶
¿Qué es Vagrant?¶
- Es una herramienta para construir entornos de desarrollo simples, con un flujo de trabajo fácil de usar y un enfoque en la automatización replicable. Permite crear y destruir los escenarios en repetidas ocasiones sin gran esfuerzo.
- Esencialmente, es una capa de software instalada entre una herramienta de virtualización (como VirtualBox, Docker, Hyper-V) y una máquina virtual.
- Por lo tanto, es un software para automatizar las operaciones que se realizan con los hipervisores:
Por ejemplo
- Crear, configurar, parar, suspender y destruir máquinas virtuales.
- Gestionar redes.
- Compartir espacios de disco entre guest y host.
- Manejar distintos tipos de hipervisores.
- Es un software de código libre disponible bajo una licencia
MIT
. El código fuente está disponible en Github. - Fue desarrollado originalmente por Mitchell Hashimoto en 2010. A partir de Vagrant se creo Hashicorp en 2012.
Aplicaciones de Hashicorp
- Packer (imágenes de vagrant)
- Consul (descubrimiento de servicios)
- Terraform (aprovisionamiento)
- Vault (seguridad)
- Nomad (despliegue contenedores)
Características¶
- Puede integrarse con herramientas de gestión de la configuración, automatizando la provisión de software de la máquina virtual.
- Forma parte del conjunto de aplicaciones utilizadas en "infraestructura como código", mediante un fichero de texto que puede formar parte del código fuente del proyecto, por lo que puede subirse al control de versiones y ser compartido por todos los desarrolladores, dicho fichero es denominado Vagrant file.
- Soluciona problemas de incidencias de desarrollo entre diferentes sistemas.
Incidencias
El problema de configurar escenarios a mano conlleva un trabajo tedioso y provoca errores, dando lugar al reproche de En mi máquina funciona.
Solución
- Vagrant: para Distribuir de forma separada imágenes “limpias” de OS y la configuración completa en un fichero de texto que es el que se distribuye por el grupo de trabajo.
- Reduce el tiempo de configuración del entorno de desarrollo, aumenta la paridad de desarrollo/producción y hace que la excusa de "funciona en mi máquina" sea una reliquia del pasado.
- A menudo se utiliza en el desarrollo de software para garantizar que todos los miembros del equipo estén construyendo para la misma configuración.
- No solo comparte entornos, sino que también comparte código. Esto permite que el código de un desarrollador trabaje en el sistema de otro, haciendo posible el desarrollo colaborativo y cooperativo.
Vagrant vs. Docker¶
Vagrant
es una herramienta centrada en proporcionar un flujo de trabajo de entorno de desarrollo coherente en múltiples sistemas operativos, trabajando sobre los hipervisores.- Docker es una gestión de contenedores que puede ejecutar software de forma consistente siempre y cuando exista un sistema de contenedorización.
- Los contenedores son generalmente más ligeros que las máquinas virtuales, por lo que iniciar y detener los contenedores es extremadamente rápido. Docker utiliza la funcionalidad de contenedorización nativa en macOS, Linux y Windows.
- Para entornos de microservicios pesados, Docker puede ser atractivo porque puede iniciar fácilmente una sola máquina virtual Docker e iniciar muchos contenedores por encima de eso muy rápidamente. Este es un buen caso de uso para Docker.
Vagrant
también puede hacer esto con el proveedor de Docker. Un beneficio principal para Vagrant es un flujo de trabajo consistente, pero hay muchos casos en los que un flujo de trabajo de Docker puro tiene sentido.- Tanto Vagrant como Docker tienen una vasta biblioteca de "imágenes" o "boxes" para elegir.
Instalación Vagrant¶
Para la instalación el mejor consejo es acudir a la documentación oficial, en el siguiente enlace se pueden obtener los comandos de instalación de Vagrant para los diferentes tipos de sistemas operativos:
Nota
En este caso se realiza la ejecución de los comandos para la instalación por repositorios en las distribuciones de Ubuntu/debian.
- Descarga de las GPG: GNU Privacy Guard es una herramienta de cifrado y firmas digitales.
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
- Introducción de la firma en los repositorios: mediante el comando echo se añade la firma digital al
sources.list
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
- Actualización de repositorios e instalación de Vagrant.
sudo apt update && sudo apt install vagrant
- Confirmación de la instalación
vagrant -v
Configuración del proyecto Vagrant¶
Para tener una máquina virtual totalmente utilizable con Ubuntu 18.04 LTS de 64 bits, solo se necesitan los siguientes dos comandos:
- Empieza por crear un directorio para almacenar tu archivo Vagrant:
sudo mkdir vagrant-test
cd vagrant-test
- Se inicializa una maquina virtual, Descargando una distribución del VAGRANT HUB.
vagrant init hashicorp/bionic64
Nota
Este comando descarga una Vagrantbox
y genera un vagrantfile
en el directorio del proyecto.
Vagrantbox
- La unidad básica en una configuración de Vagrant se llama
box
oVagrantbox
. Esta es una imagen completa e independiente de un entorno de sistema operativo. - Una
Vagrantbox
es un clon de una imagen básica del sistema operativo. El uso de un clon acelera el proceso de lanzamiento y aprovisionamiento.
vagrantfile
Un Vagrantfile
es un archivo de Ruby que le indica a Vagrant que cree, dependiendo de cómo se ejecute, nuevas máquinas o Vagrantbox
.
- Antes de poder continuar con el siguiente paso, asegúrate de que Vagrant haya creado un
Vagrantfile
.
ls -al
- Se arranca la máquina virtual.
vagrant up
- Se puede acceder por ssh a la máquina virtual.
vagrant ssh
Configuración básica¶
Por defecto, Vagrant almacena las VMs ‘boxed’ en la ruta ~/.vagrant.d
. Estas ‘boxes’ suelen ser ficheros de gran tamaño, y podemos considerarlas como una ‘imagen modelo’ de las MVs que tendremos en ejecución. Se pueden compartir entre diferentes usuarios, con el objetivo de optimizar el espacio utilizado en disco.
La ubicación del directorio principal de Vagrant puede modificarse a través de la variable de entorno VAGRANT_HOME. Por ejemplo, a través del siguiente comando:
export VAGRANT_HOME=/ruta/al/directorio
Ejemplo
Como puedes mover tus archivos Vagrant
y máquinas virtuales VirtualBox
de tu carpeta de inicio a un disco duro externo:
- Copia el directorio
.vagrant.d
de tu carpeta personal (~/.vagrant.d
) al disco externo (Y renombra la carpeta avagrant_home
:
cp -R ~/.vagrant.d /Volumes/[VOLUME_NAME]/vagrant_home"
- Elimina el directorio
.vagrant.d
fde la carpeta personal:
rm -rf ~/vagrant.d
- Edita tu archivo
.bash_profile
, y añade la siguiente línea:
export VAGRANT_HOME="/Volumes/[VOLUME_NAME]/vagrant_home"
- Para editarlo directamente:
echo 'export VAGRANT_HOME="/Volumes/[VOLUME_NAME]/vagrant_home' >> ~/.bash_profile
advertencia
Para hacerlo permanente y no solo valga para una sesión, es necesario introducirlo en el .bash_profile
- Abre VirtualBox, vaya a Preferencias y establezca la carpeta de máquina predeterminada en una ubicación en su disco duro externo (por ejemplo una nueva carpeta llamada "VMs VirtualBox").
Crear una MV ya configurada¶
Hay Boxes
subidas al Vagrant Cloud que no solo aportan un Sistema Operativo "limpio" sino que a parte tienen configurada alguna aplicación o servicio, para añadirlas correctamente su Vagrantfile viene especificado en el git
que aparece en la descripción de la box
.
Ejemplo
Para realizar un uso adecuado de está caja se clona el repositorio que contiene el Vagrantfile configurado con las características de esta imagen:
git clone https://github.com/rlerdorf/php7dev.git
Una vez clonado aparece la carpeta descargada donde podemos apreciar los archivos de Vagrantfile
y de configuración .yml
, como se observa a continuación.
Nota
Una vez realizado el Vagrant up se puede acceder al servicio de PHP
Principales comandos Vagrant¶
En la DOCUMENTACIÓN OFICIAL se encuentran todos los comandos de Vagrant, en los siguiente apartados se realiza un resumen de los más utilizados.
Advertencia
¡Asegúrate de estar en el mismo directorio que Vagrantfile cuando ejecutes estos comandos!
Crear una MV¶
vagrant init
-- Inicializa Vagrant con unVagrantfile
y . /.vagrant directorio, sin imagen base especificada. Antes de poder hacer vagrant up, tendrás que especificar una imagen base en elVagrantfile
.vagrant init <boxpath>
-- Inicializa Vagrant con una caja específica. Para encontrar una caja, accede al public Vagrant box catalog. Cuando encuentres uno que te guste, reemplaza su nombre conboxpath
. Por ejemplo,vagrant init ubuntu/trusty64
.
Empezar una MV¶
vagrant up
-- comienza el entorno de vagrant (también disposiciones solo sobre el PRIMER vagrant up).vagrant resume
-- reanudar una máquina suspendida (vagrant up también se puede utilizar).vagrant provision
-- uerza el reaprovisionamiento de la máquina de vagrant.vagrant reload
-- reinicia la máquina vagrant, carga la nueva configuración deVagrantfile
vagrant reload --provision
-- reinicie la máquina virtual y fuerce el aprovisionamiento
Accediendo a una máquina Vagrant¶
vagrant ssh
-- se conecta a la máquina a través deSSH
vagrant ssh <boxname>
-- Si le das un nombre a tu box en tu Vagrantfile, puedes acceder viassh
sustituyendo el boxname por el nombre. Funciona desde cualquier directorio.
Parando una MV¶
vagrant halt
-- detiene la máquina de vagrant.vagrant suspend
-- suspende una máquina virtual (recuerda el estado).
limpiando una MV¶
vagrant destroy
-- detiene y elimina todos los rastros de la máquina de Vagrant.vagrant destroy -f
-- lo mismo que lo anterior, sin confirmación.
Boxes¶
vagrant box list
-- ver una lista de todas las cajas instaladas en tu ordenador.vagrant box add <name> <url>
-- descarga una imagen de caja en tu ordenador.vagrant box outdated
-- comprueba si hay actualizaciones en la vagrant box.vagrant box remove <name>
-- elimina una caja de la máquinavagrant package
-- empaqueta un virtualbox env en ejecución en una caja reutilizable
Guarda el Progreso¶
-vagrant snapshot save [options] [vm-name] <name>
-- vm-name is often default
. Permite guardar una instanténea
Tips¶
vagrant -v
-- consigue la versión vagrantvagrant status
-- estado de las salidas de vagrant machinevagrant global-status
-- stado de las salidas de todas las vagrant machinesvagrant global-status --prune
-- igual que el anterior, pero las entradas no son válidasvagrant provision --debug
-- usa la bandera de depuración para aumentar la verbosidad de la salidavagrant push
-- ¡sí, vagrant se puede configurar para implementar código! deploy code!vagrant up --provision | tee provision.log
-- Ejecutavagrant up
, fuerza el aprovisionamiento y registra toda la salida en un archivo
Vagrantfile¶
Consejo
Para visualizar por consola la lista de máquina virtuales en virtual box se puede utilizar el comando: VBoxManage list vms
- La configuración de un escenario concreto se realiza de forma bastante simple mediante modificaciones en el
Vagrantfile
, que está escrito en formato Ruby, como ya se ha comentado.
Nota
Realmente la configuración que se aplica es la aplicación en serie de varios Vagranfiles
, tal como se explica en en la documentación oficial en Load Order and Merging, aunque lo más habitual es que se cargue el Vagrantfile
que incluye el box y el que exista en el directorio de trabajo, siendo este último el que se modifica en la mayoría de los casos.
Modificaciones de la máquina virtual¶
- Las modificaciones se configuran en el espacio de nombres
config.vm
, prefijo que antecede a los parámetros en este caso,por ejemplo
para modificar el hostname de la máquina se utiliza:
config.vm.hostname = "UbuntuServer22_Vagrant"
Nota
El resto de parámetros que se pueden modificar los encontramos en la documentación de Vagrant: Machine Settings, dejando en este caso para secciones posteriores algunos de los aspectos que necesitan más desarrollo como la configuración de la red o la configuración integrada de la máquina virtual mediante shell scripts o mediante aplicaciones como Ansible
o Puppet
.
- Los parámetros relativos a las características de hardware de la máquina virtual dependen del proveedor en Vagrant y en el caso de VirtualBox se definen mediante una sub-sección desde donde se realizan las modificaciones apropiadas en un Vagrantfile. Por ejemplo para cambiar el nombre de la máquina virtual, la memoria RAM asignada y el número de núcleos virtuales.
config.vm.provider "virtualbox" do |vb|
vb.name = "nombre"
vb.memory = "512"
vb.cpus = 2
end
- Como la forma habitual de gestionar máquinas virtuales en
Vagrant
es mediante la línea de comandos y accediendo a ellas a través de ssh, no tiene mucho sentido que se arranque una interfaz gráfica, pero en algunas ocasiones es conveniente. Para activar la interfaz gráfica de usuario al levantar la máquina, se debe añadir la siguiente línea alVagrantfile
.
config.vm.provider "virtualbox" do |vb|
vb.gui = true
end
Directorio compartido¶
Por defecto cuando se ejecuta una MV con Vagrant se crea una carpeta compartida entre el Anfitrión y la MV. en este caso:
Generar archivos
Si se genera un archivo en esta carpeta se generaría también en el anfitrión.
Advertencia
Existen casos en los cuales la carpeta compartida no se sincroniza correctamente, para solucionarlo existen las siguientes alternativas:
- Mediante
rsync
, la cual es una aplicación libre para sistemas de tipo Unix y Microsoft Windows que ofrece transmisión eficiente de datos incrementales. Para realizar la configuración Con Vagrant haríamos:
config.vm.synced_folder ".", "/vagrant", type: "rsync"
- Y lanzar en el
host
el comando:
vagrant rsync-auto
Nota
La sincronización se lleva a cabo desde host a guest
- Otras alternativas son
NFS
oSMB
de forma bidireccional:
config.vm.synced_folder ".", "/vagrant", type: "nfs"
Advertencia
Se requiere un servidor NFS (o SMB) en el host => se requiere red privada
Aprovisionamiento ligero (thin provisioning)¶
-
Para los casos de necesidad de clonar muchas máquinas se aconseja utilizar el Aprovisionamiento ligero (thin provisioning), el cual es una técnica muy utilizada en diferentes sistemas de virtualización.
-
Dicha técnica consiste en crear un disco de imagen de máquina virtual que incluya sólo las modificaciones respecto a una imagen base, consiguiendo un ahorro significativo de espacio en disco a costa de una pequeña penalización en rendimiento.
-
A continuación se muestra la configuración de un Vagrantfile para que realiza el
aprovisionamiento ligero
.
- Revisamos cuanto ocupa la MV de ejemplo de hashicorp.
- Para hacer la creación de la máquina ligera clonada se realiza en una carpeta a parte un nuevo proyecto y añadimos las siguientes líneas al
Vagrantfile
.
config.vm.provider "virtualbox" do |vb|
vb.name = "ligera"
vb.linked_clone = true
end
Redirección de puertos¶
-
Si se necesita habilitar puertos para determinados servicios a instalar en la MV, se puede realizar una redirección de puertos.
-
Por ejemplo si además de utilizar la redirección de puertos de
ssh
que utiliza Vagrant se debería añadir la siguiente línea:
config.vm.network "forwarded_port", guest: 80, host: 8080
Comprobación
Para comprobarlo se instalaría un NGINX en la máquina y accederíamos al servicio por el puerto configurado.
Añadir disco adicional¶
Una de las configuraciones más utilizadas en los escenarios de entornos virtualizados es la adición de discos adicionales para obtener diferentes tipos de configuraciones como puede ser la redundancia de datos mediante técnicas de RAID
.
En este caso Vagrant no dispone de comandos ni configuraciones para realizarlo, por lo que se debe añadir la programación necesaria en el VagrantFile
que actue directamente al Virtualbox.
Ejemplo
Creación de una máquina virtual que tenga un disco adicional de 500 GiB. Para ello se puede utilizar el siguiente código:
config.vm.provider "virtualbox" do |vb|
file_to_disk = 'tmp/disk.vdi'
unless File.exist?(file_to_disk)
vb.customize ['createhd',
'--filename', file_to_disk,
'--size', 500 * 1024]
end
vb.customize ['storageattach', :id,
'--storagectl', 'SATAController',
'--port', 1,
'--device', 0,
'--type', 'hdd',
'--medium', file_to_disk]
end
Advertencia
- Este tipo de configuraciones en las que se pone de forma explícita las características de la máquina virtual no son ni mucho menos generales, en el caso anterior se está poniendo de forma concreta el puerto
SATA
al que conectar el disco y el nombre del controladorSATA
, características que pueden variar de una máquina virtual a otra. - Por lo tanto Es recomendable inicialmente comprobar el nombre del controlador de
SATA
que en el caso de VirtualBox se puede hacer con el siguiente comando de VBoxManage
VBoxManage showvminfo NOMBRE_MV
- Después de levantar el Vagrant o realizar un
reload
, se comprueba la configuración:
lsblk
ls -hl tmp/
Gestión de instantáneas¶
- Para generar y recuperar instantáneas en
Vagrant
se utiliza el comandovagrant snapshot
seguido de la acción a realizar o bien guardar o recuperar.
Ejemplo
Partiendo de un escenario de vagrant con una MV que tenga instalada un NGINX y un reenvío de puertos. Se genera una snapshot
para realizar algún cambio y restaurar la captura guardada.
- Comandos:
# se genera la captura.
vagrant snapshot save nginx-limpio
# se comprueba que se ha creado.
vagrant snapshot list
# Después de realizar algún cambio se restaura.
vagrant snapshot restore nginx-limpio
Consejo
Existe un método más sencillo de realizar instantáneas, es mediante el comando vagrant snapshot push
que va almacenando instantáneas cada vez que se invoca y se recupera la más reciente con vagrant snapshot pop
.
Redes¶
-
Por defecto Vagrant realiza los pasos necesarios en la máquina virtual para que sea accesible a través de una red virtual desde el equipo anfitrión y tenga acceso a Internet, es decir le configura una red.
-
Esta configuración lógicamente va a variar en función del proveedor, pero en el caso de VirtualBox se trata de una red de tipo NAT con el direccionamiento inicial 10.0.2.0/24. Las opciones de redes son:
Red privada¶
En algunas ocasiones aparece la necesidad de utilizar un direccionamiento IP específico en una máquina virtual o añadir una red virtual adicional, por lo que en muchos casos es adecuado añadir una red privada, tal como se explica en Private Networks.
Ejemplo
config.vm.network "private_network", ip: "192.168.55.10"
Red pública¶
Para vagrant una red pública es una red en modo puente (bridged network) conectada al exterior, típicamente sería poner en la misma red la máquina anfitriona y la máquina virtual. Más detalles en Public Networks
Ejemplo
config.vm.network "public_network", bridge: "eth0"
Multi-máquinas¶
- Se puede extender la configuración de un escenario virtual con vagrant a aquellos casos en los que haya más de una máquina virtual y esto se hace con estructuras como la siguiente en el Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.define "Server" do |m1|
m1.vm.box = "Ecodev/ubuntu-server-2204"
end
config.vm.define "Client" do |m2|
m2.vm.box = "hashicorp/bionic64"
end
end
- Al existir más de una máquina virtual, muchas de las instrucciones que hemos visto hasta ahora deben incluir el nombre de la máquina como parámetro, por ejemplo si hiciéramos:
vagrant ssh Server
Ejemplo
Crea un escenario para una aplicación web en la que ubicamos en una máquina el servidor Ubuntu 22 conectado a una red pública exterior y una máquina con un cliente en una máquina no accesible desde el exterior. Para que ambas máquinas estén interconectadas entre sí, crea la red privada 10.0.100.0/24
a la que estarán conectadas ambas máquinas.
Vagrant.configure("2") do |config|
config.vm.define "ServerMulti1" do |nodo1|
nodo1.vm.box = "Ecodev/ubuntu-server-2204"
nodo1.vm.hostname = "UbuntuServerMulti"
nodo1.vm.network "public_network", bridge: "en0"
nodo1.vm.network "private_network", ip: "10.0.100.101"
end
config.vm.define "ClientMulti1" do |nodo2|
nodo2.vm.box = "hashicorp/bionic64"
nodo2.vm.hostname = "ClienteMulti"
nodo2.vm.network "private_network", ip: "10.0.100.102"
end
end
Actividades de clase (AP)¶
AC64. Introducción a entornos de desarrollo mediante Vagrant¶
Realiza los siguientes tareas introductorias a Vagrant.
- Monta el escenario necesario para trabajar con
Vagrant
.
- Instala
Vagrant
. - Realiza un primer proyecto.
- Externaliza la carpeta de boxes a un disco externo (si es posible).
- Crea y destruye varias MVs.
-
Genera un Vagrantfile multimáquina con un servidor web y un cliente que pueda acceder al servidor de forma privada. El servidor debe tener salida a Internet. Comprueba que tiene acceso al
index.html
del servidor web y modifícalo. -
Crea un entorno de desarrollo portable con Vagrant con algunas de las boxes más utilizadas del catálogo (por ejemplo ubuntu/xenial64 o centos7):
- Prueba los distintos tipos de
synced folders
. Comprueba si, para tu plataforma, en cada uno de ellos funciona adecuadamente los enlaces simbólicos y la sincronización en uno y otro sentido: - Shared folder de virtualbox ▹ Rsync
- NFS
- Prueba a compartir por los métodos anteriores carpetas de tu equipo en otras ubicaciones de la máquina guest.
NOTA
usa vagrant reload cada vez que cambies la configuración.
- Crea una máquina con un NGINX y un reenvío de puertos, Genera una
Snapshot
haz algún cambio en elindex.html
. Regenera la captura y comprueba que el index.html está como de inicio.