Proyecto para la asignatura de Cloud Computing en el Máster en Ingeniería Informática UGR.
Con este proyecto se quiere monitorizar los downtimes de las líneas de una fábrica. Consta de 2 entidades:
- PlantMonitoring: Se encarga de leer los datos de las líneas y almacenarlos en una base de datos. Los datos que se almacenan son el instante en el que se produce un downtime y la duración de este.
- Notifier: Su función es notificar a una lista de contactos que se ha producido un downtime y volver a avisar cuando se restablezca la línea.
Como arquitectura se ha elegido una arquitectura basada en microservicios, donde cada microservicio corresponde con las entidades descritas.
Más información sobre la arquitectura y el funcionamiento del todo el sistema.
El proyecto se desarrolla usando Python más:
- Flask para la interfaz REST
- Celery para gestionar los eventos
- MySQL y MongoDB como bases de datos
- Consul para la configuración distribuida
Más información sobre lenguajes y tecnologías usadas.
Las versiones de Python compatibles con el proyecto son: Linux: -Mínima: 3.6 -Máxima: 3.8 y su versión de desarrollo
Para poder usar la herramienta de construcción es necesario:
-
Instalarla con:
pip install invoke
-
Instalar las dependencias
pip install -r requirements.txt
En cualquiera de los dos casos quedará disponible
buildtool: tasks.py
La herramienta de construcción usada es Invoke
.
Para poder usar la herramienta de construcción es necesario:
-
Instalarla con:
$ pip install invoke
-
Instalar las dependencias
$ pip install -r requirements.txt
En cualquiera de los dos casos quedará disponible.
Se han configurado cuatro tareas. Estas son:
-
Instalar las dependencias necesarias
$ invoke install
Instala todas la dependencias necesarias para el proyecto. Si previamente se ha ejecutado
pip install -r requirements.txt
no es necesario ejecutar esta tarea.Se pueden consultar las dependencias usadas en el archivo requirements.txt
-
Ejecutar los test unitarios
$ invoke test
Ejecuta todos los test unitarios. Para ello se ha usado el framework
Pytest
. -
Ejecutar los test de cobertura
$ invoke coverage
Ejecuta los test de cobertura y almacena los resultados en un archivo
.coverage
. Para la ejecución de estos test se ha usado un el módulopytest-cov
que proporcionaPytest
. -
Limpiar los archivos generados por los test
$ invoke clean
Incluido el archivo
.coverage
. -
Levantar los microservicios
$ invoke start <ip> <puerto>
Levanta los microservicios usando Gunicorn, un servidor WSGI HTTP para
Python
. Si no se indica la ip y el puerto donde se quiere enlazar el servicio por defecto se establecerá0.0.0.0:5000
y el0.0.0.0:5051
Para comprobar que se ha levantado adecuadamente se puede consultarhttp:\\<ip>:<puerto>\hello
. Esto devolverá unHello, World!
-
Parar los microservicios
$ invoke stop
Mata el proceso donde se ejecutaba el microservicio.
En el momento de la ejecución se pueden listar las tareas disponibles usando invoke --list
.
Para más información sobre los comandos que se ejecutan y su opciones de configuración consulte el fichero tasks.py.
Como herramienta de integración continua se ha usado TravisCI
y Github Actions
. Para más información sobre que se realiza con ambas herramientas puede ir a la documentación correspodiente. También puede consultar los archivos de configuración de TravisCI y el workflow de Github Actions.
Se han creado varios contenedores para los microservicios notifier y monitor.
Contenedor: https://hub.docker.com/r/ibe16/notifier
Contenedor: https://hub.docker.com/r/ibe16/monitor
Para consultar como se ha realizado se puede visitar el siguiente enlace.
La imagen del microservicio está desplegada en Heroku. Para comprobarlo se puede usar la url: https://cc-notifier.herokuapp.com/hello.
Para más información acerca de cómo se ha realizado el despliegue se puede consultar el siguiente enlace.
Se usarán PostgreSQL para gestionar y consultar mejor los datos de tipo DATE y MongoDB para almacenar a donde hay qué mandar las notificaciones, para que sea más cómodo gestionar las listas.
Para la implementación de ambas bases de datos se ha usado un ORM para mapear los objetos de la base de datos a objetos de Pyhton y marcar los esquemas que deben seguir estos. Para los dos microservicos se ha usado en mismo patrón: una clase para definir cómo son los objetos y que realiza la conexión a la base de datos y otra clase que define las operaciones con la base de datos.
Para el Microservicio Notifier estas clases son:
Para el Microservicio Monitor estas clases son:
Para saber más acerca de la implementación de las bases de datos consulte el siguiente fichero.
Prestaciones: stress_test.yml
Para la evaluación de las prestaciones de ambos microservicos se ha utlizado Taurus
. El objetivo que se quiere conseguir es alcanzar las 1000 peteciones/s con 10 usuarios concurrentes.
Para saber más acerca de las prestaciones consulte el siguiente enlace.
Para la creación de la máquina virtual vamos a usar Vagrant más Virtualbox. Lo primero que tenemos que hacer es descargar e instalar estás dos herramientas. Después para crear el Vagrantfile
ejecutamos el comando vagrant init
en la raíz del proyecto.
Se puede consultar el fichero Vagrantfile que contiene comentarios explicativos acerca de la creación de la máquina virtual.
La máquina virtual se usará para desplegar los contenedores de docker que ya se tenían anteriormente.
Una vez que tengamos la máquina virtual configurada, el siguiente paso es hacer el provisionamiento. Para ello usaremos Ansible.
Para poder utilizar Ansible deberemos descargarlo primero. En mi caso al utilizar un gestor de versiones para Python se ha instalado con pip
.
Lo siguiente que hay que hacer es crear los ficheros de configuración de Ansible:
- Un fichero de configuración general ansible.cfg.
- Un fichero, inventario, con el nombre de los hosts que se van a utilizar ansible_hosts.
- Los playbooks que vayamos a usar.
Si usamos Vagrant para automatizar el provisionamiento debemos indicar donde se encuentra el fichero que queremos utilizar como inventario. Si no, Vagrant creará uno por defecto.
Después de esto en nuestro Vagrantfile
tenemos que indicar:
- Qué hosts de ansible vamos a usar.
- Dónde se encuentran los playbooks que vamos a utilizar.
- Dónde se encuentra el inventario si no usamos el por defecto.
Para más información se puede consultar el Vagrantfile y los ficheros de configuración de Ansible.
Para el despliegue de la MV en Azure se han seguido los siguientes pasos:
- Crear una cuenta de estudiante en Azure
- Instalar Azure-CLI. Para ello se ha seguido la siguiente documentación.
- Registramos la aplicación en Azure. Esto nos proporcionará una serie de claves para poder crear la MV desde Vagrant.
$ az ad sp create-for-rbac
- Conseguir el ID de nuestra subscripción de azure
$ az account list --query "[?isDefault].id" -o tsv
- Creamos las siguientes variables de entorno para guardar las claves que nos ha proporcionado los pasos anteriores:
- AZURE_TENANT_ID =
tenant
- AZURE_CLIENT_ID =
appId
- AZURE_CLIENT_SECRET =
password
- AZURE_SUBSCRIPTION_ID =
SubscriptionId
- AZURE_TENANT_ID =
- Modificamos el Vagrantfile para que use como proveedor Azure. Se puede consultar el fichero para más información. También tendremos que añadir la inofrmación necensario al inventario.
- Instalamos el plugin de Vagrant
vagrant-azure
.$ vagrant plugin install vagrant-azure
- Instalamos una
box
que Vagrant pueda usar. Realmente estabox
no hace nada.$ vagrant box add azure https://github.com/azure/vagrant-azure/raw/v2.0/dummy.box --provider azure
Para los pasos del 3 al 9 se ha seguido la siguiente documentación.
Por último debemos ejecutar vagrant up --privider=azure
para la creación de la máquina.
Cuando creamos la máquina virtual con vagrant se ejecuta el playbook provisioning.yml automáticamente. Este lo que hace es actualizar, instalar las dependencias necesarios para poder usar Docker y Docker-Compose, descargar las imágenes necesarias y contruir los contenedores. Una vez que la máquina está cosntruida también podemos ejecutar este playbook haciendo:
$ vagrant provision
Para levantar los servicios se ha realizado el playbook start_services.yml. Para ejecutarlo:
$ ansible-playbook -i ./provision/ansible_hosts ./provision/start_services.yml
Para pararlos existe el playbook stop_services.yml. Para ejecutarlo:
$ ansible-playbook -i ./provision/ansible_hosts ./provision/stop_services.yml
Bien, una vez tenemos la confuguración necesaria para crear y aprovisionar las MV vamos a elegir un SO para ellas. Para ello tenemos que tener en cuenta que el rol de Ansible que estamos utilizando tiene compatibilidad solo con las siguientes plataformas:
- Ubuntu 16.04 LTS (Xenial)
- Ubuntu 18.04 LTS (Bionic)
- Debian 9 (Stretch)
- Debian 10 (Buster)
Las box que están disponibles para Vagrant para hacer las pruebas locales son:
- ubuntu/xenial64 (Ubuntu 16.04 LTS)
- ubuntu/bionic64 (Ubuntu 18.04 LTS)
- debian/stretch64 (Debian 9)
- debian/buster64 (Debian 10)
Los resultados obtenidos son los siguientes:
Como se puede ver el sistema operativo que ofrece mejores prestaciones es Debian 10, así que este será el que usemos para construir las máquinas virtuales.
Para la máquina vistual que se ha desplegado en local se ha elegido la siguiente configuración:
- 2 CPUs
- 2 GB de RAM
Como los recursos de los que dispone son limitados, no podemos esperar un nivel de prestaciones similar al que obteníamos corriendo los microservicios en local.
Los resultados que se obtienen para cada microservicio son:
Se intentó hacer test de prestaciones para la máquina virtual que está desplegada en Azure. Sin embargo, está dispone de una configuración por defecto que previene los ataques DDoS, por lo que las prestaciones que se obtienen al realizar los test no son muy fiables. Aquí se encuentra el enlace donde se explica esta configuración de seguridad: https://docs.microsoft.com/es-es/azure/virtual-network/ddos-protection-overview
La máquina dispones de la siguiente configuración:
- 2 CPUs
- 8 GB RAM
Son unos recursos hardware similares a los que se tienen en la cuando se pasan los test en local (mi ordenader dispone de 4CPUs y 8GB de RAM), sin embargo las prestaciones que se obtienen son las siguientes:
Al no poderse desactivar la opción de seguridad y no haber un método que nos permita añadir IPs seguras o similar, no podemos asegurar cual es el nivel de prestaciones de los servicios.