1. Code
  2. PHP

Vagrant: qué, por qué y cómo

Este artículo lo ayudará a usar Vagrant para administrar sus instancias de máquinas virtuales y le explicará cómo puede aprovechar Puppet para aprovisionar varios recursos, como PHP y PostgreSQL.
Scroll to top
11 min read

Spanish (Español) translation by Luis Chiabrera (you can also view the original English article)

Este artículo lo ayudará a usar Vagrant para administrar sus instancias de máquinas virtuales y le explicará cómo puede aprovechar Puppet para aprovisionar varios recursos, como PHP y PostgreSQL.


Introducción

Los desarrolladores tienen una gran selección de formas de construir su entorno de desarrollo web.

Los desarrolladores tienen una gran selección de formas de construir su entorno de desarrollo web. Puede usar las opciones "locales", como instalar pilas de servidores "todo en uno" pre-compuestas, como el servidor Zend, XAMPP, MAMP, WAMP, etc., o puede instalar los componentes desde la fuente o a través de sistemas de gestión de paquetes como Homebrew, Apt y Yum.

Esto puede acumularse mientras trabaja en varios proyectos con: PHP 5.3 y PHP 5.4, MySQL, SQLite, MongoDB, Postgres, PEAR, PHPUnit, Rails 3.1, Memcached, Redis, Gearman, NodeJS, etc. Si actualiza o si su computadora muere, tendrá que comenzar todo de nuevo.

Podría tener una configuración "remota", utilizando un servidor en la red con recursos compartidos de Samba o un servidor SSH montado con una herramienta como ExpanDrive. La última opción puede llevar a la latencia en las lecturas / escrituras de archivos, que son extremadamente molestas. Puedes usar SSH + Vim para todo, lo cual es rápido, pero eso solo funciona si quieres usar Vim para todo.


Desarrollo vs. Producción

Si bien puede estar contento con cómo está haciendo las cosas en este momento, cuántos de ustedes han escuchado (o han dicho) "Bueno, funciona en mi computadora". Esto es terriblemente común y ocurre cuando los entornos difieren incluso en el detalle más trivial.

Es extremadamente importante asegurarse de que su entorno de desarrollo sea idéntico al entorno de producción y que coincida con los servidores de prueba y de prueba si también tiene estos.

Eso podría parecer fácil si solo piensa en instalar Apache, PHP y alguna copia de MySQL, pero hay un millón de factores en los que pensar. Si se está desarrollando en OSX y se está implementando en un sistema Ubuntu, entonces notará problemas divertidos con la capitalización de archivos. Esto es común en CodeIgniter, cuando alguien tiene una biblioteca con una primera letra minúscula. Se cargará bien en OSX, pero se romperá cuando se implemente en producción. Es posible que su proceso de desarrollo haya perdido un poco de negocio, todo debido a una diferencia de sistema operativo trivial que nadie pensó hasta que fue demasiado tarde.


Desarrollo = Producción

Forzar a los desarrolladores a usar el mismo sistema operativo va a llevar a problemas.

¿Entonces, cuál es la solución? ¿Forzar a todos sus desarrolladores a desechar sus diferentes herramientas y desarrollarlas exactamente en el mismo modelo de computadora portátil? Si todos los desarrolladores obtienen Macbooks nuevos, es posible que no recibas demasiadas quejas, pero entonces deberías usar OSX Server para todo.

Puedes usar Linux para todo, pero luego tienes que luchar sobre qué distribución usar. Forzar a los desarrolladores a usar el mismo sistema operativo llevará a problemas, reducirá la productividad y promoverá la lucha contra nerd.

La virtualización es la respuesta y no es nada nuevo, pero cuando la gente piensa en la virtualización, a menudo piensa en los problemas de rendimiento y sus fanáticos giran como locos mientras su computadora portátil intenta desesperadamente ejecutar dos sistemas operativos.

Este aún puede ser el caso al intentar ejecutar Windows en una máquina de baja potencia, pero en estos días, una Mac promedio tiene 4 GB de RAM listos para usar, lo que es más que suficiente para impulsar una instalación de servidor Ubuntu que se ejecuta en el modo de línea de comandos y todas sus herramientas de desarrollo habituales (IDE, navegador, herramientas de depuración, etc.). Hay algunas opciones para la virtualización, pero prefiero VirtualBox de Oracle (que es gratis). Este software hace todo el trabajo pesado para la virtualización, luego una herramienta llamada Vagrant administra las instancias.


Paso 1 - Instalando VirtualBox

Primero descarga VirtualBox e instálalo. En los sistemas * nix (Mac OSX, Linux, etc.), deberá modificar su .bash_profile (o .zsh_profile) para ampliar su variable $ PATH:

1
PATH=$PATH:/Applications/VirtualBox.app/Contents/MacOS/
2
export PATH

Esto permitirá a Vagrant saber dónde está instalado VirtualBox y, por supuesto, variará para diferentes sistemas operativos.


Paso 2 - Instalar Vagrant

Puedes descargar una compilación vagrant para tu sistema operativo, o instalarla como una gema si no hay una disponible:

1
$ gem install vagrant

Paso 3 - Crear una instancia

Haz un lugar para que tus configuraciones vagrant vivan:

1
mkdir -p ~/Vagrant/test
2
cd ~/Vagrant/test

Usaremos Ubuntu 12.04 LTS (Precise Pangolin), que ya tiene una configuración de "caja".

1
vagrant box add precise32 http://files.vagrantup.com/precise32.box

Aquí puede ver el argumento "precise32", que es un apodo para la URL. Ahora puede crear una instancia, que descargará este .box.

1
vagrant init precise32
2
vagrant up

Ahora estará funcionando. ¡Fácil! Si desea ingresar a esta instancia, a través de SSH, use este comando:

1
vagrant ssh

Paso 5 - Configuración

Tendrá un archivo, llamado Vagrantfile, que contiene la configuración para esta instancia:

1
# -*- mode: ruby -*-

2
# vi: set ft=ruby :

3
4
Vagrant::Config.run do |config|
5
6
    config.vm.box = "precise32"
7
    config.vm.box_url = "http://files.vagrantup.com/precise32.box"
8
9
    # Assign this VM to a host-only network IP, allowing you to access it

10
    # via the IP. Host-only networks can talk to the host machine as well as

11
    # any other machines on the same network, but cannot be accessed (through this

12
    # network interface) by any external networks.

13
    config.vm.network :hostonly, "192.168.33.10"
14
15
    # Set the default project share to use nfs

16
    config.vm.share_folder("v-web", "/vagrant/www", "./www", :nfs => true)
17
    config.vm.share_folder("v-db", "/vagrant/db", "./db", :nfs => true)
18
19
    # Forward a port from the guest to the host, which allows for outside

20
    # computers to access the VM, whereas host only networking does not.

21
    config.vm.forward_port 80, 8080
22
23
    # Set the Timezone to something useful

24
    config.vm.provision :shell, :inline => "echo \"Europe/London\" | sudo tee /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata"
25
26
    # Update the server

27
    config.vm.provision :shell, :inline => "apt-get update --fix-missing"
28
29
    # Enable Puppet

30
    config.vm.provision :puppet do |puppet|
31
        puppet.facter = { "fqdn" => "local.pyrocms", "hostname" => "www" } 
32
        puppet.manifests_path = "puppet/manifests"
33
        puppet.manifest_file  = "ubuntu-apache2-pgsql-php5.pp"
34
        puppet.module_path  = "puppet/modules"
35
    end
36
37
end

Esto, si no lo has notado, es la sintaxis de Ruby; para que pueda obtener bastante creativo con este archivo, pero esto es lo básico.

Mostrará qué apodo usar y tendrá la URL en caso de que el apodo no esté configurado localmente (bueno para compartir).

Las líneas de share_folder son realmente útiles para asignar una carpeta en la instancia a una carpeta local. Usando nfs => true, la instancia podrá escribir y cambiar los permisos de los archivos, lo cual es útil si, por ejemplo, está intentando instalar un CMS allí.

El reenvío de puertos le permite acceder a su instancia en http: // localhost: 8080 y, por supuesto, cambiarlo a un puerto diferente si eso entra en conflicto.

Este archivo de configuración también establecerá la zona horaria en Europa / Londres, luego ejecutará apt-get update, lo que obligará a su sistema a estar actualizado cada vez que se inicie. Si omite este elemento de configuración, es posible que varios paquetes se nieguen a instalar ya que las referencias ahora están desactualizadas.

Cuando cambia la configuración, puede volver a cargar la instancia para usarla:

1
vagrant reload

Ahora que nuestros servidores están funcionando y listos para funcionar, necesitamos instalar algún software. No solo vamos a apt-get install un montón de paquetes a través de la línea de comandos, vamos a "aprovisionar" nuestros servidores.


Paso 4 - Aprovisionamiento

El aprovisionamiento de servidores no es algo en lo que muchos desarrolladores deban pensar.

El aprovisionamiento de servidores no es algo en lo que muchos desarrolladores deban pensar, ya que normalmente se deja a los administradores de sistemas. La idea es hacer un registro de qué software y configuración se ha realizado en un servidor para que pueda crear nuevos entornos de desarrollo, nuevos servidores de prueba que replican la producción, o hacer que otro servidor de producción equilibre la carga entre los dos.

Aprovisionamiento de la vieja escuela

La forma en que los administradores de sistemas manejan esto varía, pero se han utilizado todo tipo de soluciones en el pasado, desde mantener un wiki de comandos ejecutados (que pueden volverse grandes y obsoletos rápidamente) y el enfoque asombroso de tener un "multi-terminal", donde escribe los comandos en una ventana y replica los mismos comandos en otros 7 servidores al mismo tiempo. Todos estos métodos son terribles.

Una solución sería crear su propio archivo .box o crear copias de seguridad .iso para que los nuevos servidores se basen en eso, pero el mantenimiento de esas imágenes genera mucho trabajo adicional, y no importa lo duro que intente, esas máquinas de desarrollo se desincroniza a medida que pasa el tiempo.

Aprovisionamiento moderno

Hay dos sistemas populares en este momento, llamados Puppet y Chef.

Hay dos sistemas populares en este momento, llamados Puppet y Chef. Ambos han existido durante años, pero se han vuelto más populares con el aumento del método de desarrollo DevOps. Las ideas para ambos son similares y debe investigar ambos sistemas, pero este tutorial se centrará exclusivamente en Puppet.

Esencialmente, en lugar de ejecutar un montón de comandos y esperar que todo funcione bien, crea un manifiesto para Puppet explicando todo lo que necesita para asegurarse de que se haya hecho. Cuando ejecuta un comando en el terminal, básicamente le está diciendo a la computadora:

"Instalar Apache"

Con Puppet, diríamos:

"Asegúrate de que Apache está instalado"

O, en lugar de:

"Cree una nueva carpeta, llamada / var / www y configure los permisos para www-data: www-data"

Con Puppet, diríamos:

"Asegúrese de que / var / www exista y tenga permisos que coincidan con www-data: www-data"

La diferencia aquí es que estos manifiestos pueden ejecutarse varias veces (en un trabajo cron por hora o por día) para mantener las cosas actualizadas, y no habrá resultados inesperados de algo que se intenta instalar dos veces.

También le ayudará a probar que todo se está ejecutando como se espera, ya que el fallar de cualquiera de estas reglas arrojará errores que son más fáciles de rastrear que el obtener una gran cantidad de resultados del comando bash. Puppet lanzará grandes errores de color rojo que le informarán que PHP no se instaló, o que no se pudo configurar un módulo específico.

Manifiestos y módulos

Los manifiestos son un poco confusos al principio, pero, después de un tiempo, comienzan a tener sentido.

Para repasar un ejemplo básico:

1
file {'testfile':
2
  path    => '/tmp/testfile',
3
  ensure  => present,
4
  mode    => 0640,
5
  content => "I'm a test file.",
6
}

No hay necesidad de explicar lo que está pasando aquí, ¿verdad?

Más adelante, se puede hacer referencia a este archivo en su manifiesto como "archivo de prueba", lo que significa que se puede enumerar como una dependencia para otras acciones.

Para más ejemplos, nos referiremos a los manifiestos de PyroCMS Puppet en GitHub.

1
include apache
2
3
$docroot = '/vagrant/www/pyrocms/'
4
$db_location = "/vagrant/db/pyrocms.sqlite"
5
6
# Apache setup

7
class {'apache::php': }
8
9
apache::vhost { 'local.pyrocms':
10
    priority => '20',
11
    port => '80',
12
    docroot => $docroot,
13
    configure_firewall => false,
14
}
15
16
a2mod { 'rewrite': ensure => present; }

Esto incluye el módulo "apache", configura algunas variables, ejecuta el manifiesto adicional "apache :: php" en el módulo de apache, configura un host virtual y luego se asegura de que "mod_rewrite" esté habilitado.

Todas estas clases se definen en el módulo de Apache que incluimos.

Continuando, también queremos instalar PHP:

1
include php
2
3
php::module { ['xdebug', 'pgsql', 'curl', 'gd'] : 
4
    notify => [ Service['httpd'], ],
5
}
6
php::conf { [ 'pdo', 'pdo_pgsql']:
7
    require => Package['php5-pgsql'],
8
    notify  => Service['httpd'],
9
}

Esta parte del manifiesto instalará las extensiones de PHP que necesitamos, luego la opción de notify le permitirá a Apache saber que ha instalado una nueva configuración, lo que significa que se reiniciará.

1
include postgresql
2
3
class {'postgresql::server': }
4
5
postgresql::db { 'pyrocms':
6
    owner     => 'pyrocms',
7
    password => 'password',
8
}

Esto configurará un servidor de Postgres, creará una base de datos, llamada "pyrocms" y se asegurará de que exista un usuario llamado "pyrocms" con la contraseña proporcionada.

¡Casi terminado! El último paso es asegurarse de que tiene archivos y carpetas de escritura correctamente configurados:

1
file { $docroot:
2
    ensure  => 'directory',
3
}
4
5
file { "${docroot}system/cms/config/config.php":
6
    ensure  => "present",
7
    mode    => "0666",
8
    require => File[$docroot],
9
}
10
11
$writeable_dirs = ["${docroot}system/cms/cache/", "${docroot}system/cms/config/", "${docroot}addons/", "${docroot}assets/cache/", "${docroot}uploads/"]
12
13
file { $writeable_dirs:
14
    ensure => "directory",
15
    mode   => '0777',
16
    require => File[$docroot],
17
}

Esto asegurará que la raíz del documento de Apache esté allí, que el archivo de configuración esté establecido en 0666 y que algunas carpetas de escritura estén configuradas en 777.

¡Ahí lo tenemos!

Para ejecutar todo esto, simplemente reinicie su instancia errante, o ejecute:

1
vagrant provision

Si todo ha funcionado correctamente, debería ver un montón de texto azul que indica que todo se está instalando, pero si algo sale mal, verá rojo. Google esos errores y vuelva a intentarlo.

Los módulos que se utilizan aquí son: Apache, Postgres, PHP y se puede ver todo en acción clonando el repositorio de PyroCMS Vagrant:

1
git clone --recursive git://github.com/pyrocms/devops-vagrant.git ~/vagrant/pyrocms
2
cd ~/vagrant/pyrocms
3
vagrant up

Dirija su navegador a http: // localhost: 8089 / y debería ver el instalador. Cosas fáciles, ¿eh?

Nota: Esto se instalará con MySQL, ya que el soporte Postgres de PyroCMS y SQLite aún está en desarrollo, a la espera de que se completen algunas de las funciones de CodeIgniter PDO. Si está interesado, puede experimentar cambiando el Vagrantfile para usar el manifiesto ubuntu-apache2-pgsql-php5.pp, destruya la instancia y luego vuelva a iniciarla. El submódulo pyrocms también tendrá que verificarse para feature / pdo


Resumen

En este artículo, utilizamos Vagrant, VirtualBox y Puppet no solo para configurar una instancia de servidor para que trabajemos, sino que creamos una suite de prueba para nuestro servidor para garantizar que todo se ejecute, instale y configure correctamente.

También hemos creado una lista de verificación para los requisitos y, en el futuro, podremos crear cualquier número de servidores idénticos en minutos, ¡no en horas!