LEMP con Vagrant y Ansible
Usando Vagrant y Ansible para crear un servidor LEMP
LEMP es una variante del conocido sistema LAMP (Linux, Apache, MariaDB y PHP) que usa Nginx como servidor web en lugar de Apache.
Lo he usado muchas veces para probar alguna aplicación web. Por lo general, lo hago en un entorno limpio, para que no interfiera con configuraciones previas.
Para esto, normalmente usaríamos algún tipo de máquina virtual que hemos instalado y configurado de cero. Si es un entorno común, puede que ya tengamos un snapshot que podemos restaurar tras realizar las pruebas. O quizás podríamos usar alguna de las múltiples imágenes remotas que existen en Internet.
Sin embargo, una opción mucho más simple es usar Vagrant para administrar estas imágenes remotas y una herramienta de gestión de configuración para administrar su configuración.
Vagrant es una herramienta para la creación y configuración de entornos de desarrollo virtualizados.
Vagrant puede usar diferentes proveedores para arrancar estas imágenes remotas, y también diferentes herramientas para la orquestación del software. Nosotros usaremos VirtualBox y Ansible respectivamente para estas tareas.
Ansible es una plataforma de software libre para configurar y administrar computadoras.
En nuestra máquina anfitrión, solamente necesitamos tener instalados Vagrant y VirtualBox, puesto que Ansible correrá en la máquina huésped. Por lo tanto, tenemos que descargar e instalar el software apropiado para nuestro sistema operativo:
Configuración de Vagrant
La configuración de Vagrant se guarda en un único archivo llamado Vagrantfile
.
Primero, le indicamos a Vagrant que deberá usar VirtualBox como proveedor por defecto:
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'
Luego, empezamos la configuración en sí seleccionando la imagen remota que usaremos como base. En este ejemplo, usamos la imagen oficial de Ubuntu Xenial 32-bit:
config.vm.box = 'ubuntu/xenial32'
Para configurar el hardware de la máquina virtual (512 MB de RAM y un único procesador limitado al 50%), añadimos lo siguiente:
config.vm.provider :virtualbox do |vbox|
vbox.memory = 512
vbox.cpus = 1
vbox.customize ['modifyvm', :id, '--cpuexecutioncap', '50']
end
Ahora configuramos el nombre de máquina y la dirección IP del sistema operativo huésped:
config.vm.define 'lemp' do |node|
node.vm.hostname = 'lemp'
node.vm.network :private_network, ip: '172.28.128.10'
node.vm.post_up_message = 'Web: http://172.28.128.10'
end
También compartiremos el subdirectorio local vagrant
con la máquina huésped de
forma que se monte en /vagrant
:
config.vm.synced_folder 'vagrant', '/vagrant'
Por último, configuramos Ansible para que se ejecute localmente en la máquina
huésped usando la configuración de /vagrant/cfg
. En este directorio, buscará
el archivo de inventario hosts.ini
y el archivo playbook site.yml
. Le
diremos también que ejecute las tareas usando sudo.
config.vm.provision :ansible_local do |ansible|
ansible.provisioning_path = '/vagrant/cfg'
ansible.inventory_path = 'hosts.ini'
ansible.playbook = 'site.yml'
ansible.sudo = true
end
Al final, el archivo debería quedar así:
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'
Vagrant.configure('2') do |config|
config.vm.box = 'ubuntu/xenial32'
config.vm.provider :virtualbox do |vbox|
vbox.memory = 512
vbox.cpus = 1
vbox.customize ['modifyvm', :id, '--cpuexecutioncap', '50']
end
config.vm.define 'lemp' do |node|
node.vm.hostname = 'lemp'
node.vm.network :private_network, ip: '172.28.128.10'
node.vm.post_up_message = 'Web: http://172.28.128.10'
end
config.vm.synced_folder 'vagrant', '/vagrant'
config.vm.provision :ansible_local do |ansible|
ansible.provisioning_path = '/vagrant/cfg'
ansible.inventory_path = 'hosts.ini'
ansible.playbook = 'site.yml'
ansible.sudo = true
end
end
Configuración de Ansible
Puesto que estamos compartiendo el subdirectorio vagrant
con la máquina
huésped, necesitamos poner los archivos de configuración de Ansible en
vagrant/cfg
tal y como hemos especificado en el archivo Vagrantfile
.
El archivo de inventario de Ansible contiene las máquinas que configurará. En este caso, correrá localmente en una única máquina por lo que la añadimos:
lemp ansible_connection=local
Así mismo, los archivos playbook de Ansible guardan los pasos que se tomarán en las máquinas. Podríamos poner todo en este archivo, pero las Buenas Prácticas de Ansible recomiendan usar roles:
---
- name: Configura servidor LEMP
hosts: lemp
roles:
- mariadb
- php
- nginx
Aquí especificamos que esta tarea se aplicará a la máquina de nombre lemp y que ejecutará los roles mariadb, php y nginx.
Rol MariaDB
Este rol instalará y configurará MariaDB. Su configuración se encuentra en el
subdirectorio vagrant/cfg/roles/mariadb
:
vagrant/cfg/roles/mariadb
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
└── vars
└── main.yml
Las tareas a ejecutar se guardan en tasks/main.yml
:
---
- name: Instala servidor
package: name={{ item }} state=present
with_items:
- mariadb-server
- python-mysqldb
notify:
- arranca mysql
- name: Cambia contraseña de root
mysql_user:
name: root
host: localhost
password: '{{ mysql_root_password }}'
state: present
- name: Cambia bind-address
replace:
dest: /etc/mysql/mariadb.conf.d/50-server.cnf
regexp: '^bind-address'
replace: 'bind-address = {{ mysql_bind_address }}'
notify:
- reinicia mysql
- name: Crea base de datos de prueba
mysql_db: name={{ mysql_db_name }} state=present
- name: Crea usuario de prueba
mysql_user:
name: '{{ mysql_db_user }}'
host: '%'
password: '{{ mysql_db_password }}'
priv: '{{ mysql_db_name }}.*:ALL'
state: present
Estos son los pasos que se toman:
- Primero, usando el módulo package, instalamos el software necesario.
- Luego, usando el módulo mysql_user, cambiamos la contraseña de root de MariaDB por aquella en la variable mysql_root_password.
- Para poder acceder al servidor desde nuestra máquina anfitrión, usamos el módulo replace para modificar el archivo de configuración de MariaDB y cambiar el parámetro bind-address por el de la variable mysql_bind_address.
- A continuación, creamos la base de datos de prueba, usando el 49
- Y, finalmente, creamos un usuario de prueba, de nuevo, usando el módulo mysql_user.
Todas las variables que usemos en este rol se pueden configurar en
vars/main.yml
:
---
mysql_root_password: 'root'
mysql_bind_address: '0.0.0.0'
mysql_db_name: 'test'
mysql_db_user: 'test'
mysql_db_password: 'test'
También, definimos unos handlers que son unas tareas básicas que se ejecutan cuando otra tarea cambia algo y notifica al handler. Las usamos para asegurarnos de que el servidor está activado y para reiniciarlo cuando hacemos algún cambio en la configuración:
---
- name: arranca mysql
service: name=mysql enabled=yes state=started
- name: reinicia mysql
service: name=mysql state=restarted
Rol PHP
Este rol instalará PHP. Su configuración se encuentra en el subdirectorio
vagrant/cfg/roles/php
:
vagrant/cfg/roles/php
├── handlers
│ └── main.yml
└── tasks
└── main.yml
Usando el módulo package, instala PHP-FPM (FastCGI Process Manager) y el módulo para comunicarse con MySQL:
---
- name: Instala PHP
package: name={{ item }} state=present
with_items:
- php-fpm
- php-mysql
notify:
- arranca php-fpm
También definimos el handler que se asegurará de que el servicio esté activado:
---
- name: arranca php-fpm
service: name=php7.0-fpm enabled=yes state=started
Rol Nginx
Este rol instalará y configurará Nginx. Su configuración se encuentra en el
subdirectorio vagrant/cfg/roles/nginx
:
vagrant/cfg/roles/nginx
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── default
└── vars
└── main.yml
Las tareas en tasks/main.yml
son:
---
- name: Instala servidor
package: name={{ item }} state=present
with_items:
- nginx
notify:
- arranca nginx
- name: Cambia configuración por defecto
template:
src: default
dest: /etc/nginx/sites-available/default
notify:
- recarga nginx
De nuevo, usando el módulo package, instalará el software necesario.
Luego, usando el módulo template, cambia la configuración del sitio por
defecto copiando nuestra plantilla desde templates/default
:
# Default server configuration
server {
listen {{ http_port }} default_server;
listen [::]:{{ http_port }} default_server;
root {{ base_dir }};
index index.html index.htm index.php;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
Las variables que se usan en la plantilla se configuran en vars/main.yml
:
---
http_port: 80
base_dir: '/vagrant/www'
De esta forma, cualquier archivo que guardemos en el subdirectorio vagrant/www
de nuestra máquina anfitrión estará disponible en el servidor web de la máquina
huésped. Podemos trabajar localmente con nuestra herramienta de desarrollo
favorita y ver los cambios inmediatamente en el servidor web.
Por último, definimos los handlers que se asegurarán de que el servidor esté activado y de que recargamos la configuración cuando hagamos cambios:
---
- name: arranca nginx
service: name=nginx enabled=yes state=started
- name: recarga nginx
service: name=nginx state=reloaded
Usando Vagrant
Una vez que todo esté configurado, simplemente tendremos que arrancar la máquina
huésped con el comando vagrant up lemp
.
La primera vez que lancemos el comando, se descargará la imagen remota, por lo que podría tardar un rato. En subsecuentes arranques solamente se comprobará si tenemos la versión más reciente de la imagen.
Una vez finalice el arranque, podremos conectarnos al servidor web en
http://172.28.128.10. Como ejemplo, supongamos que hemos puesto lo siguiente
en el archivo vagrant/www/index.php
:
<?php phpinfo(); ?>
Cuando nos conectemos al servidor con nuestro navegador web, veremos algo como esto:
Podemos también conectarnos al servidor de bases de datos con el comando:
mysql --host=172.28.128.10 --user=test --password test
Y, tras introducir nuestra contraseña, podremos ejecutar órdenes de SQL:
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 32
Server version: 10.0.29-MariaDB-0ubuntu0.16.04.1 Ubuntu 16.04
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [test]>
Para controlar la máquina huésped, aquí están los comandos de Vagrant más importantes:
Acción | Comando |
---|---|
arranca la máquina huésped | vagrant up lemp |
reinicia la máquina huésped | vagrant reload lemp |
apaga la máquina huésped | vagrant halt lemp |
arranca y reconfigura la máquina huésped | vagrant up lemp --provision |
conecta con la máquina huésped usando SSH | vagrant ssh lemp |
destruye la máquina huésped | vagrant destroy lemp |
Conclusión
Usar Vagrant con Ansible (o cualquier otro [gestor de configuración][vagrant provision]) nos proporciona un sistema portable y reproducible, contenido en unos pocos archivos de texto:
.
├── [ 66K] vagrant
│ ├── [ 58K] cfg
│ │ ├── [ 37] hosts.ini
│ │ ├── [ 54K] roles
│ │ │ ├── [ 17K] mariadb
│ │ │ │ ├── [4.1K] handlers
│ │ │ │ │ └── [ 133] main.yml
│ │ │ │ ├── [4.7K] tasks
│ │ │ │ │ └── [ 759] main.yml
│ │ │ │ └── [4.2K] vars
│ │ │ │ └── [ 162] main.yml
│ │ │ ├── [ 21K] nginx
│ │ │ │ ├── [4.1K] handlers
│ │ │ │ │ └── [ 131] main.yml
│ │ │ │ ├── [4.3K] tasks
│ │ │ │ │ └── [ 263] main.yml
│ │ │ │ ├── [4.4K] templates
│ │ │ │ │ └── [ 397] default
│ │ │ │ └── [4.1K] vars
│ │ │ │ └── [ 70] main.yml
│ │ │ └── [ 12K] php
│ │ │ ├── [4.1K] handlers
│ │ │ │ └── [ 79] main.yml
│ │ │ └── [4.1K] tasks
│ │ │ └── [ 139] main.yml
│ │ └── [ 93] site.yml
│ └── [4.1K] www
│ └── [ 144] index.php
└── [ 748] Vagrantfile
Se acabó el pelearse con instaladores, restaurar snapshots o reconfigurar cosas. Puedes arrancar un sistema limpio, meter la pata, destruirlo y arrancarlo como nuevo otra vez en unos pocos minutos. Puedes incluso usar un sistema de control de versiones para guardar los archivos y compartirlos con otra gente.
Además, existen imágenes oficiales de varios sistemas operativos en la página
de Vagrant. No sólo de Ubuntu, si no también de
Debian, Fedora, CentOS y
FreeBSD. Puedes incluso especificar tu propia imagen con el
parámetro config.vm.box_url
.
Así mismo, la gran cantidad de módulos de Ansible nos permite configurar el sistema operativo huésped automáticamente de casi cualquier forma imaginable, aunque puede que necesitemos adaptar muchas de las tareas para otras distros de Linux u otros sistemas operativos.
En conclusión, este método simplifica enormemente el proceso de creación y gestión de entornos de prueba.
Leer más
- Creating a Base Box - VirtualBox Provider - Vagrant by HashiCorp
- Box Format - VMware Provider - Vagrant by HashiCorp
- Creating a Base Box - Hyper-V Provider - Vagrant by HashiCorp
- GitHub - vagrant-libvirt/vagrant-libvirt: Vagrant provider for libvirt
- GitHub - fgrehm/vagrant-lxc: LXC provider for Vagrant