Descripción del problema
Somos muchas las personas amantes de la música que no disponemos de una plataforma que nos proporcione información y permita preescuchar albumes. Si a esto añadimos que las webs existentes están ancladas en los mismos estilos, surge la necesidad de realizar una web que abarque estilos más minoritarios de música. Por ello surge MusicSpace.
Mi intención con esta aplicación web es satisfacer la necesidad de todas aquellas personas que deseen poder acceder a una aplicación web con una interfaz atractiva, novedosa, multiplataforma y eficiente.
Arquitectura de desarrollo
MusicSpace sigue una arquitectura microkernel, ya que todos los servicios se ejecutan desde la misma máquina. Por tanto, es el núcleo central el que se comunica con la base de datos y así, comunica la aplicación web con la base de datos, gestionando las peticiones e inserciones de datos a la misma.
Así, separa la mínima funcionalidad principal de la funcionalidad extendida y las partes del cliente, implementando el propio microkernel los servicios principales y manejando la comunicación y los recursos.
Tecnología utilizada
La herramienta principal de desarrollo es Django, un framework de código abierto, escrito en Python y que se apoya en el modelo de diseño MVC (Modelo-Vista-Controlador). Este modelo MVC define una forma de desarrollar software en la que el código para definir y acceder a los datos (el modelo) está separado del pedido lógico de asignación de ruta (el controlador), que a su vez está separado de la interfaz del usuario (la vista).
Para la persistencia de datos se ha decidido utilizar la base de datos NoSQL y de código abierto MongoDB, la cual se integra perfectamente en Django. Al no necesitar relaciones para la base de datos se utilizará MongoDB, y hará que el tamaño de la base de datos sea muy ligero.
Provisionamiento
Para desplegar MusicSpace es necesario tener instalados varios paquetes, en este caso vamos a necesitar tener instalado Python, MongoDB, Django y diversos paquetes de los que dependen los mismos. Para realizar estos pasos de forma automatizada, vamos a utilizar dos herramientas para dicha provisión, de hecho son las dos más utilizadas actualmente, Ansible y Chef.
En primer lugar, se va a comentar como se ha realizado la conexión con la máquina destino, la cual va a ser la que va a disponer de las herramientas citadas anteriormente y la que podrá ejecutar la web. Dispongo de una máquina con el sistema operativo Ubuntu 14.04 en el servicio de Amazon AWS, uno de los IaaS más valorados del mercado, con la cual conecto a ella en remoto de la siguiente forma:
ssh -i ./instace-ami.pem ubuntu@ec2-35-162-52-222.us-west-2.compute.amazonaws.com
Donde instance-ami.pem contiene la clave necesaria para conectar con la máquina mediante ssh. Por tanto, de esta forma vemos que la conexión es correcta y posteriormente podremos comprobar que los paquetes se han instalado correctamente.
En primer lugar, vamos a comentar como se ha realizado el provisionamiento para la máquina que va a ejecutar el proyecto con Ansible, el cuál está programado en Python y utiliza ficheros de tipo YAML.
Para la instalación de Ansible en nuestra máquina local vamos a ejecutar el siguiente comando
sudo pip install ansible
Una vez instalado, nos vamos a dirigir a /etc/ansible, donde vamos a añadir nuestros ficheros de configuración para poder ejecutar el playbook y vamos a especificar los host que vamos a provisionar
La siguiente imagen corresponde al fichero host, donde tenemos que especificar el nombre asignado a la máquina que vamos a provisionar ,su ip y el fichero con la clave privada. En este caso la máquina especificada es la máquina que, como comente anteriormente, tengo en AWS
A continuación, vemos el archivo de configuración de Ansible, con los parametros activos que necesitamos especificar.
Por último, disponemos del fichero de instalación de los paquetes necesarios para provisionar la máquina que va a ejecutar el proyecto. Por tanto, una vez ejecutado el fichero de Ansible, llamado playbook, dispondremos de todas las herramientas necesarias para dicha ejecución.
Una vez definidos estos ficheros, vamos a ejecutar el playbook de Ansible mediante del siguiente comando.
ansible-playbook /etc/ansible/playbooks/playbook.yml
En la siguiente captura de pantalla comprobamos que la ejecución de las tareas definidas en el playbook se han realizado correctamente.
A continuación, vamos a realizar el aprovisionamiento con Chef
Para realizar el provisionamiento con una herramienta distinta he decidido utilizar Chef. Está escrita en Ruby y es otra de las más utilizadas para provisionamiento y sencillo de usar. En este caso, he utilizado chef-solo, por tanto, es necesario tener instalado dicho paquete en le cliente y así poder ejecutar el fichero.
Necesitamos varios ficheros para provisionar una máquina.
En primer lugar el fichero default.rb, donde hacemos la descripción de los paquetes o receta que vamos a necesitar en el provisionamiento.
El siguiente fichero es node.json, donde tenemos que indicar el nombre del recipiente que vamos a utilizar.
Por último tenemos el fichero solo.rb en el cual vamos a indicar los directorios que componen el provisionamiento. Podemos indicarlo de la siguiente forma.
En la siguiente imagen, comprobamos que las instalaciones se han realizado correctamente.
Corrección provisión compañero
He realizado la corrección de los playbooks del compañero Jesús García Manday. He ejecutado sus dos playbooks para Ansible llamados updateSys.yml y mySql.yml sobre la máquina utilizada anteriormente corriendo en el servicio AWS de Amazon.
En las siguientes capturas vemos que el funcionamiento ha sido correcto
Como vemos en las imágenes, la instalación se ha realizado correctamente.
Orquestación con Vagrant
Para la orquestación de máquinas virtuales se ha utilizado la herramienta de software libre Vagrant. Está desarrollada en Ruby y se complementa perfectamente con sofware de virtualización como VirtualBox y con software de aprovisionamiento como Ansible.
Para instalar la herramienta Vagrant, primero tenemos que instalar VirtualBox, ya que es el software de virtualización seleccionado para utilizar Vagrant, por tanto utilizamos el comando siguiente:
sudo apt-get install virtualbox dkms
Una vez instalado VirtualBox, procedemos a la instalación de Vagrant mediante el siguieten comando:
sudo apt-get -y install vagrant
Vamos ahora a crear el directorio en el que vamos a realizar la configuración Vagrant mediante el Vagrantfile. Para ello, creamos un directorio en nuestro sistema e iniciamos el servicio Vagrant, por tanto, ejecutamos los siguientes comandos.
mkdir vagrant
vagrant init
Ahora tenemos ya creado nuestro directorio y nuestro fichero Vagrantfile, asi que, a continuación, vamos a comentar el contenido del fichero para nuestra orquetación.
En este punto, tenemos que decidir qué sistema operativo vamos a utilizar y cuántas máquinas vamos a necesitar en nuestra instalación. Otro punto importante a comentar es la provisión que vamos a realizar sobre dichas máquinas virtuales. Para ello, he utilizado Ansible e incrustamos las intrucciones necesarias para la ejecución de dicho provisionamiento. Como comentamos anteriormente, Ansible y Vagrant se complementan perfectamente, y es por ello que la propia provisión la insertaremos en el fichero de configuración Vagrant, como vemos a continuación.
#Fichero Vagrant para crear y provisionar tres máquinas virtuales Ubuntu 14.04. Vagrant.configure(2) do |config| #Definimos la configuración de las tres máquinas virtuales. config.vm.define "vm1" do |vm1| vm1.vm.box = "ubuntu/trusty64" end config.vm.define "vm2" do |vm2| vm2.vm.box = "ubuntu/trusty64" end config.vm.define "vm3" do |vm3| vm3.vm.box = "ubuntu/trusty64" end #Especificamos cual será el fichero de ansible que va a provisionar las tres máquinas virtuales. config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" end end
Si observamos el fichero Vagrantfile, vamos a crear 3 máquinas virtuales, con el sistema operativo Ubuntu 14.04. Como podemos observar, las últimas instrucciones pertenecen al provisionamiento Ansible. Una vez creadas las máquinas virtuales, se realiza la provisión de las mismas mediante la ejecución de playbook.yml, el cual se va a situar en el mismo directorio que nuestro Vagrantfile. Vamos a obervar ahora el conteniedo de nuestro playbook, utilizado en el apartado anterior de la documentación.
--- - hosts: all become: yes remote_user: ubuntu tasks: - name: Actualizar sistema apt: update_cache=yes - name: Instalar git apt: pkg=git state=latest - name: Instalar MongoDB apt: name=mongodb state=latest - name: Instalar Pip apt: name=python-setuptools state=present apt: name=python-dev state=present apt: name=python-pip state=present - name: Instalar PyMongo pip: name=pymongo - name: Instalar Python pip: name=python - name: Instalar virtualenv pip: name=virtualenv - name: Instalar Django pip: name=django
En el playbook, especificamos los paquetes o el software que vamos a necesitar en nuestras máquinas virtuales creadas con Vagrant.
Una vez que tenemos esta organización de ficheros y el propio contenido de ellos, procedemos a la ejecución de Vagrant utilizando el siguiente comando.
vagrant up
Cuando finalice, podremos acceder a cada una de nuestras máquinas instaladas. Para ello usamos el siguiente comando, donde nombre_máquina va a corresponder al nombre especificado en el Vagrantfile, en este caso podría ser vm1, vm2 o vm3.
vagrant ssh nombre_máquina
En las siguientes imágenes se muestra cómo se realiza correctamente la creación, el levantamiento, provisionamiento de las máquinas virtuales, así como una muestra de que están corriendo en VirtualBox.
En las primeras cuatro imágenes vemos como se instala y crea la primera máquina, se aprovisiona y comienza con la segunda.
Mostramos una lista de los boxes de Vagrant creados en mi equipo.
Y por último vemos como están creadas y corriendo en VirtualBox.
Vagrant nos permite también realizar sobre ellas otra serie de acciones como son:
Salir de la máquina virtual:
exit
Apagar la máquina virtual:
vagrant halt nombre_máquina
Eliminar la máquina virtual:
vagrant destroy nombre_máquina.
O ver la lista de máquinas virtuales de las que disponemos:
vagrant box list
Aparte de esto, he realizado tambíen la orquestación en cloud utilizando el servicio de Microsoft Azure.
Podemos ver en la siguiente imagen como se realiza la instalación para el plugin de azure para Vagrant y a continuación creamos el bos para nuestra máquina virtual.
Y por último, creamos la maquina virtual a través de nuestro siguiente Vagrantfile, donde previamente tendremos que haber congfigurado nuestra cuenta de Azure mediante la herramienta azure-cli. Vemos a continuación como ha quedado el Vagrantfile y una captura de comprobación de la creación de la máquina virtual.
VAGRANTFILE_API_VERSION = '2' Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = 'azure1' config.vm.box_url = 'https://github.com/msopentech/vagrant-azure/raw/master/dummy.box' config.ssh.username = 'vagrant' config.vm.provider :azure do |azure| #full path to pem file azure.mgmt_certificate = File.expand_path('~/.ssh/azurevagrant.key') azure.mgmt_endpoint = 'https://management.core.windows.net' #to get this run: azure account list azure.subscription_id = '15ae55f3-69f0-4cab-9374-fa39efad56fe' azure.storage_acct_name = '' # optional #to get this run: azure vm image list azure.vm_image = 'b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_2-LTS-amd64-server-20150506-en-us-30GB' azure.vm_user = 'vagrant' # defaults to 'vagrant' if not provided azure.vm_password = 'vagrant123#@!' # min 8 characters. should contain a lower case letter, an uppercase letter, a number and a special character azure.vm_name = 'azurevagrant-django1' # max 15 characters. contains letters, number and hyphens. can start with letters and can end with letters and numbers azure.cloud_service_name = '' # same as vm_name. leave blank to auto-generate ##to get this run: azure vm location list azure.vm_location = 'North Europe' azure.tcp_endpoints = '3389:53389' # opens the Remote Desktop internal port that listens on public port 53389. Without this, you cannot RDP to a Windows VM. azure.winrm_https_port = 5986 azure.ssh_port = '22' azure.winrm_transport = %w(https) end config.vm.provision "ansible" do |ansible| ansible.playbook = "playbook.yml" end end
Como podemos observar, hemos utilizado el mismo playbook que para local.
En conclusión, con Vagrant estamos ante una herramienta muy potente de orquestación de máquinas virtuales, la cual nos permite no solo automatizar el proceso de creación de nuestro entorno, sino provisionar el mismo de una manera sencilla.
Docker
Para la creación de un contenedor preparado con el entorno de desarrollo de ésta aplicación web, tenemos que realizar los pasos que vamos a ver a continuación.
Vamos a realizar la creación del contenedor en una máquina remota que tenemos instalada en AWS. Por ello, en primer lugar, esta máquina tiene que tener instalado Docker, como vemos a continuación.
Una vez que se tiene Docker instalado, procedemos a crear un Dockerfile, el cual va a variar dependiendo de las necesidades. En mi caso, he creado una imagen personalizada a través de una anteriormente creada la cual incluye Django. Por tanto, unicamente me ha sido necesario añadir git, clonar nuestro repositorio e instalar MongoDB.
A continuación vemos como hacer una búsqueda de imágenes previamente creadas y el contenido del Dockerfile.
FROM django MAINTAINER Mario Ortega Aguayo "mortega87@gmail.com" RUN apt-get update #Install Git RUN apt-get -y install git #Download repository RUN git clone https://github.com/mortega87/ProyectoCC-16-17 #Install MongoDB RUN apt-get -y install mongodb
Una vez que tenemos el ficheroDockerfile definido, nos vamos a crear una imagen y la vamos a almacenar en un repositorio DockerHub llamado mortega/musicspace.
A continuación, con la imagen ya creada, la vamos a subir a nuestro perfil de Docker Hub, y comprobamos que se ha creado correctamente en nuestro perfil desde la plataforma web.
Por último, vemos que tenemos disponible nuestra inagen anteriormente creada y vamos a crear el contenedor con el comando run.