UNIVERSIDAD POLITÉCNICA DE MADRID ESCUELA TÉCNICA SUPERIOR DE INGENIEROS DE TELECOMUNICACIÓN ETSIT ESCUELA TECNICA SUPERIOR DE INGENIEROS DE TELECOMUNICACIÓN GRADO EN INGENIERÍA DE TECNOLOGÍAS Y SERVICIOS DE TELECOMUNICACIÓN TRABAJO FIN DE GRADO DISEÑO Y DESPLIEGUE DE SERVICIOS DE ALTA DISPONIBILIDAD EN LA NUBE USANDO HERRAMIENTAS DE CÓDIGO ABIERTO Antonio Julián Alférez Zamora 2016 Trabajo Fin de Grado Título: Diseño y despliegue de servicios de alta disponibilidad en la nube usando herramientas de código abierto Title: Design and deployment of high availability services in the cloud using open source tools Autor: Antonio Julián Alférez Zamora Tutor: D. Joaquín Luciano Salvachúa Rodríguez Departamento: Departamento de Ingeniería de Sistemas Telemáticos Tribunal Presidente: D. Juan Quemada Vives Vocal: D. Santiago Pavón Gómez Secretario: D. Gabriel Huecas Fernández-Toribio Suplente: D. David Fernández Cambronero Fecha de lectura Calificación i ii Resumen Las empresas punteras en tecnología e innovación cuentan con numerosos recursos de computación para llevar a cabo los diversos servicios que sustentan el proceso de negocio. En general, a estos equipos se les asignan de forma estática las distintas tareas, lo que conlleva un uso ineficiente al no distribuirse acorde con la carga de trabajo, además del trabajo de mantenimiento que conlleva. De entre las responsabilidades de los profesionales de las tecnologías de la información está gestionar eficientemente estos recursos, así como garantizar la disponibilidad de estos servicios, atendiendo a las diferentes demandas de capacidad. La motivación de este trabajo surge de la oportunidad de desplegar las diferentes tareas o servicios de una forma más eficiente, gracias a la evolución en tecnologías como la virtualización, almacenamiento distribuido o redes definidas por software, así como la mejora y el abaratamiento de los enlaces de comunicaciones, que suponen un cambio de enfoque a la hora de diseñar la infraestructura de los sistemas de información. En particular, en este proyecto se va a entrar en detalle en herramientas cuyo objetivo es optimizar los recursos y además dar ciertas garantías de escalabilidad, disponibilidad y tolerancia a fallos. De entre las soluciones que existen en la industria, hemos seleccionado dos de código abierto que alcanzan los objetivos definidos: DC/OS, desarrollada por la empresa Mesosphere y basado en el proyecto Apache Mesos, y Nomad, creada por Hashicorp. En primer lugar se realizará un análisis del funcionamiento de estas tecnologías, al que posteriormente seguirá el despliegue de casos de uso en la nube, y finalmente, las conclusiones a las que se han llegado comparando el rendimiento de ambas. Con ello, se pretende dar una perspectiva de la funcionalidad de estas tecnologías y como encajan en la perspectiva actual dentro de las tecnologías de la información. Palabras clave: Clúster, Gestor de recursos, Planificador, Computación en la nube, Apache Mesos, HashiCorp Nomad, Mesosphere DC/OS iii iv Summary Tech-savvy companies have a large amount of computational resources to handle the services that support the business process. Typically, tasks are allocated in these computers in a static way, which is inefficient due to the fact that they are not distributed according to the workload, besides involving further maintenance work. Among the responsibilities of Information Technology professionals is efficiently managing these resources and providing some guarantees of availability of those services, according to the different capacity demands. The motivation of this project comes from the opportunity of efficiently distributing the different tasks or services of an enterprise, thanks to the evolution of technologies such as virtualization, distributed storage or software defined networks; but also with the improvement and cost reduction of the communication links, a potential turning point in the approach of designing IT infrastructures. This project goes into more detail on tools which pursue resource optimization, availability, scalability and fault tolerance of services. Amongst the existing solutions in the industry, two open source projects have been chosen, both achieving the predefined objectives: DC/OS, developed by the company Mesosphere and based on the Apache Mesos project, and Nomad, developed by HashiCorp. Firstly, the internals of these two technologies will be studied, followed by a deployment of use cases in both of them in the cloud. Lastly, the conclusions reached comparing their performance will be described. By this, it is intended to provide a perspective of the functionality of these tools and how they fit in the nowadays perspective on Information Technology. Keywords: Cluster, Resource Manager, Cluster Scheduler, Cloud Computing, Apache Mesos, HashiCorp Nomad, Mesosphere DC/OS v vi Índice Resumen III Summary V Índice de figuras IX 1. Introducción y objetivos 1.1. Contexto 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3. Estructura del documento . . . . . . . . . . . . . . . . . . . . . . 2 2. Cloud Computing 3 3. Nuevas cargas de trabajo 5 4. Gestión de recursos. Planificadores 8 4.1. Sistemas distribuidos . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1. Clasificación . . . . . . . . . . . . . . . . . . . . . . . . . 5. Herramientas 8 10 13 5.1. DC/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.1.1. Apache Mesos . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.1.2. Ejemplos de uso . . . . . . . . . . . . . . . . . . . . . . . 18 5.2. Nomad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.2.1. Protocolo de consenso. Raft . . . . . . . . . . . . . . . . . 20 vii 5.2.2. Protocolo gossip. SWIM . . . . . . . . . . . . . . . . . . . 23 5.2.3. Planificación . . . . . . . . . . . . . . . . . . . . . . . . . 24 6. Casos de uso y despliegue 27 6.1. Aplicación Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 6.1.1. DC/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 6.1.2. Nomad . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 6.2. Servicio de integración continua . . . . . . . . . . . . . . . . . . . 40 6.2.1. DevOps . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 6.2.2. Integración Continua . . . . . . . . . . . . . . . . . . . . . 40 6.2.3. Jenkins con Nomad . . . . . . . . . . . . . . . . . . . . . 42 6.2.4. Jenkins con DC/OS . . . . . . . . . . . . . . . . . . . . . 42 7. Escalando la infraestructura 43 7.1. Diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 7.2. Implementación . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 8. Resultados y conclusiones 45 8.1. Comparación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 8.2. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 8.3. Objetivos conseguidos . . . . . . . . . . . . . . . . . . . . . . . . 46 8.4. Líneas de investigación . . . . . . . . . . . . . . . . . . . . . . . . 47 viii Índice de figuras 1. Comparación Centro de datos - Computación en la nube . . . . . 4 2. Arquitectura Docker . . . . . . . . . . . . . . . . . . . . . . . . . 6 3. Planificador monolítico . . . . . . . . . . . . . . . . . . . . . . . . 11 4. Planificador de dos niveles . . . . . . . . . . . . . . . . . . . . . . 11 5. Planificador de estado compartido . . . . . . . . . . . . . . . . . 12 6. Planificador distribuido . . . . . . . . . . . . . . . . . . . . . . . 12 7. Arquitectura DC/OS . . . . . . . . . . . . . . . . . . . . . . . . . 14 8. Servicios DC/OS . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 9. Arquitectura de Apache Mesos . . . . . . . . . . . . . . . . . . . 17 10. Arquitectura multi-región en Nomad . . . . . . . . . . . . . . . . 20 11. Equipos sin consenso ejecutando el protocolo RAFT . . . . . . . 21 12. Un equipo pasa a estado candidato (RAFT) . . . . . . . . . . . . 22 13. Cambio en un registro (RAFT) . . . . . . . . . . . . . . . . . . . 22 14. Aprobación del resto de equipos (RAFT) . . . . . . . . . . . . . 23 15. Diagrama de tiempo del protocolo SWIM . . . . . . . . . . . . . 24 16. Procedimiento de asignación en Nomad . . . . . . . . . . . . . . 25 17. Arquitectura aplicación web . . . . . . . . . . . . . . . . . . . . . 28 18. Infraestructura en Azure . . . . . . . . . . . . . . . . . . . . . . . 29 19. Arquitectura de la aplicación web en DC/OS . . . . . . . . . . . 32 20. Despliegue en Azure de Nomad+Consul . . . . . . . . . . . . . . 35 ix 1. Introducción y objetivos 1.1. Contexto Las tecnologías de la información y la comunicación están suponiendo un cambio drástico en la sociedad: en 2007 comenzaron a aparecer los teléfonos inteligentes tal y como los conocemos y, nueves años después, se empieza a concebir la idea de dar conectividad a todo dispositivo electrónico, movimiento que ha tomado el nombre de Internet de las cosas. Para hacerse una idea de la rapidez y magnitud de esta evolución, la consultora Excelacom1 ha estimado que en un minuto se realizan 2,4 millones de búsquedas en Google o se ven 2,78 millones de vídeos en Youtube. En una época en la que los recursos tecnológicos crecen exponencialmente y los usuarios demandan mayor contenido y movilidad, no cabe duda que las empresas deben adaptarse lo más rápidamente posible a este proceso de digitalización, movidas por las nuevas necesidades de las personas. Dado el gran volumen de información, a lo largo de estos años, la computación y el almacenamiento están pasando de clientes locales a concentrarse en grandes centros de datos, una tendencia que Google ha denominado “Warehousescale computing” en 2009[1]. Este movimiento hacia la computación desde servidor no solo viene de la necesidad de mejorar la experiencia de los usuarios, sino también de facilitar la gestión y configuración de los recursos, así como la ubicuidad de acceso que permite. En 2006, Amazon lanza Amazon Web Services, siendo uno de los pioneros en el mercado de los recursos virtuales, ofreciendo capacidad de computación con un coste proporcional exclusivamente a los recursos utilizados. Todo ello cambió la perspectiva de los modelos tradicionales de TI a la conocida como computación en la nube: recursos informáticos, que antes suponían barreras de entrada en ciertos mercados, han pasado a ser condición necesaria para la constante evolución de la tecnología y la sociedad. De hecho, Cisco estima que para el año 2019, más del 86 % de las cargas de trabajo serán procesadas por centros de datos en la nube2 . 1 http://www.excelacom.com/resources/blog/2016-update-what-happens-in-one-internet-minute 2 http://www.cisco.com/c/en/us/solutions/collateral/service-provider/ global-cloud-index-gci/Cloud_Index_White_Paper.pdf 1 1.2. Objetivos El propósito de este proyecto es estudiar la viabilidad del uso de planificadores de recursos para aumentar la eficiencia de éstos y facilitar al desarrollador el despliegue de aplicaciones de forma distribuida y así, ofrecer un servicio caracterizado por una alta disponibilidad y escalabilidad. A lo largo de este trabajo se han usado algunas de las herramientas que se están comenzando a desarrollar para hacer frente a este nuevo enfoque de gestión de infraestructuras de las tecnologías de la información (en adelante infraestructuras TI), realizando pruebas de concepto sobre cada una de ellas. 1.3. Estructura del documento A continuación, se detalla las secciones que componen este trabajo. La estructura queda como sigue: Cloud computing Se entra en detalle en este nuevo modelo de negocio que ha originado nuevos enfoques y diseños de las infraestructuras TI dentro de las organizaciones. Nuevas cargas de trabajo Se explican algunas tecnologías representativas que están suponiendo un desafío para los profesionales de TI a la hora de planificar los recursos, y que se ven beneficiadas por entornos de tipo cloud. Gestión de recursos. Planificadores Estado del arte de las tecnologías de gestión de clusters y planificación de recursos. Herramientas Descripción detallada del funcionamiento y arquitectura de las herramientas usadas a lo largo del proyecto. Casos de uso y despliegue Se describe el proceso de implementación de una aplicación web y un servicio de integración continua con el software propuesto. Escalando la infraestructura Se propone un procedimiento con cierta independencia del proveedor cloud. Resultados y conclusiones Resume las ideas y hechos a los que se ha llegado, además de introducir líneas de investigación futuras. 2 2. Cloud Computing El NIST (National Insitute of Standards and Technology) define este concepto como un modelo que permite un acceso ubicuo y bajo demanda de forma remota a un conjunto compartido de recursos de computación, que pueden ser aprovisionados y liberados con unos mínimos esfuerzos de gestión por parte del proveedor del servicio3 . Clasificación La computación en la nube abarca una amplia variedad de servicios y enfoques, por lo que, en primer lugar, se va a dar una clasificación para posteriormente entrar más en detalle. Existen distintos modelos de nube atendiendo a la gobernabilidad de la infraestructura según el NIST: Nubes públicas. Los servicios y recursos son ofertados de forma pública y son provistos por una organización que los comercializa bajo demanda. Nube privada. Los recursos son gestionados por una única organización para su propio uso. Nube comunitaria. En este caso la infraestructura es administrada por un conjunto de organizaciones con objetivos comunes. Nube híbrida. Una combinación de las anteriores. A su vez, los distintos servicios que ofrece se pueden clasificar atendiendo al grado de control del usuario: Servicios de software (Software as a Service, SaaS). El proveedor se encarga de toda la gestión de la infraestructura y oferta aplicaciones, a las cuales el cliente puede acceder de forma ubicua a través de diversos clientes, como un navegador web. Por ejemplo, Office 365 o Google docs. Servicios de plataforma (Platform as a Service, PaaS). Modelo de distribución que ofrece la capacidad de desplegar aplicaciones desarrolladas por el cliente, usando las herramientas y lenguajes de programación soportadas por el proveedor, pero sin la posibilidad de gestionar los recursos consumidos. En este caso, el cliente solo tiene control sobre la propia aplicación y algunas configuraciones del entorno. Es el caso de Heroku o Google App Engine. 3 http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-145.pdf 3 Servicios de infraestructura (Infrastructure as a Service, IaaS). Se ofertan recursos de computación puros, como procesamiento o almacenamiento, mediante una plataforma de virtualización. El cliente puede controlar el sistema operativo, componentes de red y aplicaciones. Figura 1: Comparación Centro de datos - Computación en la nube Fuente: https://ad-hoc.net De entre las numerosas ventajas que ofrece la computación en la nube, se puede destacar su flexibilidad, ya que permite aprovisionar recursos y adaptarlos de acuerdo a la demanda, reduce el capital inmovilizado y su amortización, la ubicuidad que permite su consumo desde cualquier parte con conexión a la red y la seguridad y fiabilidad que ofrece el proveedor, que normalmente cuenta con recursos geográficamente distribuidos, frente a la gestión y mantenimiento de recursos propios. 4 3. Nuevas cargas de trabajo Las organizaciones que cuentan con sus propios infraestructuras TI han comenzado a adoptar un enfoque de nube privada para gestionar las tareas o funciones informáticas sobre las que se sustentan el negocio, ya que una estructura virtualizada puede ofrecer ventajas con respecto a las adaptaciones de centros de datos tradicionales en los ámbitos de rendimiento, escalabilidad e incluso seguridad4 . A su vez, se han desarrollado nuevas tecnologías que suponen cargas de trabajo dinámicas y con gran intensidad de consumo de datos para las empresas, que se ven beneficiadas al desplegarlas en recursos virtualizados. Big data Con la creciente aceptación de las tecnologías TIC por parte de la sociedad, la cantidad de datos generados en la red es ingente. Las profesionales de TI tiene como objetivo extraer valor de éstos para, por ejemplo, prever las tendencias del mercado. Sin embargo, este incremento exponencial hace que su procesamiento y almacenamiento requiera de un sistema con gran escalabilidad, dado el hecho de que una sola máquina no puede proveer de la capacidad necesaria. Integración continua Modelo informático que consiste en hacer integraciones automáticas de un proyecto con cualquier cambio en el código, con el objetivo de detectar fallos de forma temprana. Esto implica la compilación del código y su ejecución en un entorno de pruebas automáticamente, un proceso que mediante tecnologías de virtualización, permiten simular entornos con eficiencia y rapidez. Su implementación en sistemas distribuidos permite tanto una mejor planificación, como un mejor rendimiento de los recursos. Arquitectura de microservicios Enfoque para desarrollar aplicaciones software como un conjunto de servicios autónomos que se comunican entre sí, a diferencia de aproximaciones monolíticas, donde la lógica del servicio está desarrollada como una unidad. Un sistema distribuido permite el despliegue de los componentes en distintas máquinas, lo que mejora tanto su escalabilidad como la tolerancia a fallos. 4 https://www.akamai.com/es/es/resources/public-private-cloud.jsp 5 Docker Proyecto de código abierto que facilita y automatiza el despliegue de aplicaciones al encapsular el entorno de trabajo en contenedores Linux, una tecnología que permite a un sistema físico ejecutar múltiples instancias de sistemas operativos aislados mediante entornos virtuales, con sus propios espacios de procesos y redes, pero compartiendo el núcleo (kernel) con el equipo anfitrión. En la figura 2 se compara la pila de una virtualización tradicional con respecto a los contenedores: no se simula el sistema operativo, por lo que el proceso es mucho más ligero. Docker se caracteriza por: Autosuficiencia. Los contenedores cuentan con las librerías y configuraciones necesarias para ejecutarse de manera autónoma al compartir el núcleo. Portabilidad. El hecho de que sean autosuficientes implica que es independiente del host, es decir, se puede desplegar en cualquier equipo que soporte esta tecnología. Tamaño. El peso de un contenedor es sustancialmente inferior a otras tecnologías de virtualización. Figura 2: Arquitectura Docker Fuente: https://docker.com 6 Los componentes fundamentales de esta herramienta son: Imágenes. Describen el entorno de base sobre el que ejecutar el contenedor, por ejemplo, la imagen del sistema operativo Ubuntu. Sobre ésta se construyen las aplicaciones particulares del usuario, dando lugar a otra imagen. Contenedores. Se crean a partir de las imágenes y comprenden todo aquello necesario para arrancar la aplicación, decir, su entorno de ejecución. • Volúmenes: Encargados de gestionar la persistencia de datos e independientes del ciclo de vida del contenedor. Registros. Pueden ser públicos o privados y almacenan las imágenes; el registro público oficial de Docker es Docker Hub. Dadas estas características, los profesionales TI están comenzando a adoptar Docker ya que facilita tanto los despliegues como el trabajo compartido en distintos entornos. Sin embargo, esto requiere de un software que permita desplegar los distintos contenedores de forma que puedan trabajar en conjunto, proceso que se ha denominado orquestación de contenedores. 7 4. Gestión de recursos. Planificadores Para sacar el máximo provecho a las tecnologías anteriormente descritas, lo ideal es desplegarlas en sistemas distribuidos, sin embargo, esto aumenta la complejidad del propio despliegue así como la necesidad de software especializado para ello. Se necesitan algoritmos de planificación que permitan obtener el máximo rendimiento de los recursos por un lado y dar ciertas garantías de que todas las tareas y procesos se van a ejecuta por otro. 4.1. Sistemas distribuidos En primer lugar, se definen los sistemas distribuidos o clusters, como un conjunto de ordenadores conectados entre sí cuyo objetivo es trabajar como una única instancia de gran capacidad5 . Su clasificación varía de acuerdo a cada autor, pero en general, se pueden dividir según su objetivo en: alto rendimiento, aquellos cuyo objetivos es proveer de gran capacidad de cómputo gracias al conjunto de los nodos, y alta disponibilidad, con los cuales se busca la fiabilidad del sistema mediante redundancia y/o balanceo de carga. El interés de este proyecto recae en los últimos ya que el objetivo es, por un lado, ofrecer al desarrollador un entorno donde desplegar sus aplicaciones de forma distribuida, y por otro, maximizar el rendimiento de los recursos. De forma general, las características que se buscan son las siguientes: Elasticidad. Adaptación a cargas dinámicas de trabajo aumentando (o disminuyendo) recursos de manera automática, de tal forma que la utilización sea lo más cercana a la demanda. Disponibilidad. Capacidad de un sistema para mantener el servicio funcional. Tolerancia a fallos. Recuperación del servicio ante el fallo de un componente. Balanceo de carga. Compartir las tareas entre las diferentes máquinas redundadas evitando así puntos de único fallo. 5 https://en.wikipedia.org/wiki/Computer_cluster 8 Los programas que se implementan en entornos distribuidos se caracterizan por ejecutarse de forma concurrente en equipos independientes, estar conectados por una red que introduce fallos aleatorios y no compartir memoria ni reloj. Esto implica, entre otras cosas, que: Los nodos sólo tienen un acceso rápido a su memoria local por lo que cualquier información relativa al estado global puede ser potencialmente errónea. Las máquinas pueden sufrir caídas de forma aleatoria. El intercambio de información puede fallar ya sea por error en transmisión o por caída de los nodos. Estas dificultades se ponen de manifiesto en el teorema de CAP: en ciencias de la computación, el teorema de CAP que lanzado inicialmente como conjetura en el año 2000 por Eric Brewer (motivo por el cual al teorema se le conoce formalmente como teorema de Brewer), y posteriormente demostrado en el año 20026 , establece que es imposible para un sistema de cómputo distribuido garantizar simultáneamente dos de las tres propiedades siguientes: Consistencia (Consistency), es decir, que todos los nodos vean la misma información al mismo tiempo. Se busca que un cambio en el sistema sólo se ejecute satisfactoriamente si y sólo si se efectúa a todos las máquinas, de tal forma que los datos entre ellos nunca difieren y la respuesta a una petición sea la misma, independientemente del nodo que la atienda. Disponibilidad (Availability), esto es, la garantía de que toda petición debe obtener una respuesta (servicio funcional), aunque exista inconsistencia entre nodos. Tolerancia al particionado (Partition Tolerance), es decir, que el sistema siga funcionado a pesar de un fallo en la comunicación entre los equipos. Por todo lo expresado anteriormente, conseguir un sistema distribuido capaz de ofrecer procesamiento de forma transparente implica una arquitectura TI compleja. Se requieren de subsistemas y herramientas que permitan la cohesión entre todos los nodos: Gestor de los recursos de las diferentes máquinas. Monitorización tanto de los servicios activos como de la funcionalidad del sistema, además de políticas para recuperación de fallo. Protocolos de consenso que permitan a los nodos ser consistentes con el estado global del cluster. 6 urlhttps://groups.csail.mit.edu/tds/papers/Gilbert/Brewer2.pdf 9 Herramientas de descubrimiento de servicios que permita la comunicación entre tareas distribuidas. Planificadores. Encargados de distribuir las tareas y procesos en las diferentes máquinas, asignándole parte de su capacidad. Los planificadores, del inglés cluster schedulers son un componente fundamental, por lo que vamos a entrar un poco más en detalle en ellos. Planificadores (Cluster Schedulers) Es el software encargado de monitorizar los recursos usados por cada máquina perteneciente a un cluster y distribuir la carga de trabajo entre ellas de acuerdo a un política o reglas. Este tipo de herramientas comparten cierta terminología que es relevante definir: Tarea. Unidad de trabajo computacional comprendida por una secuencia de instrucciones, datos de entrada y recursos asociados. Por ejemplo, la ejecución de un comando o el arranque de una base de datos. Nodo. Cualquier máquina integrante de un cluster. En una arquitectura maestro-esclavo se definen dos roles: • Cliente, Agente, Esclavo. Aquellos ordenadores que se encargan de ejecutar las tareas. • Maestro, Servidor. Su objetivo es mantener el estado del cluster y gestionar sus recursos. 4.1.1. Clasificación A lo largo de los últimos años, se han desarrollado diferentes tipos de planificadores[2]: Monolítico Un solo planificador que se encarga de distribuir todas las tareas entrantes. La mayoría de los planificadores en computación de alto rendimiento, así como Borg, desarrollado por Google, son de este tipo. En la figura 3 se puede observar de forma gráfica el procedimiento, siendo las cajas grises máquinas pertenecientes al cluster y los círculos, las tareas a asignar. 10 Figura 3: Planificador monolítico Fuente: https://www.cl.cam.ac.uk Planificación de dos niveles La mayoría de los clusters ejecutan aplicaciones con distintas necesidades, desde procesos casi instantáneos hasta servicios persistentes,lo que implica distintas necesidades de recursos. Por ello, la planificación a dos niveles distingue dos funciones: la gestión de recursos (gestor) y la disposición de las tareas (planificador). Cada servicio tiene su propio planificador, de tal manera que el gestor les “oferta” recursos de acuerdo a una política y los planificadores se encargan de escoger la más adecuada. Esto permite que el proceso de distribución sea más acorde con las necesidades de los diferentes servicios. Apache Mesos, que detallaremos más adelante, sigue este esquema. Como desventaja, cabría señalar que esta programación implica que los planificadores pierden la vista general de la infraestructura y las tareas sólo pueden ejecutarse con los recursos que les son ofrecidos, lo que dificulta la implementación de prioridades de ejecución de tareas, entre otras. Figura 4: Planificador de dos niveles 11 Planificación de estado compartido Múltiples réplicas del estado del cluster se actualizan independientemente para cada planificador, como se observa en la figura 5; cuando sucede un cambio de forma local, el planificador se encarga de informar al resto. Ejemplo de este tipo son Omega, la evolución de Borg por parte de Google, Microsoft Apollo y Nomad, que usaremos para los casos de uso. De entre las desventajas se puede destacar el hecho de que, en general, los nodos trabajan con información desactualizada, lo que conlleva una degradación del rendimiento en situaciones de alta contienda. Figura 5: Planificador de estado compartido Planificación distribuida En este caso no existe coordinación entre los distintos planificadores. Cada uno de ellos funciona con su propia vista del cluster. Las tareas pueden ser organizadas por cualquiera de ellos y desplegadas en cualquier parte del cluster, en base a la aleatoriedad y multiplexación estadística de los flujos de trabajo, sin ningún control central. Figura 6: Planificador distribuido 12 5. Herramientas En la industria comienzan a aparecer soluciones software de código abierto que aglutinan los servicios necesarios para gestionar la infraestructura TI de manera más eficaz. El objetivo es doble: se busca facilitar la gestión de los recursos de computación para organizaciones con instalaciones propias mediante su uso con un enfoque cloud, esto es, desplegar aplicaciones a través de un conjunto de ordenadores de forma transparente y sin tener en cuenta la infraestructura subyacente; o aprovechar el máximo rendimiento de la infraestructura de los proveedores cloud públicos, de forma que se tiene el máximo control sobre ésta pero no se depende de las soluciones propietarias, permitiendo así despliegues híbridos. Entre estas herramientas se pueden destacar: OpenStack Proyecto desarrollado por la fundación del mismo nombre para proporcionar servicios de infraestructuras (IaaS) basado en componentes que se comunican a través de APIs. El componente Magnum incluye motores de orquestación de contenedores. Kubernetes Sistema de orquestación de contenedores Docker creado por Google. CoreOs Sistema operativo basado en Linux, diseñado para despliegues distribuidos sobre contenedores, incluyendo mecanismos de descubrimiento de servicio y compartición de configuración. Docker Swarm Herramienta nativa de orquestación de contenedores Docker. YARN Entorno de gestión de recursos y aplicaciones distribuidas de Hadoop, una librería software de procesamiento de grandes conjuntos de datos. Como podemos observar, existe un gran rango de opciones para gestionar la infraestructura, desde un bajo nivel como puede ser OpenStack, hasta Kubernetes o Docker Swarm, que ofrecen exclusivamente orquestación de contenedores. En este trabajo se ha optado por Mesosphere DC/OS y HashiCorp Nomad, que se encuentran en el término medio: su objetivo es proporcionar servicios de plataforma que permitan la coexistencia dediferentes cargas de trabajo en el cluster. 13 5.1. DC/OS DC/OS es un proyecto de código abierto7 creado y desarrollado por la empresa Mesosphere. Se describe como un sistema operativo distribuido, que abstrae los recursos de un cluster (capacidad de procesamiento, memoria), permite la gestión de múltiples ordenadores de forma transparente y simplifica la instalación de aplicaciones distribuidas. Su arquitectura se puede comparar a la de Linux en términos de núcleo (kernel) y espacio de usuario. El primero consta de recursos protegidos, a los que no puede acceder el usuario, e involucra operaciones de bajo nivel como asignación de recursos o aislamiento de procesos. En el espacio de usuario se ejecutan las aplicaciones y servicios de más alto nivel. Siguiendo con este símil, el núcleo de DC/OS está basado en Apache Mesos, que se explicará en un apartado posterior, y el espacio de usuario, que está comprendido por los componentes del sistema, esto es, las diferentes herramientas que en conjunto conforman DC/OS, y los servicios, encargados de planificar y ejecutar las aplicaciones y tareas del usuario: Figura 7: Arquitectura DC/OS Fuente: https://dcos.io/ De entre los componentes que conforman DC/OS destacan: Admin Router. Balanceador de carga central, basado en NGINX, que dispone un proxy entre todos los servicios en el puerto 80, permitiendo su gestión mediante la interfaz gráfica. Además se encarga de la autenticación para acceder al panel de administración. Cosmos. Gestor de paquetes de las aplicaciones. Diagnostics. Se ejecuta en todos los nodos y se encarga de monitorizar el estado de los daemons que sustentan DC/OS. 7 Desde abril de 2016: https://mesosphere.com/blog/2016/04/19/open-source-dcos/ 14 Exhibitor. Gestiona y automatiza el despliegue de ZooKeper, la herramienta que provee de configuración centralizada y registro de nombres. Marathon. Equivale al proceso init de los sistemas tipo Unix, esto es, el primer proceso en ejecución tras la carga del kernel y que genera los demás procesos. Se encarga de arrancar y monitorizar las aplicaciones y servicios. Mesos-DNS. Servicio de DNS interno que define el dominio .mesos para nodos y tareas en el cluster, es decir, permite resolver nombres con independencia de la dirección física. Minuteman. Balanceador de carga integrado a nivel TCP/UDP disponible para las propias aplicaciones. Por otra parte, se definen como servicios a las diferentes aplicaciones distribuidas que DC/OS permite instalar en el cluster, y que pueden haber sido desarrollados por la misma empresa Mesosphere o por terceros, por ejemplo, Apache Spark, Jenkins o Apache Hadoop. En la figura 8 se muestra un diagrama de los servicios disponibles, incluyendo algunos de las aplicaciones distribuidas que soporta DC/OS: Figura 8: Servicios DC/OS Fuente: https://dcos.io/ 5.1.1. Apache Mesos El núcleo de DC/OS está basado en Apache Mesos, un proyecto de código abierto creado por la Universidad de California, Berkeley y desarrollado actualmente por la fundación Apache. Se trata de un administrador de clusters que abstrae los recursos y los dispone para diferentes aplicaciones y entornos de trabajo distribuidos (frameworks) mediante una interfaz común. En el momento de redacción de este proyecto, Apache Mesos soportaba una variedad de entornos que abarcaba desde Big Data (Apache Spark, Hadoop) hasta bases de datos (Cassandra, Hypertable). 15 Arquitectura Mesos se basa en la asignación de dos roles diferentes a los nodos: Maestros (Masters). Se encargan de la gestión y repartición de los recursos para los diferentes entornos de trabajo mediante “ofertas de recursos”, de acuerdo a los disponibles y a la política de asignación (planificación en dos niveles). Esclavos (Slaves). Ordenadores donde se ejecutarán las aplicaciones y cuyos recursos son ofertados por los maestros. En el caso de fallo del maestro, las tareas pueden seguir ejecutándose pero no se podrá asignar nuevos recursos ni tareas, por ello, pueden existir varios en el cluster para configuraciones de alta disponibilidad, pero sólo uno orquesta a los esclavos. Para la elección del master líder, Mesos usa Apache ZooKeeper, un proyecto de software desarrollado por la misma fundación, cuyo objetivo es proveer de un servicio de configuración centralizado y registro de nombres8 . Por otra parte, los entornos de trabajo son los programas que deciden finalmente qué recursos se van a usar y se encargan de que los esclavos ejecuten las tareas. Éstos se ejecutan sobre Mesos y constan de dos componentes: Planificador (Scheduler). Optimiza y decide los recursos a utilizar de los ofertados, informando a los Masters. Procesador (Executor). Ejecuta las aplicaciones o servicios en los esclavos. El objetivo final es conseguir una interfaz liviana tolerante a fallos para cualquier tipo de entorno de trabajo, de tal manera que en los esclavos del cluster puedan ejecutarse simultáneamente tareas con necesidades y duración diferentes. Para ello, se basa en dos conceptos: asignación y aislamiento de recursos. Asignación de recursos En el cluster pueden coexistir entornos de trabajo con tareas de larga duración y con gran consumo de recursos, con tareas cortas que los ocupan y liberan con rapidez. El maestro integra un módulo de asignación de recursos (allocation module) que se encarga del algoritmo de distribución. En el momento de escribir este proyecto estaban desarrollados dos módulos: uno mediante el cual el usuario puede asignar prioridades y otro que implementa 8 https://zookeeper.apache.org/ 16 el algoritmo Dominant Resource Fairness9 : a grandes rasgos, se determina en todos los esclavos la tarea en ejecución que necesita más recursos y se calcula la proporción del recurso de mayor peso con respecto al total; por ejemplo, si una tarea ocupa 2 GB de memoria con respecto a 10 GB totales que tiene el cluster, se le asigna un dominant share del 20 %; la tarea se asignará al nodo con menor dominant share. Aislamiento de recursos Para conseguir que tareas de diferentes entornos de trabajo y con distinta naturaleza se ejecuten simultáneamente en un mismo nodo, Mesos usa los contenedores Linux (descritos en la sección 3). Funcionamiento La figura 9 muestra el esquema de la arquitectura de Apache Mesos con alta disponibilidad (tres maestros) y con dos entornos de trabajo ejecutándose: Hadoop, que permite el almacenamiento y procesamiento de gran cantidad de datos para proyectos de big data; y un sistema que implementa la interfaz sistema de paso de mensajes MPI. Como se puede observar, el sistema ZooKeeper elige a un solo maestro como líder y éste orquesta el cluster comunicando los esclavos con los planificadores de los diferentes entornos de trabajo. También se puede observar como las tareas de los distintos entornos están distribuidas entre los tres esclavos disponibles. Figura 9: Arquitectura de Apache Mesos Fuente: https://mesos.apache.org/ El proceso de asignación se realiza como sigue: en primer lugar, un usuario solicita la ejecución de una tarea mediante la interfaz de cada entorno de trabajo (interfaz gráfica, API HTTP,. . . ). De forma paralela, un esclavo informa al maestro de los recursos que tiene libres. En consecuencia, éste se lo notifica al módulo de asignación que, en función de su configuración, decide cuánto ofertar 9 https://people.eecs.berkeley.edu/~alig/papers/drf.pdf 17 y a qué entorno de trabajo, y envía la oferta a los planificadores. Éstos responden al maestro con qué recursos ha decidido usar para cada tarea. Finalmente, las tareas son enviadas al esclavo seleccionado, el cual asigna los recursos indicados al procesador (executor), quien finalmente las ejecuta. Cabría pensar que esta metodología puede conducir a situaciones en las que un entorno podría quedarse con tareas sin ejecutarse a la espera de una oferta satisfactoria; para ello, Mesos implementa un sistema de filtros mediante el cual los entornos especifican los requisitos mínimos que debe cumplir una oferta, por ejemplo, se puede especificar en qué nodos debe desplegarse la tarea. Este sistema está diseñado así con el objetivo de mantener lo más transparente posible esta herramientas de forma que acepte entornos de trabajo de distintas naturalezas. 5.1.2. Ejemplos de uso Grandes empresas están usando Apache Mesos con eficacia de acuerdo a sus necesidades e infraestructuras. Caben destacar: Ebay En el modelo de implementación continua en esta empresa10 , cada desarrollador cuenta con su propia instancia, que se ejecuta en una máquina virtual dedicada, lo que ha conllevado un uso de los recursos poco eficiente. En una prueba de concepto, consiguieron realizar una herramienta de integración continua distribuida basada en un cluster con Apache mesos y con el entorno Marathon y Jenkins. Apple Anunció que el motor de su famosa herramienta de asistencia personal para iPhones, Siri, está desplegada sobre Apache Mesos11 . Para ello, han desarrollado su propio entorno para facilitar a los ingenieros a desplegar los servicios que la herramienta necesita para resolver las peticiones de los usuarios. Twitter Desarrolló su propio entorno, denominado Aurora, y actualmente, gestionan sus recursos y miden el coste de las tareas que los empleados usan con el objetivo de que sean conscientes del gasto que puede suponer un uso inadecuado de la infraestructura12 . 10 http://www.ebaytechblog.com/2014/04/04/delivering-ebays-ci-solution-with-apache-mesos-part-i/ 11 http://www.businessinsider.com/apple-siri-uses-apache-mesos-2015-8 12 https://www.linux.com/NEWS/4-UNIQUE-WAYS-UBER-TWITTER-PAYPAL-AND-HUBSPOT-USE-APACHE-MESOS 18 5.2. Nomad Herramienta de código abierto de gestión de clusters, creada y desarrollada por Hashicorp13 , que permite el despliegue de aplicaciones y procesos de forma distribuida. Las principales diferencias con Apache Mesos, a grandes rasgos, son: Arquitectura más ligera: Nomad sólo requiere de un fichero para funcionar; ejecutándolo con las correspondientes configuraciones en todos los nodos, realiza las funciones de gestión del cluster, elección de líder, planificación de recursos y ejecución de las tareas. Centro de datos y regiones múltiples: Su arquitectura está orientada a facilitar la gestión de diferentes centros de datos geográficamente distribuidos. Entorno de ejecución: Las tareas se definen y son interpretadas mediante controladores integrados en Nomad, que se valen de los recursos y herramientas de los nodos clientes para ejecutarlas. Esta integración dificulta el desarrollo de controladores por parte de terceros, a diferencia de Mesos, que delega dicha responsabilidad en los entornos de trabajo externos al proyecto. Usa un planificador de estado compartido con respecto a la planificación en dos niveles de Mesos. Antes de entrar en más detalle en la arquitectura, es importante definir los siguientes términos: Controlador (Driver) Software que se encarga de interpretar las definiciones de las tareas y ejecutarlas, semejante a los procesadores de los entornos de trabajo de Mesos. A la hora de redactar este proyecto, Nomad contaba con controladores para contenedores Docker, virtualización de máquinas mediante el emulador QEMU, aplicaciones java y archivos binarios. Grupo de trabajo (Task Group) Conjunto de tareas que se ejecutan en el mismo nodo cliente. Trabajo (Job) Conjunto lógico de tareas y grupos de trabajo que se despliegan a la vez. Asignación (Allocation) Relación entre un grupo de trabajo y el cliente donde se ejecuta. Evaluación (Evaluation) Proceso mediante el cual Nomad planifica y gestiona el registro o actualizaciones de los trabajos. 13 https://www.hashicorp.com/ 19 Nomad sigue una arquitectura maestro-esclavo similar a la de Apache Mesos: múltiples servidores acuerdan entre sí un líder, que gestiona la planificación de tareas en los clientes, que sólo conocen sus asignaciones y las ejecutan. Todos los servidores participan paralelamente en tareas de planificación de recursos y asignación de tareas y, además, entre ellos eligen un líder que se encarga de la coordinación de la suscripción de los clientes al cluster y de la gestión de las peticiones. Los clientes están configurados para comunicarse con el servidor usando llamadas a procedimiento remoto (RPC, por sus siglas en inglés) que permite un ordenador ejecutar código en otra máquina. Mediante esta tecnología, los nodos clientes avisan de su estado e informa de sus asignaciones, recursos y controladores disponibles. Existe la posibilidad de gestionar varios centros de datos agrupados en regiones; éstas son independientes, pero permite definir tareas o comprobar el estado de todas ellas desde cualquier punto. A continuación se muestra una figura de la arquitectura a alto nivel de esta configuración: Figura 10: Arquitectura multi-región en Nomad Fuente: https://www.nomadproject.io/ La herramienta se sustenta sobre tres protocolos fundamentales: un protocolo de consenso entre los servidores para compartir información sobre su estado y el líder, un protocolo Gossip para la gestión entre regiones, y el planificador de tareas. 5.2.1. Protocolo de consenso. Raft El objetivo es obtener consistencia en un conjunto de nodos que comparten información, es decir, si un cliente realiza un cambio, que todos los nodos vean la misma información a la vez, y además, sea tolerante a fallos. Para ello se basa en el algoritmo Raft[13], que se detalla brevemente a continuación. 20 Los nodos participantes en el algoritmo pueden estar en tres estados: Líder (Leader) Todos los cambios que realicen en el cluster pasan por él primero. Seguidor (Follower) Nodo pasivo cuya responsabilidad es responder a las peticiones del nodo líder. Candidato (Candidate) Máquina que no ha encontrado líder y solicita su elección. Supongamos que tenemos cinco equipos que acaban de arrancar el protocolo. En la figura 11 se observan los nodos y sus respectivos registros a la derecha. Figura 11: Equipos sin consenso ejecutando el protocolo RAFT Fuente: https://github.com/ongardie/raftscope Al comenzar, todos los nodos son seguidores esperando recibir comunicación de un nodo que actúe como líder. Cada nodo tiene un tiempo de espera aleatorio después del cual, si no es informado por un líder, pasa a estado candidato y pide el “voto” al resto de los participantes. El algoritmo divide el tiempo en plazos: un candidato pasa a líder si recibe la mayoría de los votos en un plazo determinado. Se define mayoría o cuórum (quorum) como: N/2 + 1 (1) donde N representa el número de nodos. Para el ejemplo propuesto de 5 equipos, se requieren de 3 votos. Sólo los nodos que se encuentren en estado seguidor pueden votar una única vez a la primera solicitud que reciba dentro de un plazo. Supóngase que el nodo denotado con S1 ha cumplido su tiempo de espera y realiza la petición de voto (figura 12). A partir de este momento se pueden dar tres casos: La máquina gana la elección y pasa a ser líder, informando al resto. Otro servidor se establece como líder en el mismo momento. Varios nodos pasan a ser candidatos por lo que ninguno consigue los votos. 21 Figura 12: Un equipo pasa a estado candidato (RAFT) Si un candidato recibe un aviso de un líder en el mismo plazo, el primero pasa a ser seguidor y se acaba la elección de líder. Por otro lado, si un equipo candidato no recibe los votos en el plazo y agota su tiempo de espera, avanza al siguiente plazo y repite el proceso de votación. La tercera posibilidad puede conllevar a un estado indefinido ya que varios candidatos pueden agotar su tiempo de espera al mismo tiempo y repartir los votos. Para solventarlo, el algoritmo, establece tiempos de espera aleatorios para los candidatos. Siguiendo con el ejemplo propuesto, el servidor S1 pasa a ser el líder. Cada cierto tiempo, éste debe realizar avisos a los nodos seguidores para no agotar su tiempo de espera. En este momento, el cluster de servidores está en “consenso” y la información en todos los nodos está actualizada. Un cambio en la información inicia un proceso de replicación: el líder registra el cambio, lo pasa al resto de nodos, y una vez éstos responden, el cambio se hace efectivo. Supóngase que se realiza un cambio en los datos; en la figura 13, en la parte derecha, se observa el cambio en el registro del servidor S1, que informa a los nodos seguidores. En consecuencia, los nodos registran el cambio y responden a S1. Figura 13: Cambio en un registro (RAFT) Una vez el cuórum (en el ejemplo, tres equipos) informa al líder de que 22 ha registrado el cambio, el líder lo hace efectivo en su sistema y notifica a los nodos, que hacen lo mismo. En la figura 14, el envío todavía no ha llegado a la máquina S3 y se observa que no ha hecho efectivo el cambio (en el registro aparece punteado). Figura 14: Aprobación del resto de equipos (RAFT) Este protocolo funcionará correctamente mientras exista un número de nodos en funcionamiento igual o superior al cuórum : en el ejemplo propuesto, el cuórum es tres por lo que el sistema puede tolerar la caída de dos de los equipos. 5.2.2. Protocolo gossip. SWIM Nomad permite la gestión simultánea de varios centros de datos repartidos en regiones geográficamente separadas, requiriendo de un protocolo ligero que mantenga a los miembros actualizados sobre los participantes del conjunto. Para ello, usa una ligera variante del protocolo SWIM[3] (Scalable Weaklyconsistent Infection-style Process Group Membership Protocol) desarrollada por HashiCorp. Está clasificado como un protocolo de tipo gossip, que debe su nombre a la semejanza con cómo se distribuye un rumor en una red social. SWIM se sustenta en dos características fundamentales: la detección de fallos y la distribución de la información relativa a los miembros. A continuación se detalla el funcionamiento de ambos componentes: Detección de fallos Este componente tiene dos parámetros: el periodo de protocolo T y el número de subgrupos de detección de fallos k en los que se dividen los nodos. Para comprobar la comunicación entre dos máquinas usa la utilidad ping, basada en el protocolo ICMP. La detección de caída de un servidor sigue el siguiente algoritmo: Durante el periodo T, cada miembro Mi de un subgrupo elige otro al azar Mj del mismo subgrupo y le envía un mensaje ping para comprobar su estado. En el caso de que se cumpla un tiempo de espera, determinado por una estimación 23 del tiempo de ida y vuelta (RTT, por sus siglas en inglés) de la red, y no haya respuesta, Mi le vuelve a enviar un mensaje ping indirectamente a través de un número k de miembros escogidos aleatoriamente. De no recibir ninguna respuesta, Mi establece que Mj ha sufrido un fallo y lo etiqueta como “sospechoso”, informando al componente de distribución. Figura 15: Diagrama de tiempo del protocolo SWIM Fuente: https://www.cs.cornell.edu Componente de distribución Se encarga de informar de cualquier cambio en los miembros a todo el conjunto. Los eventos de nodo caído y la unión o disociación de un miembro se transmiten a todos los servidores para que actualicen sus lista. Para distribuir la información a todos los nodos, se podría usar el método de multicast, pero suele estar deshabilitado. Por ello, se utiliza una técnica de transmisión denominada Piggybacking, mediante la cual, se adjunta a los propios mensajes PING y ACK del algoritmo la información a distribuir, reduciendo así la congestión en la red. 5.2.3. Planificación Proceso encargado de distribuir las tareas entre los nodos clientes de acuerdo a su estado. El planificador de Nomad está basado en las publicaciones de Google sobre sus herramientas de gestión de clusters Borg y Omega14 y entiende los trabajos descritos por el usuario como un estado deseado, es decir, su despliegue en una máquina cliente de forma correcta, y los clientes como el estado actual, esto es, lo que se encuentra en ejecución. El registro, actualización o cancelación de un 14 http://research.google.com/pubs/pub43438.html 24 trabajo, así como el fallo de un nodo cliente, implican un cambio de estado a tramitar por el sistema, lo que se define como evaluación (evaluation). Esto último supone comparar el estado actual (clientes) con el estado deseado (conjunto de trabajos registrados) y enviarlos a los planificadores correspondientes, que se encargarán de asignar las tareas a los nodos clientes. Figura 16: Procedimiento de asignación en Nomad Fuente: https://www.nomadproject.io/ En la figura 16 se observa el flujo de trabajo en el que las distintas evaluaciones se encolan en el evaluation broker, que se ejecuta en el servidor líder y gestiona las evaluaciones pendientes asignándoles prioridades. A continuación, los nodos servidores ejecutan los scheduling workers que procesan las evaluaciones llamando a los distintos planificadores, que generan un plan de asignación, esto es, un conjunto de relaciones entre las tareas y los nodos clientes donde se ejecutarán. Este proceso se divide en dos fases: primero se descartan aquellos clientes que no cumplan los requisitos y, posteriormente, se asigna una calificación al resto. Se selecciona el nodo con mayor puntuación y se encola el plan en el gestor, que se ejecuta en el servidor líder. Existen tres planificadores de acuerdo al tipo de trabajo: Service Incluye aquellos trabajos que están destinados a ejecutarse en un período largo de tiempo. Para realizar las asignaciones, el planificador evalúa la mayor parte de los nodos y usa una versión del algoritmo Best fit influenciada por el trabajo de Google en su herramienta Borg. Se trata de un algoritmo de planificación que sacrifica tiempo a cambio de maximizar el rendimiento de los clientes asignando la tarea a la máquina que tenga la mayor carga de trabajo con el objetivo de reducir equipos en funciona25 miento. Batch Tareas que incluyen listas de comandos, en general de menor duración, y que no requieren interacción con el usuario. Se vale del algoritmo de Sparrow, desarrollado por la universidad de Berkeley15 para limitar los nodos clientes a evaluar. System Trabajos destinados a ejecutarse en todos los nodos, incluso los que se unen al cluster posteriormente. Core Mantenimiento interno de Nomad Una vez se ha realizado el proceso de planificación, el nodo líder lo registra en la cola de planes (plan queue) que se encarga de asignarles prioridad y manejar condiciones de carrera, es decir, que no accedan a los recursos de los clientes sin control y evitar que éstos superen su capacidad. La máquina líder del conjunto puede, de este modo, aceptar una asignación y ser ejecutada por los clientes, o por el contrario, rechazársela al planificador, lo que implicaría realizar un plan parcial o totalmente nuevo. Finalmente, el estado de las evaluaciones se actualizan y los clientes son informados de las asignaciones, ejecutándose las tareas. 15 http://people.eecs.berkeley.edu/~keo/publications/sosp13-final17.pdf 26 6. Casos de uso y despliegue Con el objetivo de mostrar las posibles utilidades que este tipo de sistemas pueden tener en las infraestructuras TI actuales, se han desplegado las dos herramientas en la nube Microsoft Azure, usando su servicio cloud de instancias de máquinas virtuales Linux para simular un conjunto de ordenadores conectados entre sí por una red LAN. Sobre ellas, se ha implementado dos casos de uso: una aplicación web con una arquitectura con cierta orientación a microservicios y un sistema de integración continua. El código y todos los ficheros de configuración se pueden encontrar en el repositorio del proyecto en GitHub16 . 6.1. Aplicación Web Se busca simular el proceso de adaptación de una solución web para su despliegue en un sistema distribuido con las herramientas anteriormente descritas, con el objetivo de aumentar tanto su escalabilidad como disponibilidad mediante redundancia. Se ha partido de una aplicación ya existente17 , un servicio de almacenamiento y reproducción de canciones. A grandes rasgos, este servicio permite crear usuarios, subir canciones con sus respectivas portadas, tener playlists propias y escuchar las canciones a través de un navegador web. La solución está dividida en 4 partes (figura 17): Una vista web con la lógica. Un almacenamiento conectado en red (NAS, por sus siglas en inglés). Una API REST para gestionar las peticiones al almacenamiento. Base de datos NoSQL basada en MongoDB. La nueva tendencia de los proyectos web es su implementación en contenedores Docker ya que facilitan su portabilidad y ofrecen un procedimiento de despliegue rápido, sobre todo a la hora de desarrollar y realizar pruebas en entornos de producción simulados. Por ello, en este caso se va a hacer uso de los 16 https://github.com/AntonioAlfrz/Cloud-Orchestrators 17 https://github.com/sonsoleslp/CDPSfy 27 motores de orquestación de contenedores de ambas herramientas: Marathon en DC/OS y el controlador Docker en el caso de Nomad. Figura 17: Arquitectura aplicación web A continuación vamos detallar el despliegue en ambas herramientas de esta solución y observar tanto qué dificultades se encuentran, como que ventajas ofrecen. El objetivo final es adaptar el proyecto modificándolo lo menos posible con objeto de analizar la capacidad de estas herramientas para desplegar cualquier aplicación sin que eso conlleve la modificación de la arquitectura de ésta, es decir, que no sea dependiente del entorno. 6.1.1. DC/OS Se ha descrito DC/OS como una herramienta que se despliega sobre un conjunto de ordenadores y que permite instalar gestionar el despliegue de sistemas distribuidos. Microsoft Azure cuenta con una plantilla para desplegar en su servicio cloud un cluster de máquinas virtuales con DC/OS ya instalado, que cuenta con: Máquinas maestras (1, 3 o 5 a seleccionar por el usuario), configuradas como un conjunto de disponibilidad, esto eso, Azure da ciertas garantías de que al menos una máquina estará en funcionamiento. Máquinas agentes. Por motivos de seguridad, se distinguen dos roles: • Nodos privados, solo accesibles desde la red interna, y configurados como un conjunto de escala, un recurso de Azure para gestionar y desplegar máquinas con configuraciones idénticas para permitir un rápido escalado. • Un equipo conectado accesible desde Internet a travñes de un balanceador de carga público y situado en una subred externa. 28 Dos balanceadores de carga: • La interfaz pública del cluster, que se conecta con el cliente público. • Acceso a los equipos maestros para el administrador, que sólo permite conexión mediante SSH y credenciales. Almacenamiento para todas las máquinas. Configuraciones necesarias de red y seguridad. En la figura 18 se observa un diagrama de la infraestructura: Figura 18: Infraestructura en Azure El primer obstáculo es la persistencia de estado de la aplicación, que se consigue gracias a una base de datos no relacional basada en MongoDB, así como el almacenamiento de las canciones. Para implementarla tenemos varias posibilidades: Montar un sistema externo de almacenamiento conectado en red en todos los agentes donde se ejecuten las tareas; de esta manera, si una tarea pasa de un nodo a otro por cualquier motivo, puede tener acceso a los mismos ficheros (opción del caso de uso original). Implementar un sistema de ficheros distribuidos en los agentes. Usar los servicios de almacenamiento de las nubes públicas. Aprovechar el sistema de volúmenes persistentes de Apache Mesos. Éste permite reservar recursos de un agente de forma que al arrancar una tarea, se crea un volumen independiente del ciclo de vida de ésta, con ello, esos recursos donde se ha almacenado la información pueden volver a ofrecerse al mismo entorno, de tal manera que otra tarea pueda acceder a ella. DC/OS aprovecha este sistema de volúmenes persistentes y permite instalar bases de datos distribuidas como ArangoDB o Apache Cassandra; sin embargo, esto implicaría modificar todo el código referente al modelo de la base de datos. 29 Por motivos de eficiencia y latencia, así como de una mayor gobernabilidad de los datos, la mejor opción es usar el recurso de volúmenes persistentes que ofrece Apache Mesos, ya que de esta manera se gestionaría la aplicación completa mediante una única herramienta. Sin embargo, esto implica que la información se encuentra exclusivamente en el agente donde se haya ejecutado la tarea y, por lo tanto, se sigue requiriendo de software externo para distribuir la información para que se accesible para todos los agentes. A la hora de realizar este proyecto, se encontraba en desarrollo Flocker, una solución desarrollada por ClusterHQ, que permite compartir los volúmenes de Docker a través de un cluster, que si bien es compatible con el planificador de Mesos, el proyecto se encontraba todavía en fases tempranas de desarrollo y los sistemas de almacenamiento que soporta quedaban fuera del ámbito de este trabajo. Por todo ello, dado que las máquinas se han desplegado en la nube pública de Azure, se decidió usar su servicio de almacenamiento de objetos para las canciones y otra máquina para desplegar MongoDB, y así mantener el modelo de datos original de la aplicación. La diferencia del almacenamiento de objetos con respecto a nivel de fichero es que el primero no tiene jerarquía para organizar los archivos, éstos se guardan como objetos (con sus metadatos) en un mismo espacio, sólo diferenciándose por un identificador único; esto implica, entre otras cosas, que se puede acceder a un fichero dado únicamente su ID, independientemente de la localización física de éste, facilitando pues la gestión y el desarrollo. El código del proyecto se ha modificado en los siguientes apartados: Las direcciones de la base de datos y los balanceadores de carga, así como sus puertos, estaban originalmente fijos. Se han configurado como variables de entorno para facilitar el descubrimiento del servicio y hacer transparente la aplicación al entorno de despliegue. La API REST se ha adaptado al almacenamiento en Azure en vez de en local. Estas modificaciones no suponen un cambio sustancial pero permiten separa la persistencia de las tareas ejecutadas por DC/OS, lo que facilita en gran medida su ejecución al ser totalmente sin estado, y además, implican tener los datos bajo un mayor control. Para la orquestación de contenedores, se va a usar el entorno Marathon, desarrollado también por Mesosphere. Éste se puede usar a través de una interfaz gráfica, la interfaz de línea de comandos (en lo que sigue CLI, por sus siglas en inglés) de DC/OS o con su API HTTP. Primero, se han publicado la imágenes de los contenedores que encapsulan la interfaz web y la api de la aplicación en el repositorio público DockerHub. Los despliegues en este entorno se describen mediante ficheros JSON en los que se detalla, entre otras opciones, la imagen del contenedor, los puertos a usar, 30 los recursos que debe ocupar en un nodo o las instrucciones de monitorización. Para el servicio de descubrimiento, DC/OS ofrece la posibilidad de asignar direcciones IP virtuales (VIP, por sus siglas en inglés) a tareas, que se comparten en todos los nodos. DC/OS lleva integrado un balanceador de carga a nivel TCP (el componente denominado Minuteman), que balancea entre las direcciones virtuales de las tareas y todas las instancias de éstas a lo largo del cluster. Esto es necesario por dos motivos: equilibrar la carga de los equipos con el fin de evitar un punto de único fallo mediante redundancia y evitar la contienda de direcciones al ejecutar las tareas en puertos aleatorios. Este balanceador de carga está basado en el trabajo de Michael Mitzenmacher, The Power of Two Choices in Randomized Load Balancing18 . A grandes rasgos, el algoritmo mantiene una media móvil exponencial de latencias para cada destino (backend), además de las caídas consecutivas. Si un destino no responde a una negociación en tres pasos (three way handshake) de forma consecutiva en un periodo inferior a 5 ms se considera caído. El algoritmo itera sobre los destinos disponibles en base a su histórico de fallos y escoge dos de forma aleatoria, de los cuales coge el de mejor métrica. Las direcciones virtuales sólo se pueden resolver dentro del cluster, por ello, para implementar la interfaz pública de la aplicación, esto es el balanceador de carga de la interfaz web, usaremos un paquete de DC/OS denominado marathon-lb, un balanceador basado en HAProxy y adaptado por Mesosphere. En este caso, equilibra la carga de todas instancias de las tareas ejecutadas por el entorno Marathon por sus etiquetas, y permite además, definir como punto de entrada múltiples hosts virtuales definidos por sus nombres completos de dominio (FQDN, por sus siglas en inglés), en nuestro caso, la interfaz pública del balanceador de Azure para los agentes. Por motivos de seguridad, todas las tareas se ejecutan en los agentes privados, es decir, los que son exclusivamente accesibles desde la red interna. Por su parte, marathon-lb se ejecuta en el agente público, que cuenta con IP pública y los puertos 80 (HTTP) y 8080 abiertos, de forma que la aplicación sea accesible desde Internet. Esto es posible debido a que Apache Mesos permite reservar recursos mediante roles asignados a nodos para un uso específico. De esta forma, la arquitectura vista desde la aplicación quedaría como en la figura 19. 18 https://www.eecs.harvard.edu/~michaelm/postscripts/tpds2001.pdf 31 Figura 19: Arquitectura de la aplicación web en DC/OS Ejecución A la hora de desplegar la aplicación, DC/OS puede gestionarse mediante una interfaz gráfica o una interfaz de línea de comandos. La primera se accede a través de un navegador web en el puerto 80 (HTTP) y permite instalar los entornos disponibles, observar el estado de los nodos y las tareas que se están ejecutando y los ficheros de registros que éstas generan. La CLI permite el control desde un nodo o una máquina remota (suponiendo que los maestros tienen IP pública y el puerto 80 abierto), ya que DC/OS tiene un sistema de autorización que permite tener una interfaz pública con ciertas garantías de seguridad. Por su parte, cada entorno de trabajo puede ser controlado por la CLI, pero además, cuenta con sus propias interfaces. Marathon expone una API HTTP en el puerto 8080 de la dirección pública de los maestros del cluster, así como otra interfaz gráfica. Para desplegar un contenedor se podría usar la CLI: $ d c o s marathon app add < f i l e . j s o n > O la API HTTP: $ c u r l −X POST \ h t t p :// < ip_maestro >:8080/ v2 / apps \ −d @< f i l e . j s o n > \ −H " Content−type : a p p l i c a t i o n / j s o n " 32 6.1.2. Nomad La arquitectura de Nomad es más sencilla ya que solo requiere de un fichero ejecutable en todos los nodos para funcionar. Si DC/OS es la base de instalación de entornos de terceros, Nomad integra todas las funcionalidades básicas, esto es, gestor de recursos, planificador y ejecutor en los nodos cliente. Esta herramienta cuenta con un menor tiempo de desarrollo y, en el momento de escribir este documento, cuenta exclusivamente con los siguientes controladores en comparación con los entornos de DC/OS: Motor Docker, es decir, función de orquestación de contenedores. Ejecución de archivos binarios como comandos de Shell. Ejecución de aplicaciones Java. Virtualización de máquinas mediante tecnología QEMU. Todos ellos necesitan que la tecnología subyacente esté instalada en las máquinas clientes (Docker, Java, QEMU). Actualmente no permite el registro de controladores por parte de terceros, aunque está planificado en un futuro ofrecer una interfaz para su desarrollo. Nomad no cuenta con el servicio de descubrimiento, sin embargo, puede integrarse con la herramienta Consul, desarrollada por la misma empresa. Por otro lado, para el balanceo de carga, usaremos un contenedor Docker con HAProxy, una herramienta de código abierto que ofrece tanto servicios de proxy como de balanceador, y cuyos ficheros de configuración completaremos con el proyecto Consul Template19 . Consul Consul sigue la misma arquitectura que Nomad, es decir, un nodo servidor que orquesta un conjunto de máquinas clientes, y permite a los procesos que se ejecutan en los equipos definirlos como servicios, ofreciendo diversas características entorno a estos, de los cuales vamos a usar dos: Descubrimiento de servicio Las máquinas clientes publican en el catálogo de servicios las tareas en ejecución y Consul les asigna nombres de dominio accesibles por todos los miembros del cluster a través de la interfaz DNS incluida en esta herramienta. Consul se integra con Nomad de forma que todas las tareas que se ejecuten en la segunda son automáticamente publicados como servicios de la primera; de esta manera, no hace falta conocer la dirección de la máquina cliente donde se esté ejecutando el proceso, ya que se puede acceder a él a través de su nombre de dominio de forma transparente. Por ejemplo, si 19 [https://github.com/hashicorp/consul-template] 33 ejecutamos una tarea con ID web en el puerto 8080, se puede acceder a ella en la dirección web.service.consul:8080. Para que las direcciones propias de Consul las resuelva su propio DNS y no el que esté asignado por defecto en la máquina, usaremos la herramienta dnsmasq20 , que permite especificar la dirección de un servidor DNS para consultas de direcciones específicas. Monitorización Permite realizar comprobaciones del servicio y seguir su estado. Aprovecharemos esta funcionalidad tanto para definir el propio proceso de Nomad como servicio de Consul, como las tareas desplegadas. HAProxy + Consul Template HAProxy es una solución versátil de código abierto que ofrece soluciones de balanceo de carga y proxy. Existen otras herramientas en el mercado como NGINX o ldirectord, sin embargo, HAProxy suponía una solución sencilla de configurar para mostrar el caso de uso. El uso de estas herramientas se debe a dos motivos: para que no exista contienda con respecto a los puertos de los clientes usados por las tareas, éstos se van a asignar de forma dinámica, lo que en principio implicaría que la aplicación debería realizar consultas DNS de tipo SRV (que incluye puertos) a la interfaz de Consul; y balancear la carga entre tareas por redundancia y capacidad. Como la dirección IP y puerto son variables, cada vez que las tareas se actualicen o se reasignen es necesario volver a configurar HAProxy de forma manual. Por ello, HashiCorp ha desarrollado un programa, denominado Consul Template, que realiza peticiones sucesivas a la interfaz HTTP de Consul de las direcciones físicas de un servicio y reinicia automáticamente el proceso de HAProxy. Así, definiendo estas tareas como servicios Consul, podremos tanto monitorizarlas, como escalar las tareas dinámicamente sin necesidad de cambiar el balanceador. A partir del contenedor Docker oficial de HAProxy, se ha desarrollado otro con la configuración básica y con Consul Template para desplegarlo como una tarea en Nomad. Despliegue Se ha usado el mismo código que en el apartado anterior, con la persistencia en el servicio de almacenamiento de Azure. Desde la perspectiva del hardware, se implementará la misma infraestructura que en el caso de DC/OS (figura 18), estos es, definiremos dos tipos de máquinas clientes: un agente que se conectará con el balanceador de carga con nombre de dominio público y donde se desplegará el balanceador de carga de la vista web, y agentes privados, no accesibles desde fuera del cluster y donde se ejecutarán el resto de tareas en la red interna. La principal diferencia radica en las tareas que ejecutan HAproxy y Consul Template que sustituye a las direcciones IP virtuales que ofrece DC/OS. 20 http://www.thekelleys.org.uk/dnsmasq/doc.html 34 Figura 20: Despliegue en Azure de Nomad+Consul Cabe matizar que los balanceadores basados en HAProxy se implementan por necesidad de la aplicación para el descubrimiento del servicio, a diferencia de los de Azure, que se implementan por motivos de seguridad y escalabilidad del cluster en sí. Configuración Nomad Los ficheros de configuración de las máquinas máster y cliente son similares y comparten la mayoría de las opciones, como por ejemplo el nombre del nodo o la interfaz de red donde escucha Nomad las peticiones. Sus opciones son, en general, auto-explicativas, sin embargo, existen dos detalles que matizar: El proceso de Nomad escucha las peticiones tanto de los protocolos de consenso como del usuario a través de una interfaz de red que se debe indicar en el fichero de configuración. En el caso de los clientes se deben indicar las direcciones de los servidores del cluster, sin embargo, se trata de un sistema dinámico en el que los nodos pueden sufrir errores y cambiar de dirección. Por ello, se ha definido Nomad como un servicio de Consul y así poder definir la dirección de los servidores como un nombre de dominio, no por su dirección física, que el servidor DNS de Consul se encargará de resolver. Por defecto, Nomad usa los siguientes puertos: API HTTP: 4646. Peticiones HTTP y recepción de órdenes mediante la línea de comandos. RPC: 4647. Protocolo de consenso entre los nodos del cluster. Serf: 4648. Protocolo de gossip entre los servidores de los centros de datos gobernados por Nomad. 35 Los dos últimos deben ser interfaces alcanzables por otros nodos, sin embargo, la API HTTP, por motivos de seguridad, debería ser local, ya que en caso contrario, cualquier persona con acceso a ella tiene el control sobre la herramienta. Ésta solo debería estar accesible en un servidor o gestionarlo mediante una terminal SSH, por ejemplo. En este trabajo, al ser una prueba de concepto, se ha abierto en todos los nodos. Trabajos de Nomad Las tareas se detallan en ficheros con formato HashiCorp Configuration Language, un derivado del formato JSON creado por la empresa que le da nombre, compatible con éste, y que permite comentarios. En estos ficheros se puede definir: La región y el centro de datos donde se ejecutará (Nomad permite la gestión de centros de datos geográficamente distribuidos en regiones). La política de actualización de la tarea. Grupo de tareas, esto es que se ejecutarán en el mismo nodo. El número de grupos a ejecutar/escalar, así como los límite que deben cumplir los nodos asignados. La política de reinicio ante fallo o error. Tareas. El controlador, su configuración, los parámetros del servicio asociado a registrar en Consul, así como los recursos que consume (puertos, memoria). En nuestro caso, usamos sobre todo el controlador Docker, esto eso, orquestación de contenedores en los nodos clientes y tres de sus opciones: Imagen del contenedor Se han subido todas las imágenes del proyecto a Docker Hub, donde por defecto se busca la imagen. Puertos Los puertos a usar por el contenedor, que pueden ser estáticos, asignados por el usuario o dinámicos, siendo Nomad el que se encarga de mapear un puerto libre del nodo cliente al expuesto por el contenedor. Servidores DNS Como usamos la interfaz DNS de Consul como descubrimiento de servicio, se debe configurar el contenedor para que use cualquier nodo del cluster como servidor DNS. Configuración Consul Al ser desarrolladas por la misma empresa, los ficheros de configuración de Consul y Nomad comparten muchas opciones. Consul también acepta peticiones a través de una interfaz de red, siendo los puertos usados por defecto: 36 RPC: 8300, 8400. Maneja la peticiones del resto de nodos y usuarios. Serf: 8301, 8302. Protocolo gossip. HTTP API: 8500. HTTPS API: Desactivada por defecto. Interfaz DNS: 8600. Se debe asignar a los protocolos internos del cluster, esto es RPC y Serf, una interfaz alcanzable por los nodos, y por el contrario,asignar a los dos últimos a la interfaz de loopback por motivos de seguridad. Cabe destacar, que Consul también cuenta con una interfaz gráfica que permite ver el estado de los equipos y los servicios registrados, y que se encuentra en el mismo puerto que la API HTTP, en la dirección http://IP_EQUIPO:8500/ui. Ejecución Tanto Nomad como Consul requieren de la ejecución de un fichero en todos los nodos integrantes del cluster. Como prueba de concepto se ha decidido usar dos servidores para ambos, aunque cabe matizar que es un número ineficiente ya que la caída de uno de ellos supondría la pérdida del cuórum y, por tanto, del consenso del cluster. En primer lugar, se arrancan los servidores, que son los encargados de ejecutar el protocolo de consenso y gestionar el cluster, y a continuación los clientes, que no tienen prácticamente estado y dependen de los servidores. En el caso de Consul, se debe indicar el directorio donde se guardan los ficheros que describen los servicios así como el archivo que especifica el resto de las opciones: 1. Se inicia el primer servidor en uno de los equipos: $ consul agent \ −c o n f i g −d i r / e t c / c o n s u l . d/ s e r v i c e s \ −c o n f i g − f i l e c o n s u l _ s e r v e r . j s o n 2. Los siguientes equipos deben unirse al anterior, por lo que añadimos el argumento join con la dirección del primer servidor. Para el caso de otros servidores: $ consul agent \ −c o n f i g −d i r / e t c / c o n s u l . d/ s e r v i c e s \ −c o n f i g − f i l e c o n s u l _ s e r v e r . j s o n \ −j o i n <I P _ s e r v i d o r 1 > 37 Una vez los servidores han alcanzado el consenso y elegido un líder, en los clientes: $ consul agent \ −c o n f i g −d i r / e t c / c o n s u l . d/ s e r v i c e s \ −c o n f i g − f i l e c o n s u l _ c l i e n t . j s o n \ −j o i n <I P _ c u a l q u i e r S e r v i d o r > El proceso para iniciar Nomad es igual y los comandos similares, sin embargo, ya no es necesario indicar una dirección IP fija en los equipos sino el nombre de dominio del servicio de Nomad registrado por Consul. En el primer servidor: $ nomad a g e n t \ −c o n f i g nomad_server . j s o n Y el resto de equipos (con su fichero de configuración correspondiente): $ nomad a g e n t \ −c o n f i g nomad_server . j s o n \ −j o i n nomad . s e r v i c e . c o n s u l Por último, para desplegar la aplicación web, se han escrito tres ficheros que detallan las tareas de la interfaz web, API y los balanceadores de carga. Mediante la CLI: $ nomad run \ −a d d r e s s=h t t p :// < i p _ c l u s t e r >:4646 \ < f i l e . hcl> O mediante la API HTTP de Nomad: $ c u r l −X POST \ −d @< f i l e . h c l > h t t p :// < i p _ c l u s t e r >:4646/ j o b/<job_name> Ansible Como se puede comprobar, con el aumento del número de equipos pasa a ser inviable manejar todos los nodos a través de terminal. Además, como se ha comentado con anterioridad, Nomad requiere que en los nodos clientes estén instalados las herramientas que soporten las tareas, por ejemplo, el motor de Docker. Por ello, para facilitar tanto el arranque como la instalación de las dependencias, vamos a usar Ansible, una herramienta de código abierto, desarrollada en Python, que permite gestionar configuraciones, aprovisionar recursos, despliegue de aplicaciones de forma automática. A grandes rasgos, esta herramienta funciona mediante ficheros en formato YAML, denominados play-books, que describen un conjunto de pasos a ejecutar en una lista de equipos remotos. Estos pasos son ejecutados por módulos independientes a través de SSH, es decir, en cualquier ordenador con conexión a los 38 hosts, dado su contraseña o clave pública, puede arrancar el script y realizaría los pasos de forma remota, gestionando el cluster desde un solo equipo. Se han desarrollado guiones para lo siguiente: Descarga de los binarios de Nomad y Consul en todos los nodos, copia de los ficheros de configuración básicos y modificarlos de acuerdo a cada nodo (nombre del equipo, dirección IP). Instalación de las dependencias. Arranque de Nomad y Consul. Ansible extiende su funcionalidad a través de módulos independientes que permiten, por ejemplo, instalar paquetes mediante herramientas de gestión de paquetes (APT, yum), aprovisionar automáticamente máquinas virtuales de Amazon EC2,. . . Algunas opciones de los ficheros de configuración de Nomad y Consul son dependientes del nodo particular, por ejemplo, la interfaz de red. Para este trabajo, se ha realizado un módulo para modificar los ficheros de configuración de forma automática. En el repositorio del proyecto se encuentra una carpeta donde se encuentran todos los ficheros necesarios; para desplegar un cluster totalmente funcional, solo requiere de una línea de terminal con Ansible: $ a n s i b l e −playbook \ −i hosts \ −k <ssh_pass> \ −u <node_user> \ s i t e . yml 39 6.2. Servicio de integración continua Se ha implementado un sistema de integración continua que permite ejecutar tareas de compilación y pruebas de forma distribuida, aumentando así el rendimiento de los equipos. En primer lugar se detallará los motivos por los que puede resultar beneficioso para las empresas una implementación de este tipo a lo que seguirá los detalles del despliegue. 6.2.1. DevOps Metodología que defiende la comunicación y colaboración entre desarrolladores de software y los profesionales de operaciones a lo largo de todo el ciclo de vida de una aplicación. Está muy relacionado con el desarrollo ágil de software, esto es, un enfoque para los proyectos que defiende el desarrollo iterativo e incremental, donde los requisitos y soluciones evolucionan con el tiempo según la necesidad del proyecto; DevOps extiende esta filosofía a todas los componentes de un servicio, incluyendo sistemas y operaciones. Se trata de un concepto que cada organización o empresa adapta a sus propias necesidades y procesos de negocio; en este proyecto nos vamos a centrar en la integración continua, una práctica fundamental tanto del desarrollo ágil como de esta filosofía. 6.2.2. Integración Continua Se define como una práctica de desarrollo software donde los miembros del equipo ponen en común su trabajo frecuentemente, al menos una vez al día21 . Cada integración se verifica con una compilación automática, que incluye la ejecución de pruebas para detectar errores de integración tan pronto como sea posible. Desde el punto de vista operativo, esto supone automatizar la configuración de equipos o el despliegue de máquinas virtuales donde compilar el proyecto y ejecutar las pruebas, y posteriormente, eliminarlas. Este flujo de trabajo se ve beneficiado en entornos distribuidos ya que el objetivo del desarrollador es comprobar el resultado de las pruebas rápidamente, sin preocuparse del despliegue o los propios equipos. Para esta prueba de concepto, vamos a usar Jenkins, un servidor de integración continua escrito en Java, que nos permite definir trabajos que contendrán la descripción tanto del entorno como su ejecución. Este sigue una estructura maestro-esclavo muy similar al de los gestores de clusters usados en este proyecto: el maestro contiene toda la lógica del servicio, 21 http://martinfowler.com/articles/continuousIntegration.html 40 trabajos, autenticación,. . . y los esclavos son los encargados de la ejecución en sí. Jenkins tiene varias vías para aprovisionar los últimos: Mediante SSH. Interfaz gráfica. Desarrollar un script propio. Ejecución de un fichero java. La ventaja de usar planificadores es que el despliegue de esclavos es dinámico, es decir, no tener una máquina específicamente configurada para ello: DC/OS y Nomad se encargarán de configurar estos despliegues en sus máquinas y posteriormente eliminarlos. Para ello, se ha usado la última opción, definiendo tareas que descarguen el fichero java. Con todo ello, se consigue un entorno de integración continua eficiente, que además permite la ejecución de otros servicios de forma independiente. Jenkins permite la creación de plugins que extienden sus funcionalidades. Tanto Nomad22 como Apache Mesos cuentan con uno que permite su integración. Para esta prueba se va a usar el mismo proyecto que para el caso de uso de orquestación de contenedores, la aplicación web, al que se le ha añadido un test para comprobar que se conecta correctamente a la base de datos mediante Mocha, un framework de Nodejs. Por otro lado, se añade el plugin de git, ya que el código se obtiene de GitHub, el repositorio remoto de control de versiones del proyecto. El proceso general de ejecución sería como sigue: 1. Se ejecuta el maestro de Jenkins como tarea Docker partiendo de la imagen oficial. 2. Al arrancar un trabajo, se manda una tarea a los planificadores que la asignarán a un nodo cliente. Esta tarea consiste en la descarga del fichero de configuración Java y arrancarlo, configurando el equipo como un cliente de Jenkins temporalmente. 3. Jenkins ejecuta el trabajo en el nuevo cliente, en este caso, iniciar la aplicación web, iniciar las pruebas y generar un informe. 4. Se elimina el cliente. A continuación, se detallan los matices de cada herramienta a la hora de implementar este servicio. 22 Desarrollado por Ivo Verberk: http://www.ivoverberk.nl/ 41 6.2.3. Jenkins con Nomad El plugin permite la ejecución del fichero Java mediante dos controladores: contenedores Docker y Java. En este proyecto nos hemos decantado por el primero ya que nos ahorra instalar la máquina virtual de java en todos los nodos cliente. Por ello, se ha construido un contenedor base con Java, para la ejecución del fichero de configuración, y Nodejs, para lanzar la aplicación web. El plugin se configura con la dirección IP del cluster y el contenedor que ejecuta el esclavo Jenkins. Por su parte, el trabajo en Jenkins se define con el repositorio en GitHub donde se aloja el código del proyecto a probar y los comandos a ejecutar, en este caso: npm update y npm test. 6.2.4. Jenkins con DC/OS En el caso de DC/OS, su sistema de paquetes incluye Jenkins, por lo que al instalarlo, ya se tiene la configuración de Mesos totalmente funcional. Sin embargo, para ejecutar la aplicación en particular y las pruebas, se requiere de Nodejs en los equipos esclavos, por ello, debemos añadir un plugin de Jenkins que permite instalar este entorno antes de ejecutar el trabajo. Una vez hecho esto, sólo queda definir la tarea igual que en el caso anterior. Cabe destacar que Mesosphere también ha desarrollado un plugin que permite hacer despliegues en Marathon, de tal manera que permitiría, con cada commit del código, compilar la imagen del contenedor Docker y desplegarla automáticamente, aunque en este proyecto no se ha hecho pruebas de esta funcionalidad. 42 7. Escalando la infraestructura Uno de los factores clave que se busca a la hora de implementar sistemas distribuidos es el poder escalar la infraestructura de forma más sencilla, esto es, detectar que las máquinas están alcanzando el límite de su capacidad y aumentar ésta, ya sea mejorando sus características técnicas o añadiendo más nodos al cluster. El código y todos los ficheros de configuración de esta sección también se pueden encontrar en el repositorio del proyecto en GitHub23 . 7.1. Diseño Microsoft Azure permite organizar los servicios cloud de forma lógica a través de grupos de recursos, y así, poder crear o eliminar éstos en conjunto para una aplicación determinada (por ejemplo, una aplicación web suele requerir de máquinas virtuales, bases de datos, almacenamiento,..). Además, dispone de la opción de crear plantillas en formato JSON que permite al desarrollador definir los recursos y su interrelación para desplegar de forma automática una infraestructura TI en la nube. Azure también ofrece la posibilidad de monitorizar el estado de las máquinas virtuales a través de extensiones, lo que permite configurar el escalado automático al alcanzar cierto límite definido por el operador. Ésta es, a priori, la forma en que debería implementarse hablando en términos de eficiencia, sin embargo, esta aproximación es totalmente dependiente de la plataforma, es decir, no se puede extrapolar a otro proveedor o sobre recursos propios sin realizar un nuevo diseño. En este proyecto, las tareas que son ejecutadas por estos equipos no tienen estado ya que todo lo relativo a la persistencia lo hemos asignado fuera del cluster, esto permite escalar la plataforma a través de otra aproximaciones. Las plantillas aceptan una serie de variables a indicar por el usuario, entre otras, los conjuntos de escala para definir los nodos aceptan una variable que define el número de máquinas que los componen. Por otro lado, Azure ofrece una API REST y kits de desarrollo software (SDK, por sus siglas en inglés) que permiten su despliegue de forma programática. Aprovechando estas facilidades, en este proyecto se va a aproximar la escalabilidad con el sucesivo despliegue de la infraestructura de forma automática: se monitorizan los equipos y si se detecta una máquina excesivamente cargada, se aumenta el número de equipos en la plantilla y se vuelve a desplegar. 23 https://github.com/AntonioAlfrz/Cloud-Orchestrators 43 En este proyecto se han diseñado las plantillas para desplegar la arquitectura necesaria tanto de Nomad como de DC/OS. En el caso de la primera, el despliegue es más descriptivo ya que incluye máquinas virtuales, grupos de seguridad, redes,. . . En el caso de DC/OS, Azure cuenta con un servicio específico para clusters gobernados por DC/OS denominado Azure Container Service, que incluye los componentes necesarios y la instalación ya realizada. 7.2. Implementación En primer lugar, para monitorizar el estado de los equipos se va a usar la herramienta Nagios, un sistema que permite controlar el estado del hardware y los servicios de un equipo. Se trata de una herramienta muy completa, de la que se va a usar su capacidad para ejecutar comandos (plugins) en los nodos para detectar picos de carga, generar alertas y ejecutar programas para estos eventos. Se ha desplegado una máquina virtual con esta herramienta en ambos sistemas y se ha instalado una extensión de Nagios (Nagios Remote Plugin Executor) en todos los nodos que permite ejecutar comprobaciones remotamente, en concreto para esta prueba de concepto, medir el nivel de saturación de la unidad central de procesamiento (CPU, por sus siglas del inglés). Cuando sucede un cambio de estado de una máquina, esto es, cuando este parámetro supera el límite definido por el operador, Nagios permite actuar en consecuencia ejecutando programas; por ello, se ha desarrollado un script que ejecuta lo siguiente: Un programa desarrollado en Python con el SDK de Azure que modifica las plantillas y despliega los recursos. Un guión de Ansible para instalar todos los componentes necesarios en las nuevas máquinas y arrancar de nuevo el cluster y las aplicaciones. 44 8. Resultados y conclusiones En este último apartado se da una visión global del proyecto, así como a las conclusiones más importantes a las que se ha llegado y posibles temas futuros de desarrollo. 8.1. Comparación Ambas herramientas ofrecen las funcionalidades para gestionar los recursos eficientemente, ofreciendo a los desarrolladores una plataforma donde desplegar sus aplicaciones de forma distribuida independientemente de los equipos físicos y el hardware que las soporten. DC/OS es una herramienta que en un comienzo fue privativa, pero cuyos responsables, la empresa Mesosphere, decidieron publicar una versión de código. Ésta nos permite gestionar un cluster de una forma sencilla y usable, además de complementarlo con otras herramientas, como el balanceador de carga integrado o la autenticación de usuarios; además, está basada en Apache Mesos, un proyecto de relativa madurez y con el soporte de la Apache Software Foundation. De forma resumida, DC/OS ofrece muchas posibilidades y servicios a cambio de una arquitectura e instalación más compleja. Por su parte, HashiCorp, con menor tiempo de desarrollo, ha conseguido una herramienta muy sencilla de desplegar, que además cumple con todas las funcionalidades básicas: ejecutando un simple binario en cada nodo se puede desplegar un gestor de clusters totalmente funcional. Sin embargo, no cuenta con todas las posibilidades de Mesos (Nomad cuenta con menos controladores que entornos posibles de Mesos), ni con los añadidos de DC/OS, lo que implica el uso de otras herramientas para complementar el servicio (Consul, HAProxy). De entre las dificultades encontradas al usar estas herramientas y desplegar aplicaciones sobre ellas se puede destacar la depuración: en ocasiones se desconoce si un error viene de la propia herramienta, de la aplicación desplegada o del equipo físico; si no se cuenta con un sistema de procesamiento de registro, uno se puede encontrar con múltiples terminales abiertas inspeccionando numerosos ficheros de registro buscando posibles errores. Además, no dejan de ser soluciones que, para usar eficientemente, se debe conocer parte de su funcionamiento y sintaxis a la hora de describir la tareas, lo que supone un esfuerzo añadido ya que cada una tiene sus particularidades y límites. 45 8.2. Conclusiones En una sociedad cada vez más digital, las empresas deben adaptarse a un mercado cuya demanda de contenido no deja de crecer. Las nuevas arquitecturas como microservicios, así como la gran cantidad de datos generada, implica que una mejor gestión de los recursos y la rapidez para desplegar o escalar soluciones, dando valor al cliente lo más rápido posible, es uno de los objetivos de todas las empresas de base tecnológica. Las ventajas que ofrecen los planificadores con aplicaciones distribuidas son numerosas, sin ir más lejos, empresas tan punteras como Google llevan más de 10 años orquestando contenedores24 . Por un lado, permiten aumentar el rendimiento de los equipos propios y por otro, implementar un servicio como plataforma para despliegues distribuidos sobre cualquier conjunto hardware; de esta forma, se provee un servicio similar al de la nube pública, pero con la principal diferencia de que se elimina la independencia con el proveedor (vendor lock-in), esto es, las aplicaciones no tienen limitaciones impuestas por éste tales como lenguaje de programación o herramientas, y permite despliegues híbridos entre recursos propios y la nube. 8.3. Objetivos conseguidos Implementación de los planificadores propuestos en la nube Se ha entendido y detallado el funcionamiento de estas herramientas, y se han implementado en el servicio de infraestructura de Microsoft Azure. Despliegue de aplicaciones y servicios distribuidos Servicios que se usan actualmente en la industria del desarrollo software, así como una aplicación web con una arquitectura moderna, han sido desplegados de forma distribuida en los equipos, cumpliendo con la funcionalidad esperada, además de consiguiendo una alta disponibilidad. Aproximación de arquitectura escalable Se ha hecho una aproximación de infraestructura escalable de forma que sea parcialmente extrapolable a otros proveedores. 24 http://www.nextplatform.com/2016/03/22/decade-container-control-google/ 46 8.4. Líneas de investigación Siguiendo con la materia de este proyecto, se presentan posibles líneas de investigación: Analizar el despliegue con estas herramientas de aplicaciones de Big Data y comparar la eficiencia con respecto a soluciones especializadas. Analizar el rendimiento de los algoritmos de planificación antes pruebas de estrés y situaciones de alta contienda. Comparar el uso de estas herramientas con las prácticas actuales de la industria o implementación en un sistema de producción real. 47 Referencias [1] L.A. Barroso y U. Hölzle. «The Datacenter as a Computer: An Introduction to the Design of Warehouse-Scale Machines». En: Morgan & Claypool Publishers (). [2] Systems Research Group – NetOS (University of Cambridge). The evolution of cluster scheduler architectures. 2016. url: https://www.cl.cam. ac.uk/research/srg/netos/camsas/blog/2016- 03- 09- schedulerarchitectures.html. [3] A. Das, I. Gupta y A. Motivala. SWIM: Scalable Weakly-consistent Infectionstyle Process Group Membership Protocol. Inf. téc. Dept. of Computer Science, Cornell University. url: https : / / www . cs . cornell . edu / ~asdas/research/dsn02-swim.pdf. [4] D. Dubhashi y A. Das. Mastering Mesos. PACKT Publishing, mayo de 2016. [5] The Apache Software Foundation. Apache Mesos documentation. url: https://mesos.apache.org/. [6] David Greenberg. Building Applications on Mesos. O’Reilly Media, 2016. [7] Armand Grillet. Comparison of Container Schedulers. Inf. téc. Technische Universität Berlin. [8] HashiCorp. Consul documentation. url: https://www.consul.io/. [9] HashiCorp. Nomad documentation. url: https://dcos.io/. [10] Dan C Marinescu. Cloud computing : theory and practice. Morgan Kaufmann, 2013. [11] Mesosphere. DC/OS documentation. url: https://www.nomadproject. io/. [12] Microsoft. Azure documentation. url: https://azure.microsoft.com/ es-es/documentation/. [13] D. Ongaro y J. Ousterhout. In Search of an Understandable Consensus Algorithm. Inf. téc. Stanford University. url: https://raft.github.io/ raft.pdf. [14] Fei Teng. «Ressource allocation and schelduling models for cloud computing». Tesis de mtría. Ecole Centrale Paris, 2011. [15] A. Williams y col. Automation and Orchestration with Docker and Containers. A Comprehensive Overview of the Docker and Container Ecosystem 3. The New Stack, 2016. 48