Despliegue con Fabric

Fabric es una herramienta para Python similar a Makefiles pero con la capacidad de ejecutar comandos en un servidor remoto. En combinación con un paquete Python correctamente configurado (Grandes aplicaciones como paquetes) y un buen concepto de configuraciones (Manejo de la configuración) es muy fácil desplegar aplicaciones Flask en servidores externos.

Antes de empezar, aquí una lista rápida de cosas que tenemos que asegurar por adelantado:

  • Fabric 1.0 tiene que ser instalado localmente. Este tutorial asume la última versión de Fabric.

  • La aplicación ya tiene que ser un paquete y requiere un archivo setup.py que funcione (Despliegue con Setuptools).

  • En el siguiente ejemplo estamos usando mod_wsgi para los servidores remotos. Por supuesto, puedes usar tu propio servidor favorito, pero para este ejemplo elegimos Apache + mod_wsgi porque es muy fácil de configurar y tiene una forma sencilla de recargar las aplicaciones sin acceso de root.

Creación del primer Fabfile

Un fabfile es lo que controla lo que ejecuta Fabric. Se llama fabfile.py y es ejecutado por el comando fab. Todas las funciones definidas en ese fichero aparecerán como subcomandos fab. Se ejecutan en uno o más hosts. Estos hosts pueden ser definidos tanto en el fabfile como en la línea de comandos. En este caso los añadiremos al fabfile.

Este es un primer ejemplo básico que tiene la capacidad de subir el código fuente actual al servidor e instalarlo en un entorno virtual preexistente:

from fabric.api import *

# the user to use for the remote commands
env.user = 'appuser'
# the servers where the commands are executed
env.hosts = ['server1.example.com', 'server2.example.com']

def pack():
    # build the package
    local('python setup.py sdist --formats=gztar', capture=False)

def deploy():
    # figure out the package name and version
    dist = local('python setup.py --fullname', capture=True).strip()
    filename = f'{dist}.tar.gz'

    # upload the package to the temporary folder on the server
    put(f'dist/{filename}', f'/tmp/{filename}')

    # install the package in the application's virtualenv with pip
    run(f'/var/www/yourapplication/env/bin/pip install /tmp/{filename}')

    # remove the uploaded package
    run(f'rm -r /tmp/{filename}')

    # touch the .wsgi file to trigger a reload in mod_wsgi
    run('touch /var/www/yourapplication.wsgi')

Ejecución de Fabfiles

Ahora, ¿cómo se ejecuta ese fabfile? Utiliza el comando fab. Para desplegar la versión actual del código en el servidor remoto usarías este comando:

$ fab pack deploy

Sin embargo esto requiere que nuestro servidor ya tenga la carpeta /var/www/tuaplicacion creada y /var/www/tuaplicacion/env para ser un entorno virtual. Además no estamos creando el archivo de configuración o .wsgi en el servidor. Entonces, ¿como arrancamos un nuevo servidor en nuestra infraestructura?

Esto depende ahora del número de servidores que queramos configurar. Si sólo tenemos un servidor de aplicaciones (que es lo que tendrán la mayoría de las aplicaciones), crear un comando en el fabfile para esto es excesivo. Pero obviamente se puede hacer. En ese caso probablemente lo llamarías setup o bootstrap y luego pasarías el nombre del servidor explícitamente en la línea de comandos:

$ fab -H newserver.example.com bootstrap

Para configurar un nuevo servidor, se deben seguir los siguientes pasos:

  1. Cree la estructura de directorios en /var/www:

    $ mkdir /var/www/yourapplication
    $ cd /var/www/yourapplication
    $ virtualenv --distribute env
    
  2. Suba un nuevo archivo aplicacion.wsgi al servidor y el archivo de configuración de la aplicación (por ejemplo: aplicacion.cfg)

  3. Crea una nueva configuración de Apache para tuaplicacion y actívala. Asegúrate de activar la vigilancia de los cambios del archivo .wsgi para que podamos recargar automáticamente la aplicación al tocarlo. Ver mod_wsgi.

Así que ahora la pregunta es, ¿de dónde vienen los archivos aplicacion.wsgi y aplicacion.cfg?

El archivo WSGI

El archivo WSGI tiene que importar la aplicación y también establecer una variable de entorno para que la aplicación sepa dónde buscar la configuración. Este es un breve ejemplo que hace exactamente eso:

import os
os.environ['YOURAPPLICATION_CONFIG'] = '/var/www/yourapplication/application.cfg'
from yourapplication import app

La propia aplicación tiene que inicializarse así para buscar la configuración en esa variable de entorno:

app = Flask(__name__)
app.config.from_object('yourapplication.default_config')
app.config.from_envvar('YOURAPPLICATION_CONFIG')

Este enfoque se explica en detalle en la sección Manejo de la configuración de la documentación.

El archivo de configuración

Ahora, como se mencionó anteriormente, la aplicación encontrará el archivo de configuración correcto buscando la variable de entorno tuaplicacion_CONFIG. Así que tenemos que poner la configuración en un lugar donde la aplicación sea capaz de encontrarla. Los ficheros de configuración tienen la antipática cualidad de ser diferentes en todos los ordenadores, por lo que no se suelen versionar.

Un enfoque popular es almacenar los archivos de configuración para diferentes servidores en un repositorio de control de versiones separado y comprobarlos en todos los servidores. Entonces se hace un enlace simbólico al archivo que está activo para el servidor en la ubicación donde se espera (por ejemplo: /var/www/tuaplicacion).

De cualquier forma, en nuestro caso sólo esperamos uno o dos servidores y podemos subirlos antes a mano.

Primer despliegue

Ahora podemos hacer nuestro primer despliegue. Hemos configurado los servidores para que tengan sus entornos virtuales y activado las configuraciones de apache. Ahora podemos empaquetar la aplicación y desplegarla:

$ fab pack deploy

Fabric se conectará ahora a todos los servidores y ejecutará los comandos tal y como están escritos en el fabfile. Primero ejecutará pack para que tengamos nuestro tarball listo y luego ejecutará deploy y subirá el código fuente a todos los servidores y lo instalará allí. Gracias al archivo setup.py automáticamente se incorporarán las librerías necesarias a nuestro entorno virtual.

Próximos pasos

A partir de ahí, hay muchas cosas que se pueden hacer para que la implantación sea realmente divertida:

  • Crear un comando bootstrap que inicialice los nuevos servidores. Podría inicializar un nuevo entorno virtual, configurar apache adecuadamente, etc.

  • Poner los archivos de configuración en un repositorio de control de versiones separado y hacer un enlace simbólico a las configuraciones activas en su lugar.

  • También podría poner el código de su aplicación en un repositorio y comprobar la última versión en el servidor y luego instalar. De esta manera también puedes volver fácilmente a versiones anteriores.

  • enganche en la funcionalidad de pruebas para que pueda desplegar a un servidor externo y ejecutar el conjunto de pruebas.

Trabajar con Fabric es divertido y te darás cuenta de que es bastante mágico escribir fab deploy y ver que tu aplicación se despliega automáticamente en uno o más servidores remotos.