Modelo para el desarrollo de la infraestructura guiado por pruebas empleando el paradigma de infraestructura como código
119
0
0
Texto completo
(2) El que suscribe, Lic. Enrique Carbonell Muela, hago constar que el trabajo titulado “Modelo para el desarrollo de la infraestructura guiado por pruebas empleando el paradigma de infraestructura como código” fue realizado en la Universidad Central “Marta Abreu” de Las Villas como parte de la culminación de los estudios de la especialidad de Máster en Ciencias de la Computación, autorizando a que el mismo sea utilizado por la institución, para los fines que estime conveniente, tanto de forma parcial como total y que además no podrá ser presentado en eventos ni publicado sin la autorización de la Universidad.. _________________ Firma del autor. Los abajo firmantes, certificamos que el presente trabajo ha sido realizado según acuerdos de la dirección de nuestro centro y el mismo cumple con los requisitos que debe tener un trabajo de esta envergadura referido a la temática señalada.. _____________________. _____________________. Firma del Tutor. Firma del Jefe del Laboratorio.
(3) RESUMEN En el proceso de desarrollo de software se han identificado como buenas prácticas el desarrollo guiado por pruebas y la aplicación de un enfoque de automatización que permita obtener en el menor tiempo posible un producto de software validado y documentado desde su concepción. En este trabajo se describen los beneficios de las Herramientas de Gestión de la Configuración y se recomienda la aplicación de un marco de selección de las mismas. Se propone un modelo para la construcción de proyectos de infraestructuras aplicando la Infraestructura como Código bajo un enfoque guiado por pruebas. Se introducen los conceptos y enfoques aplicados sobre proyectos de infraestructura definiendo un modelo genérico y aplicable a cualquier organización. Para su definición se modelaron y fueron refinando los procesos que intervienen en el desarrollo del proyecto de infraestructura y se declararon las actividad y entidades de datos que intervienen en los procesos. Se mostró como estos proyectos pueden ser versionados e integrados en un proceso de integración continua como cualquier proyecto de código, apoyado de tecnologías de sandboxing como Docker y Vagrant sobre entornos locales y el servidor Gitlab. Se valida el modelo aplicándolo a un caso de estudio de la empresa de desarrollo de software DATYS en la implementación de una solución informática a uno de sus clientes.. Palabras claves: Infraestructura como Código, desarrollo guiado por pruebas, Desarrollo Guiado por Comportamiento.
(4) ABSTRACT In the software development process, test driven development and the application of an automation approach have been identified as good practices in order to obtain a validated and documented software product from its conception in the shortest possible time. This work describes the benefits of Configuration Management Tools and recommends the application of a framework to select them. A model for the construction of infrastructures by applying the Infrastructure as Code with test-driven approach, is proposed. The research introduces the concepts and approaches applied to infrastructure projects, defining a generic model applicable to any organization. For its definition, the processes that intervene in the development of the infrastructure project were modeled and refined and the activity and data entities that intervene in the processes were declared. It showed how these projects can be versioned and integrated in a continuous integration process like any code project, supported by sandboxing technologies such as Docker and Vagrant on local environments and the Gitlab server. It is validated with a real case study applied in the software development company DATYS in the implementation of a IT solution to one of its clients.. Keywords: Infrastructure as Code, Test Driven Development, Behavior Driven Development..
(5) TABLA DE CONTENIDOS INTRODUCCIÓN ............................................................................................................. 1 1. CARACTERIZACIÓN DE LOS ENFOQUES DE DESARROLLO GUIADO POR PRUEBAS, ENCAPSULAMIENTO E INFRAESTRUCTURA COMO CÓDIGO ........ 7 1.1. Desarrollo guiado por pruebas ............................................................................ 7. 1.1.1 Documentación en el proceso ......................................................................... 15 1.2 Viabilización del desarrollo de software ................................................................ 21 1.2.1 Virtualización .................................................................................................. 25 1.2.2 Vagrant ............................................................................................................ 28 1.2.3 Docker ............................................................................................................. 30 1.3 Infraestructura como Código ................................................................................. 35 1.4 Conclusiones del Capítulo ..................................................................................... 41 2. MODELO PARA DESARROLLAR PROYECTOS DE INFRAESTRUCTURA ..... 43 2.1 Herramientas de gestión de la configuración ......................................................... 43 2.2 Categorías de requisitos ......................................................................................... 47 2.3 Notación para la representación de los procesos ................................................... 49 2.4 Características del modelo ..................................................................................... 49 2.5 Estructura del modelo ............................................................................................ 50 2.5.1 Definición del modelo de implementación de proyectos de infraestructura ... 51 2.5.2 Definición del proceso de implementación de proyectos de infraestructura .. 57 2.5.3 Definición del proceso de implementación de un componente de infraestructura .................................................................................................................................. 61 2.5.4 Definición del proceso de creación/modificación de código de infraestructura .................................................................................................................................. 63 2.6 Ejemplos de proyectos de componentes desarrollados guiado por pruebas .......... 65.
(6) 2.7 Conclusiones del Capítulo ..................................................................................... 77 3. CASO PRÁCTICO DE ESTUDIO .............................................................................. 79 3.1 Planteamiento del problema ................................................................................... 79 3.2 Requisitos ............................................................................................................... 81 Conclusiones del Capítulo ........................................................................................... 95 CONCLUSIONES ........................................................................................................... 96 RECOMENDACIONES .................................................................................................. 97 REFERENCIAS BIBLIOGRÁFICAS ............................................................................. 98 Anexo 1: Tabla de comparación de las CMT seleccionadas ......................................... 106 Anexo 2: Aval de aplicación del modelo en DATYS .................................................... 110.
(7) INTRODUCCIÓN Recientemente, en la industria de desarrollo de software, apareció el término de liberación continua como un concepto o método. El desarrollo tradicional del software está basado en la idea que los equipos pueden comenzar su desarrollo solo cuando todo el diseño del software está concluido y bien documentado, liberando el software para la entrega cuando todas las funcionalidades comprometidas han sido bien implementadas. Por otra parte, el desarrollo ágil apoya la idea que el desarrollo de software puede ser un proceso iterativo e incremental, donde los requerimientos y soluciones van apareciendo producto de la colaboración entre los miembros de los equipos de trabajo durante el proceso de desarrollo (Beck et al., 2001; Martin, 2003; Ambler, 2008; Rubin, 2013). Esto sugiere una planificación adaptativa de despliegue, una liberación evolutiva, así como lidiar con requerimientos rápidos y flexibles que respondan al cambio. La liberación continua, es un subconjunto del desarrollo ágil donde los equipos dedican esfuerzos para mantener el software desarrollado listo para la liberación en cualquier momento durante el proceso de desarrollo. Esto es diferente del desarrollo tradicional por el esfuerzo para crear un entregable terminado. Técnicas como las pruebas automáticas, la integración continua y el despliegue continuo permiten que el software sea desarrollado con una alta calidad, fácilmente ajustable y desplegado en los entornos de producción (Humble and Farley, 2010; Deng et al., 2013; Caum, 2014; Gomede, Silva and Barros, 2015), lo que trae como resultado, que los desarrolladores tengan la posibilidad de incorporar mejoras y corregir bugs de los clientes de una forma más rápida, fiable y repetible con bajos costos. En la actualidad, los servicios de software están pasando de los servicios locales a los servicios basados en la web. Este cambio le permite al software no estar restringido por la dependencia de una plataforma en particular y a su vez, el servicio se puede utilizar desde cualquier dispositivo con acceso a red. Esta transición trae como consecuencia que los servicios sean más difíciles de gestionar, consumiendo un mayor tiempo de los administradores de los sistemas. Con la centralización del software y la información en lugar de tenerlos localmente en cada dispositivo, la complejidad de un sistema aumenta considerablemente a medida que el 1.
(8) Introducción entorno se escala. Con los servicios centralizados, la carga de trabajo de los administradores de sistema aumenta; evidenciándose usualmente con la adición de un mayor trabajo para el administrador del sistema sin agregar recursos humanos, que usualmente son limitados. Los desafíos con los servicios web son los requisitos de tiempo de actividad y consistencia del rendimiento de los servicios. Los usuarios esperan servicios con calidad, los cuales deben estar disponibles las 24 horas del día durante toda la semana. Al centralizar el software, cualquier interrupción del servicio afecta a todos usuarios. Sin embargo, cualquier cambio en el software consume mucho tiempo en la planificación, pruebas en múltiples entornos hasta su aplicación en producción. Los usuarios esperan la liberación de nuevas características con regularidad y frecuencia, sin degradación en la calidad del servicio. En el contexto de entrega continua de nuevos productos y funcionalidades surge el DevOps (por sus siglas en inglés Develop and Operations) como un movimiento de desarrollo con enfoque en la automatización y liberación continua propiciado por la colaboración entre los involucrados en la liberación de software (Humble and Farley, 2010; Dyck, Penners and Lichter, 2015; de Kort, 2016; Jabbari et al., 2016; Rothenhaus et al., 2018). Adicionalmente a las tareas diarias de administración de sistemas y el mantenimiento de los servicios, el administrador tiene que liberar nuevas funcionalidades en el menor tiempo posible para atraer nuevos clientes y mantener los ya existentes. Los seres humanos no son capaces de trabajar día y noche, y es irrentable escalar los recursos humanos junto con los sistemas informáticos. Por lo tanto, la gestión de la liberación de versiones se ha convertido en una de las principales dificultades y a su vez en una solución para los administradores de sistemas que gestionan arquitectura de servicios de alta complejidad acoplados con requisitos extremos de tiempo de funcionamiento. La automatización es un enfoque común (Barrett et al., 2004) utilizado para desplegar fácil y rápidamente las actualizaciones de software. Anderson plantea que la automatización es valiosa, y se utiliza frecuentemente en el campo de la administración de sistemas (Anderson, 1994, 2006), y en entornos informáticos donde se precisa. 2.
(9) Introducción gestionar muchos recursos. A través de la automatización, se ahorran potencialmente recursos humanos mientras el número de servidores aumenta logrando limitar los errores humanos en las etapas críticas del despliegue del sistema. La escalabilidad, puede ser un efecto secundario deseado de la automatización. En el contexto de Cuba recién se comienzan a dar los primeros pasos para el establecimiento de la industria del software. Dentro de las empresas que están en esta carrera podemos encontrar a: DATYS, DESOFT, XETID, UCI, ATIS; todas ellas con una gran diversidad de productos reconocidos que cubren diferentes segmentos del mercado. Como resultado de intercambios previos con profesionales de estas instituciones (directivos, jefes de proyectos, administradores de sistemas y desarrolladores) se ha constatado que el área de infraestructura y despliegue es una de las más débiles, ya que presenta algunas de las deficiencias antes descritas que dieron lugar, en años recientes, el surgimiento de la infraestructura como código. Esto ha estado aparejado en muchos casos a la ausencia de los recursos necesarios (hardware, conectividad de calidad, acceso a servicios de nube pública o centros de datos) para trabajar, al menos, bajo entornos de virtualización. En la mayoría de las empresas con un mínimo de recursos se proveen los servicios de forma física y las que constan con más recursos tienen montados sus servicios empleando la virtualización. Ninguna de estas empresas hasta la fecha, emplean los servicios de computación en la nube pública para desplegar sus aplicaciones o servicios. Por otra parte, se pueden encontrar empresas fuera de la industria del software pero que por su nivel de operaciones constan con los recursos suficientes para montar entornos de virtualización en aras de satisfacer los requerimientos de servicios internos y externos, como es el caso de la empresa cubana de telecomunicaciones, ETECSA. En la mayoría de los casos se pudo constatar que no se conocía el concepto de infraestructura como código, y, por otra parte, aunque las empresas relacionadas con el desarrollo de software conocen de la existencia del desarrollo guiado por pruebas, generalmente este se aplica parcialmente o no se aplica, con la salvedad de algunas divisiones de DATYS. Finalmente, y como es de esperarse, ante esta situación no se encuentra ninguna empresa de las mencionadas, que esté aplicando el desarrollo de la infraestructura guiado por pruebas. 3.
(10) Introducción De lo anteriormente expuesto se deriva el problema de científico: Cómo combinar los enfoques de desarrollo guiado por pruebas con el paradigma de la Infraestructura como Código para obtener un modelo de trabajo bien definido en cuanto a actividades e información asociada, que genere proyectos de infraestructura para la gestión de las TI (Tecnologías de la Información). Para contribuir a la solución del problema científico antes plateado, se formuló la siguiente hipótesis general de investigación: Empleando las prácticas del desarrollo guiado por pruebas de conjunto con enfoques de automatización aplicados al paradigma de la Infraestructura como Código, se puede definir un modelo para el desarrollo de proyectos de infraestructura dedicados a la gestión de las TI. En conformidad con la hipótesis de investigación identificada, el objetivo general de la investigación consiste en: Proponer un modelo para el desarrollo de infraestructuras guiado por pruebas empleando el paradigma de “Infraestructura como Código”. El objeto de estudio de la presente investigación es el paradigma de la infraestructura como código. Este objetivo general fue desglosado en los objetivos específicos siguientes: 1. Combinar los enfoques de desarrollo guiado por pruebas, el encapsulamiento de código y la gestión de la configuración en proyectos de infraestructura. 2. Definir un modelo para la generación de proyectos de infraestructura utilizando una notación formal de representación de procesos. 3. Realizar un estudio de caso de aplicación del modelo anterior a modo de validación de la investigación.. 4.
(11) Introducción. Justificación de la Investigación Esta tesis tiene como novedad la definición formal de un modelo para la generación de proyectos de infraestructura que integra los enfoques del desarrollo guiado por pruebas, el encapsulamiento de código y la gestión de la configuración a fin de disminuir el tiempo y los recursos dedicados a la gestión de las TI que soportan los negocios. El valor práctico de la tesis radica en dotar a los desarrolladores de infraestructura de un modelo que los guía en la implementación de proyectos de infraestructura. Esta tesis posee valor metodológico, pues puede ser utilizada como material de consulta para la impartición de cursos de pregrado y postgrado relacionados con el desarrollo guiado por pruebas y la administración de sistemas en proyectos informáticos. En el desarrollo de la investigación se utilizaron varios métodos de investigación; dentro de los métodos teóricos podemos citar el histórico – lógico, analítico – sintético, hipotético – deductivo. El documento está estructurado en tres capítulos que se describen a continuación: En el Capítulo I se muestran los beneficios del enfoque de desarrollo guiado por pruebas, junto a la necesidad de crear especificaciones ejecutables que constituyan un documento de intercambio eficaz para desarrolladores y clientes. Se presentan las ventajas y deficiencias de las herramientas de encapsulación de código para agilizar el proceso de desarrollo de software. Se introducen aspectos fundamentales a tomar en cuenta para la aplicación de Infraestructura como Código en proyectos de infraestructura. En el Capítulo II se describen las herramientas de gestión de la configuración y se recomienda la aplicación de un marco de comparación para las mismas. Se define formalmente el modelo para el desarrollo de infraestructura guiado por pruebas empleando el paradigma de infraestructura como código. En el Capítulo III se describe un caso de estudio aplicando el modelo propuesto a modo de validación de la investigación.. 5.
(12) Introducción Por último, se presentan las conclusiones y las recomendaciones del trabajo, así como las referencias y bibliografía utilizadas. Además, se utilizan anexos que explican en detalle varios aspectos de los contenidos tratados.. 6.
(13) CAPÍTULO I CARACTERIZACIÓN DE LOS ENFOQUES DE DESARROLLO GUIADO POR PRUEBAS, ENCAPSULAMIENTO E INFRAESTRUCTURA COMO CÓDIGO.
(14) 1. CARACTERIZACIÓN DE LOS ENFOQUES DE DESARROLLO GUIADO. POR. PRUEBAS,. ENCAPSULAMIENTO. E. INFRAESTRUCTURA COMO CÓDIGO En este capítulo se muestran los beneficios del enfoque de desarrollo guiado por pruebas, junto a la necesidad de crear especificaciones ejecutables que constituyan un documento de intercambio eficaz para desarrolladores y clientes. Se presentan las ventajas y deficiencias de las herramientas más recientes para agilizar el proceso de desarrollo de software. Se introducen aspectos fundamentales a tomar en cuenta para la aplicación de Infraestructura como Código en proyectos de infraestructura. Finalizando con el arribo de las conclusiones sobre la importancia de establecer un modelo para el desarrollo de proyectos de infraestructura empleando un enfoque guiado por pruebas. 1.1 Desarrollo guiado por pruebas Alrededor del movimiento Ágil, se ha desarrollado la idea que es perfectamente posible escribir códigos de calidad, seguros, bien probados y de fácil mantenimiento sin perder la idea de conjunto. A los desarrolladores de software no se les contrata para escribir códigos, pero sí para ayudar a resolver los problemas de los clientes. En la práctica, los problemas que resuelven casi siempre pueden caer en una de estas tres categorías: . Ayudar a los clientes a hacer más dinero.. . Ayudar a los clientes a gastar menos dinero.. . Ayudar a los clientes a proteger el dinero que ya tienen.. Ken Beck en su libro (Beck and Andres, 2004) y más tarde, José Joskowicz resume estas prácticas o reglas excelentemente en su reporte de introducción a la Programación Extrema (Joskowicz, 2008) . Algunas de estas prácticas pueden ser introducidas como buenos hábitos y no requieren mucha tecnología para su implementación. Dentro de estas prácticas surgió el desarrollo guiado por pruebas (TDD: Test-Driven Development) permitiendo la creación de estructuras para el cambio inminente, aportando seguridad, códigos fáciles de mantener y advertencia de los efectos secundarios no deseados antes de la liberación de un código. Para los desarrolladores de proyectos de infraestructuras, la 7.
(15) Capítulo I práctica es tan difícil de introducirla como de implementarla, pero también promete un retorno de la inversión mayor. El desarrollo guiado por pruebas es un enfoque de desarrollo donde el desarrollador crea la prueba antes de adicionar el código de la funcionalidad que desea implementar y posteriormente pasa a la etapa de refactorización. De esta forma se acorta el lazo de retroalimentación y se provee confianza en la incorporación de pequeños incrementos de forma evolutiva. En el proceder, cuando escribimos el código de prueba, inmediatamente la ejecución de los mismos falla por la ausencia del código funcional, luego se procede a implementar la funcionalidad esperada y se repite el proceso de prueba de forma iterativa permitiendo la refactorización evolutiva del código en un ciclo conocido como “Red-Green-Refactor” que permite guiar el desarrollo del software de forma tal que la funcionalidad desarrollada quede probada desde su implementación (ver Figura 1). Por refactorización se entiende la aplicación de mejoras del código fuente que mejoran su diseño sin agregar nuevas funcionalidades.. Figura 1 Diagrama general del TDD (fuente: (Kumar and Bansal, 2013)). 8.
(16) Capítulo I El desarrollo aplicando TDD se implementa en el orden representado por la Figura 2 para unidades de funcionalidad de una aplicación (ejemplo: los métodos de una clase en Programación Orientada a Objetos) y quedando declarado en los siguientes pasos: 1. Adicionar la nueva prueba para la unidad de funcionalidad no implementada. 2. Ejecutar todas las pruebas previamente creadas comprobando que no fallen. La nueva prueba se mantiene fallando mientras no se implemente la funcionalidad. 3. Implementar la nueva unidad de funcionalidad. 4. Ejecutar todas las pruebas y verificar su ejecución satisfactoria. 5. Refactorizar el código 6. Comenzar desde el comienzo (paso 1). Figura 2 Flujo de trabajo aplicando TDD (fuente: (Kumar and Bansal, 2013)). Como resultado de la aplicación del TDD para el desarrollo de software tendremos varias baterías de pruebas por cada uno de los componentes de la aplicación permitiendo la 9.
(17) Capítulo I construcción iterativa e incremental del código junto a su batería de pruebas que operan como pruebas de regresión cada vez que se adiciona una funcionalidad. La refactorización del diseño se realiza con la certeza que si esta afecta algún componente de la aplicación los test fallarán y el problema será identificado rápidamente por dichas pruebas implementadas con anterioridad y operando como test de regresión. Sobre el TDD y su implementación podemos encontrar varios trabajos interesantes donde destaca el aporte de Ken Beck (Beck, 2003) introduciendo el tema mediante ejemplos concretos y patrones de pruebas a seguir. En un estudio sobre evidencia de aplicación del TDD en la academia (Desai, Janzen and Savage, 2008) se muestran algunas concepciones erróneas que suelen presentarse al aplicar el enfoque de pruebas y que por su importancia para la comprensión se enumeran a continuación: . TDD no es una técnica de pruebas, es un proceso.. . Las pruebas solo se terminan cuando la funcionalidad está completamente implementada, debido a que la declaración de las pruebas se entrelaza con el propio desarrollo de la funcionalidad.. . No se requiere una batería de pruebas de regresión que cubra el 100% de las funcionalidades. Debido al costo-beneficio no se recomienda la cobertura total del código de aplicación (ejemplo: en las interfaces de usuario que se modifican constantemente sin adicionar funcionalidad).. . Las pruebas unitarias constituyen una evidencia de especificación de diseño, pero no tienen que ser las únicas, sobre todo en sistemas complejos donde se deben apoyar las decisiones de diseño con diagramas de componentes, diagramas de interacción, casos de uso, etc.. . Desarrollar empleando pruebas unitarias no constituye una garantía que el producto implementado es de calidad; aún se requieren pruebas adicionales.. Dentro de las evidencias de aplicar el TDD (Desai, Janzen and Savage, 2008) se encuentran que se desarrollan habilidades analíticas y de comprensión que permiten desarrollar proyectos complejos incrementando la confianza sobre el código implementado. Al comenzar el desarrollo forzando a escribir la prueba, se guía al 10.
(18) Capítulo I implementador a separar la funcionalidad solicitada de la base de código necesaria para que la funcionalidad opere satisfactoriamente llevando a tomar mejores decisiones de diseño durante la implementación del sistema o, en otras palabras, escribir un código más limpio que funcione como se espera. Los estudios también muestran que luego de aplicar este enfoque se tiende a mejorar la calidad de código interno y a reducir la cantidad de problemas o defectos del sistema. Con respecto a la productividad no se ha logrado una uniformidad de criterio pues aún hay estudios que muestran un aumento y otros que no. En palabras de Randy Shoup en sus presentaciones sobre prácticas para adopción de DevOps en las organizaciones (Shoup, 2018) encontramos las interrogantes: ¿No tenemos tiempo para hacerlo mejor? Vs ¿Tenemos tiempo para hacerlo dos veces? en las que el experimentado profesional aborda la necesidad de producir el código correcto correctamente desde el principio aplicando en sus elementos el enfoque de TDD llevándonos a construir mejores códigos con procedimientos de detección de fallas en etapas tempranas del proceso. (Beck, 2003), define dos reglas básicas para el TDD: solo se debe escribir nueva funcionalidad luego que su test automatizado falle y se debe eliminar o mejorar todo el código que se encuentre (en la práctica actual se suele lidiar con la deuda técnica en el tiempo). Estas reglas generan en sus practicantes los siguientes comportamientos como resultados: -. Se diseña orgánicamente, con la retroalimentación constante en cada decisión.. -. Usted asume la responsabilidad de escribir sus propias pruebas para evitar el tiempo de espera en caso de que otra persona en otro equipo las escriba por usted.. -. Su entorno de desarrollo debe ofrecer una respuesta rápida ante pequeños cambios, es necesario que el tiempo de compilación y corrida de los test sea mínimo.. -. Su diseño debe garantizar una alta cohesión y bajo acoplamiento de componentes para facilitar el desarrollo de las pruebas y el mantenimiento del código y su evolución.. 11.
(19) Capítulo I -. Su diseño debe garantizar una alta cohesión y bajo acoplamiento de componentes para facilitar el desarrollo de las pruebas y el mantenimiento del código y su evolución.. En el caso de los desarrolladores las implicaciones son referentes a la necesidad de aprender a escribir pruebas unitarias de calidad. Según la experiencia de Ken Beck se puede definir como una prueba de calidad aquellas: -. Rápidas (configuración, ejecución, destrucción del escenario de prueba). -. Auto contenidas (pueden ejecutarse en cualquier orden). -. Emplean datos simples que facilitan la comprensión de la prueba.. -. Emplean datos reales en caso de ser requeridos Cubren un único aspecto de la funcionalidad global. Algunos autores ven el TDD como una práctica de programación, aunque el enfoque por el que se apuesta es el que lo define por su objetivo de especificar en lugar de validar (Martin, 2003). Visto de esta forma se prioriza el diseño antes de escribir el código funcional. Según (Ambler and Lines, 2012) existen dos niveles de TDD: 1- TDD. Donde el desarrollador codifica un solo test, en ocasiones referido al test unitario y luego implementa la funcionalidad que cumple con la prueba antes declarada. El objetivo final es la especificación detallada y el diseño ejecutable de la solución a medida que se va construyendo. 2- Desarrollo guiado por test de aceptación (en inglés: Acceptance TDD, ATDD): donde se escribe la prueba de aceptación para luego desarrollar el código funcional que cumple dichos test. El objetivo final es obtener una especificación bien detallada que sea ejecutable a medida que se va desarrollando el código. Usualmente este término es conocido como Desarrollo Guiado por Comportamiento (en inglés: Behavior Driven Development, BDD). El BDD se enfoca en el proceso de especificar escenarios del comportamiento del sistema, construyendo un espacio de entendimiento entre los equipos y los stakeholders. 12.
(20) Capítulo I El trabajo de (Wynne and Hellesoy, 2012) y referencias afines plantean que el BDD se construye sobre el TDD formalizando los buenos hábitos de los mejores practicantes del TDD. Sse trabaja de afuera hacia adentro, comenzando con un test de aceptación de usuario fallido que describe el comportamiento del sistema desde la perspectiva de cliente. Es responsabilidad de los equipos involucrados la declaración de los test de aceptación con ejemplos garantizándose su comprensión por todos los involucrados. La escritura de estos ejemplos incrementa la retroalimentación y ayuda en la construcción del producto correcto correctamente antes de comenzar a implementar. Para la descripción de los escenarios propuestos empleando BDD se recomienda la construcción de ejemplos y casos de prueba utilizando un lenguaje que garantice la compresión, amén de la experticia o áreas de conocimiento de los involucrados. Se puede emplear el lenguaje denominado Gherkin, que es el conjunto de reglas de sintaxis para la descripción de funcionalidades y escenarios como se muestra en la Figura 3.. Figura 3 Ejemplos de sintaxis Gherkin para describir escenarios (fuente: (Wynne and Hellesoy, 2012)). 13.
(21) Capítulo I En la Figura 4 se muestra el modelo ideal para el desarrollo de una nueva funcionalidad donde se entrelazan ambos niveles de pruebas. Primeramente, se escribiría un test de comportamiento y luego para implementar su funcionalidad se debe caer en el proceso de declaración de las pruebas unitarias y finalmente el código funcional que cumpla con la declaración de las pruebas unitarias y a su vez satisfagan el comportamiento general esperado por la aplicación.. Figura 4 Flujo de trabajo BDD + TDD (fuente: (Ambler and Lines, 2012)). 14.
(22) Capítulo I Muchos equipos pueden estar realizando TDD sin tener implementado el BDD lo cual no indica que su proceso sea errado, pues el poder aplicar ambos niveles implica habilidades de pruebas y diseño que se alcanzan con la práctica y mejora constante y que pueden no ser comunes entre los desarrolladores. He aquí el valor de los equipos multifuncionales que refiere Randy Shoup en sus conferencias donde el miembro del equipo especializado en QA aporta y socializa los conocimientos en este proceder. En estudios previos se evidencian resultados y los retos de la praxis del TDD y BDD desde diferentes enfoques y entornos de aplicación (Desai, Janzen and Savage, 2008; Ambler, 2010; Hammond and Umphress, 2012; Mahmood KhanIbrar and Arshad, 2012; Garousi and Zhi, 2013) y donde comúnmente se presentan algunas herramientas para la práctica (por ejemplo: JUnit, TestNG, RSpec, Cucumber). Es importante destacar que estas no son las únicas formas de validación de aplicaciones, sobre todo con énfasis en elementos para llevar la aplicación a producción donde debemos tomar en cuenta la relación entre aplicaciones y servicios de los que esta depende (datos), para lo cual usualmente es necesario implementar test de integración, carga y desempeño seguridad, entre otros. 1.1.1 Documentación en el proceso Aun cuando en el proceso productivo de software es usualmente requerida la documentación de las funcionalidades, los programadores en etapas posteriores se deben enfrentar al código y generalmente prefieren leer el código fuente para descifrar el comportamiento esperado. En este marco, la realización del test facilita la comprensión de las funcionalidades implementadas con los casos de prueba que constituyen un ejemplo ejecutable o como se le denomina en la comunidad: especificación ejecutable. Nótese que esta pasa a ser un elemento de apoyo a la documentación pero que no elimina la necesidad de documentación desde la perspectiva de usuario, administración, soporte, etc. El gremio de desarrolladores en los últimos tiempos, se ha enfocado en la construcción del producto en la forma correcta aplicando las mejores prácticas que garanticen la alta calidad. Pero, de acuerdo con (Adzic, 2011): “construir el producto correctamente no es equivalente a construir el producto correcto” (ver 15.
(23) Capítulo I Figura 5). Adicionalmente, John Ferguson (Smart, 2015) reafirma que para construir un producto exitoso se debe llevar de la mano ambos aspectos en el proceso productivo enfocándose en qué construir y cómo hacerlo eficazmente. Como se ilustra en la Figura 6 si se degrada el “como construimos” no diseñando e implementado correctamente, se construye un producto con problemas, poco comprensible, difícil de modificar y mantener. Por otra parte, si se le resta importancia al “que construimos” fallando en la comprensión de que características del negocio realmente son necesarias, se pasa a implementar un producto que no aporta valor al cliente final.. Figura 5 Construir el producto correcto Vs construir correctamente el producto (fuente: (Adzic, 2011)). Figura 6 Proyecto exitoso debe construirse correctamente el producto correcto (fuente: (Smart, 2015)). 16.
(24) Capítulo I Para construir el producto correcto se requiere usualmente de gran cantidad de documentación y fases de prueba que atentan contra los requerimientos de agilidad en la entrega y liberación de soluciones informáticas de la actualidad. Por esto se requiere una solución que garantice: (ver Figura 7) . Evitar la sobre especificación, que no es tolerante a los cambios de funcionalidades y que genera un gasto considerable de tiempo. . La compresión del funcionamiento del sistema y que su modificación sea sencilla.. . Validar la especificación funcional contra el funcionamiento del sistema.. . La documentación sea mínima y de fácil mantenimiento, permitiendo que sea generada en iteraciones cortas y que en todo momento se tenga la especificación funcional del sistema.. Figura 7 Elementos para obtener la documentación correcta en equipos ágiles (fuente: (Adzic, 2011)). La especificación mediante ejemplos: es un conjunto de patrones de procesos para facilitar el cambio en productos de software que garanticen que el producto entregado es el correcto, o en otras palabras entregar el producto correcto correctamente. Dentro de los principales elementos de la especificación mediante ejemplos se encuentran: (ver Figura 8). 17.
(25) Capítulo I -. Derivación del alcance de los objetivos: los clientes no tienen por qué saber de las especificidades técnicas de una solución, por lo que no se debe esperar que dentro de los requerimientos de un sistema se encuentren aspectos tecnológicos. Usualmente se parte de un análisis de los objetivos principales y se comienza a desglosar su alcance de forma tal que quede bien especificado qué se quiere lograr y el equipo llega a proponer soluciones efectivas.. -. Especificación colaborativa: cuando se comienza la especificación de una solución debe tenerse en cuenta el criterio de todos los miembros del equipo que implementarán la solución sin diferenciar el rol dentro del proyecto para evitar los efectos de las llamadas barreras departamentales. Cada miembro del equipo aportará con su experiencia valor a la solución contribuyendo en la detección temprana de posibles problemas y por ende re-trabajo en las funcionalidades.. -. Ilustración mediante ejemplos: debido a la riqueza y ambigüedad a la que puede llegar el lenguaje natural, la especificación debe llevarse a ejemplos principales y concretos que reflejen el objetivo y alcance de una funcionalidad. Estos ejemplos reflejan el comportamiento esperado del sistema. Al final, si el software cumple con todos los ejemplos claves declarados, estaremos verificando que se cumple con los acuerdos tomados por el equipo y pueden considerarse como un elemento que valida cuando hemos terminado una funcionalidad.. -. Refinamiento de la especificación: Los ejemplos claves deben ser concisos y útiles, eliminando posible información extra no requerida para la ejecución de pruebas y validaciones en general.. -. Automatizar la validación sin modificar las especificaciones: una vez que los miembros del equipo aprueban las especificaciones con sus ejemplos, estas se convierten en la meta técnica a alcanzar y se prosigue con la automatización de las pruebas que las respaldan en aras de eliminar o reducir la validación manual ante cada escenario de ejemplo descrito.. -. Validación frecuente: con la comprobación frecuente de las especificaciones ejecutables, se puede descubrir rápidamente cualquier diferencia entre el sistema y la especificación. Debido a que la especificación ejecutable es fácil de comprender y generalmente está escrita en un lenguaje cercano al natural, 18.
(26) Capítulo I constituye un elemento a presentar en las discusiones con el cliente y su modificación reflejará cómo manejar un cambio recomendado. -. Evolucionar el sistema de documentación: el trabajo no se termina con la validación de las especificaciones ejecutables, se debe garantizar que estas especificaciones estén bien organizadas y son consistentes con el sistema. Debido a que en la vida real las necesidades de un cliente no se mantienen constantes en el tiempo y todo sistema debe adaptarse al cambio, las especificaciones que respaldan esos cambios también deben adicionarse o modificarse, convirtiéndose en un sistema de documentación viviente.. Un sistema de documentación viviente constituye una fuente fidedigna de información sobre las funcionalidades de un sistema alineadas en todo momento con la implementación. Este sistema de documentación puede ser empleado por todos los miembros del equipo, personal de soporte y cliente final para la comprensión, validación y demás análisis que se pueden realizar sobre las funcionalidades de un sistema.. Figura 8 Elementos principales de la Especificación por Ejemplos (fuente: (Adzic, 2011)). Los aportes fundamentales de la especificación mediante ejemplos son: 19.
(27) Capítulo I -. Se unifican los requerimientos funcionales, las especificaciones, y las pruebas de aceptación.. -. El resultado final es la documentación viviente capaz de explicar qué hace el sistema en un lenguaje comprensible para programadores y clientes.. -. Diferentes equipos pueden emplear diferentes prácticas para la implementación del proceso de especificación.. -. Permite construir una buena documentación de forma incremental.. -. La documentación viviente es un artefacto tan importante como el código en sí.. -. Enfocarse en la creación de la documentación del sistema contribuye a evitar problemas de mantenimiento y errores en el futuro.. Uno de los enfoques para aplicar durante la especificación mediante ejemplos es el desarrollo guiado por pruebas abordado en el epígrafe anterior. Conclusiones parciales De forma general se puede ver que el TDD creció y evolucionó focalizándose específicamente en cómo ayudar a los desarrolladores a escribir el código que verdaderamente tiene valor. Tal y como TDD es una práctica enormemente efectiva en la mejora de la calidad del software, el BDD aumenta el éxito con que el software se ajusta a las necesidades del negocio. El cambio entre TDD y BDD es sutil pero significativo. En lugar de pensar en términos de verificación de unidades de código, se pasa a pensar en las especificaciones de cómo debería comportarse el código o qué debería hacer. La tarea de los desarrolladores entonces es escribir las especificaciones del comportamiento del sistema, y debe ser ejecutada como código para verificar su comportamiento. Es importante destacar que BDD puede ser interpretado como una conversación entre las partes interesadas. El punto completo del BDD es asegurar que los objetivos reales del negocio provistos por los stakeholders son los entregados en la liberación del software. Si los stakeholders no están involucrados, si no se realizan discusiones de trabajo, entonces no se está en presencia de BDD. Se puede decir que los principales beneficios que aporta. 20.
(28) Capítulo I BDD son: reducir el riesgo de funcionalidades no deseadas e imponer la necesidad de diseñar en el proceso, contribuyendo en la construcción de los productos correctamente. La especificación mediante ejemplos es un recurso valioso a tomar en cuenta en el desarrollo de cualquier solución informática. Su implementación se considera un flujo que inicia con la especificación de ejemplos claros y concretos que reflejen requerimientos en sí, traducidos en funcionalidades declaradas a implementar y validar desde los propios test de aceptación y test unitarios. Todo esto da lugar al ciclo de declaración, implementación, validación, y mejora, que se ha tratado en este epígrafe bajo la denominación de desarrollo guiado por pruebas. 1.2 Viabilización del desarrollo de software El desarrollo de software usualmente es un proceso complejo que comprende desde el levantamiento de requisitos hasta la puesta en producción del producto. Con el paso del tiempo, diferentes metodologías y prácticas de desarrollo se han propuesto acorde a los diferentes escenarios que puede enfrentar la industria: RUP, SCRUM, Kanban, etc. Han surgido un grupo de recomendaciones para la construcción del producto correcto correctamente mencionado con anterioridad tomando en cuenta la agilidad requerida y la cooperación entre los involucrados: Manifiesto Ágil (Fowler and Highsmith, 2001) y el término más reciente DevOps, enfocado en eliminar las barreras departamentales entre los desarrolladores y los especialistas de operaciones en post de lograr la liberación continua de aplicaciones o servicios (Hüttermann, 2012; Loukides, 2012; Peuraniemi, 2014; Duffy, 2015; Perera, Silva and Perera, 2018). En cualquier variante, el desarrollo de software va aparejado de una forma u otra con la medición de la calidad, que comprende desde el análisis del código desarrollado (métricas: complejidad ciclomática, repetición de código, etc.) hasta la satisfacción del cliente con el producto entregado. En los últimos años se ha generalizado el desarrollo de sistemas distribuidos y aplicaciones web, adicionando complejidad al proceso por la variedad de dependencias, requerimientos y componentes que se interrelacionan en estos sistemas. Es considerable 21.
(29) Capítulo I el tiempo necesario para la puesta a punto del entorno de desarrollo y su transición hasta producción. Si se tiene en cuenta que es necesario cambiar el entorno para el desarrollo de nuevos productos, el tiempo de preparación de los mismos aumenta considerablemente. Los problemas más comunes durante el desarrollo de software son los siguientes: . El desarrollo en entornos que difieren de las condiciones reales de producción, puede provocar que las pruebas locales resulten satisfactorias y sin embargo se presentan fallas en producción (por ejemplo, por la ausencia de una biblioteca nativa en el sistema operativo de producción).. . Se complejiza la preparación de recursos para las pruebas automatizadas (test unitario, test de integración, test de carga).. . Un bug detectado en producción es difícil de recrear en el entorno de desarrollo.. Al mismo tiempo que la industria del software ganaba seguidores y años, por la línea de la administración de sistemas surgía la idea de aprovechar los recursos de hardware para simular en un mismo dispositivo la instalación de diferentes sistemas operativos (OS) o servicios, dando lugar a la virtualización. Desde sus inicios los desarrolladores vieron las fortalezas de la virtualización para aislar sus entornos de desarrollo, incluyendo así las herramientas y dependencias necesarias para construir un producto determinado. En el área informática es usual el termino Sandbox (en español: caja de arena) asociado a la ejecución de procesos de forma aislada o encapsulada, como algunos autores prefieren referir, reservando recursos como: CPU, RAM, disco y red. Inicialmente su uso se enmarcaba en la evaluación de seguridad de programas, pero la idea se fue generalizando al desarrollo de software como práctica para recrear el entorno de desarrollo, prueba y finalmente su despliegue en producción (Ambler and J. Sadalage, 2006; Ambler, 2008; Grattafiori, 2016). La virtualización puede ser considerada una variante para lograr el sandboxing. Como se muestra en (Peacock, 2015), Vagrant es una poderosa herramienta para la creación, gestión y trabajo con entornos de desarrollo virtualizados para los proyectos. 22.
(30) Capítulo I Con la creación de un entorno virtualizado para cada proyecto, sus dependencias y requerimientos quedan aislados y no son interferidos por otros componentes de software que pudiéramos tener en el host físico. Los desarrolladores pueden disponer del mismo entorno de desarrollo en menor tiempo, y de esta forma minimizar la complejidad de la configuración. Existen múltiples trabajos que muestran la diversidad de escenarios donde se aplica Vagrant (Zenzinov, 2013; Bhattacharya, Paul and Jaiswal, 2014; Piccolo, 2014; Berger et al., 2015; Gomede, Silva and Barros, 2015; Martinez Romero, 2015; Stillwell and Coutinho, 2015; Vujović et al., 2015) los cuales abarcan, desde el ámbito educativo para preparar recursos de laboratorios, hasta el científico para recrear el trabajo de un investigador, lo cual muestra la aceptación que ha tenido por la comunidad. Inclusive, muchos de los proveedores de soluciones de software en su documentación o recursos de prueba gratuita distribuyen recursos con Vagrant para facilitar el mantenimiento y gestión de los componentes a desplegar, para ilustrar las funcionalidades de sus productos. Por esta razón, en el artículo publicado para la determinación de características para la evaluación de tecnologías de software, se recomienda tener en cuenta la presencia de este tipo de herramientas (Carbonell and García, 2016). Con Vagrant ya se habían dado pasos en la automatización y socialización del aprovisionamiento en desarrollo, pero para la producción continuaba siendo costoso (almacenamiento y tiempo de construcción) mantener salvas de las máquinas virtuales probadas en desarrollo para su empleo en producción. En aras de mejorar el aprovechamiento de los recursos surgen las tecnologías de contenedores que proveen una forma sencilla de virtualización que permite aislar procesos y recursos sin la necesidad de proporcionar mecanismos de interpretación de instrucciones y otras complejidades de la virtualización (Helsley, 2009). Dentro de las tecnologías de contenedores más recientes y adoptadas se encuentra LXC (Linux Containers - LXC Introduction, no date; Beda, 2014; Clark, 2014) (Linux Containers). Su principal meta es crear un entorno lo más cercano posible a la instalación estándar de Linux, pero sin la necesidad de tener un kernel independiente. 23.
(31) Capítulo I Posterior a la aparición de los contenedores de Linux, surge Docker en el 2013 como un proyecto de código abierto que aumento las posibilidades para el desarrollo de software, el cual mitigó varias de las problemáticas de la virtualización en la industria de software y facilito el desarrollo de aplicaciones haciendo el sandboxing más ligero. Docker es una herramienta que permite empaquetar una aplicación con todas las dependencias en una unidad estandarizada para el desarrollo y ejecución de software. El crecimiento de la comunidad de Docker fue explosivo y en la actualidad es empleado por una gran variedad de compañías como Microsoft, RedHat, LinkedIn, eBay. Muchas de las compañías que ofrecen plataforma como servicio (PaaS) incluyen el soporte a los contenedores de Docker. El empleo de Docker se ha extendido también a otros escenarios de aplicación: en el ámbito de la producción de software facilitando el desarrollo, la integración, liberación y despliegue continuo de los productos (Hansen and Heide, 2015; Rahman, Chen and Gao, 2015; Stillwell and Coutinho, 2015), en la reproducción de experimentos computacionalmente como la opción más sencilla en comparación con la reproducción física de los mismo (Piccolo, 2014; Bastin et al., 2015; Belmann et al., 2015; Boettiger, 2015; Gerlach et al., 2015; Hwee, 2015; Kacamarga, Pardamean and Wijaya, 2015; Meng et al., 2015), en la migración del procesamiento en computadoras personales a los servicios de la nube (Clark et al., 2014), entre otros. Recientemente se han publicado varios libros donde se reflejan los principios para trabajar con la tecnología de contenedores, que recomiendan prácticas que mejoran y estandarizan su uso, así como afianzan el trabajo con la seguridad en los mismos (Khare, 2015; Matthias and Kane, 2015; Goasguen, 2016). Al mismo tiempo, se presentan trabajos relacionados con el auto escalado y gestión de aplicaciones y servicios en entornos distribuidos con la plataforma Mesosphere que emplean Docker (Wuggazer, 2015). De igual forma la liberación de la solución de Google para la orquestación de contenedores. 24.
(32) Capítulo I Kubernetes1 ha ganado fuerza desde sus inicios y actualmente cuenta con el soporte de Docker como alternativa nativa para la gestión de contenedores en múltiples nodos. 1.2.1 Virtualización El desarrollo de aplicaciones bajo el paradigma cliente servidor, dentro de las que se encuentran las aplicaciones web, tiene sus propios retos como se describe en (Gajda, 2015). Para ilustrar algunos de estos elementos, se toma el escenario más común de producción donde los servicios de backend y frontend se ejecutan en host diferentes (ver Figura 9).. Figura 9 Despliegue usual de aplicación web (elaboración propia). Para preparar el entorno de desarrollo se plantean usualmente dos variantes (ver Figura 10): a) ejecutar los servicios de frontend y backend en el mismo host b) ejecutar la aplicación cliente en el host del desarrollador y los servicios de backend en otro host diferente para lograr una mayor aproximación al entorno de producción.. 1. https://kubernetes.io/ Kubernetes es un sistema de código libre para la automatización del despliegue, ajuste de escala y manejo de aplicaciones en contenedores que fue originalmente diseñado por Google y donado a la Cloud Native Computing Foundation. Soporta diferentes ambientes para la ejecución contenedores, incluido Docker.. 25.
(33) Capítulo I. Figura 10 Entornos de desarrollo (elaboración propia). En el escenario (a) se manifiestan las dificultades siguientes: . La instalación y actualización de los softwares necesarios deben ser realizados manualmente por cada desarrollador lo cual incurre en un gasto de tiempo considerable por cada desarrollador que recree el escenario.. . Debido a que cada desarrollador emplea su SO preferido es muy difícil recrear el mismo escenario para todas las plataformas.. . Al recrear manualmente el entorno cada desarrollador podría experimentar los problemas de “funciona en mi host”.. . Diferencias entre el entorno de desarrollo y producción que pueden provocar fallas no detectadas en las etapas de prueba.. . Todos los miembros del equipo requieren un conocimiento especializado sobre cómo instalar todos los componentes necesarios del sistema desarrollado aun cuando su trabajo solo sea de diseño de interfaces.. . En el caso de los desarrolladores que trabajan sobre varios proyectos a la vez, estos proyectos se ven afectados por el mismo entorno de desarrollo (mismas bibliotecas instaladas, servicios). Incluso el manejo de las dependencias y servicios necesarios para cada proyecto se hace complejo.. En el escenario (b) aparecen las desventajas siguientes:. 26.
(34) Capítulo I . Siempre se requiere de una conexión de red para trabajar y el desempeño de los servicios de backend se ven afectados por la concurrencia de varios desarrolladores.. . Si los servicios de backend dejan de funcionar todos los desarrolladores se ven afectados.. . Debido a políticas de seguridad de algunas empresas el servicio podría no estar público por lo que se limita el trabajo colaborativo fuera de la entidad.. . Mantener la actualización del código en los diferentes hosts constituye una tarea adicional que puede abordarse de disímiles formas (sync, ssh copy, control de versiones, almacenamiento compartido) con sus respectivos retos.. La virtualización aprovecha las mejores características de los escenarios anteriores y mitiga las deficiencias al mismo tiempo. Cuando se utiliza la virtualización se pueden instalar los componentes de frontend y backend con las variantes de despliegue que se consideren necesarias (en VM diferentes o en una misma VM con IDE incluido). Adicionalmente se facilita el desarrollo de diferentes proyectos aislando los entornos de desarrollo por proyecto. Se pueden desarrollar aplicaciones que requieren de un entorno de desarrollo en Windows cuando los desarrolladores emplean Linux como SO base para el resto de las tareas que no son de desarrollo. Se puede construir un repositorio de imágenes base por entorno de desarrollo ahorrando el tiempo de preparación a la hora de asumir la implementación de nuevos proyectos. Con la virtualización no se necesita de redes para la conexión a recursos externos o publicar ciertos servicios para que otros se conecten, todo esto puede lograrse de forma controlada y de forma análoga a un escenario de producción en el propio host del desarrollador, un esquema de este escenario aparece en la Figura 11.. 27.
(35) Capítulo I. Figura 11 Entorno de desarrollo virtualizado (elaboración propia). 1.2.2 Vagrant Aunque el empleo de los entornos de desarrollo virtualizados fuese sencillo, no resulta tan natural su configuración y gestión, viéndose involucrados algunos conocimientos de administración de sistemas. Debido a que su diseño no suele ser portable, se requiere exportar grandes imágenes con los entornos virtualizados para compartirlas entre los miembros de los equipos, lo que dificulta la actualización de los entornos de desarrollo. Para superar estas dificultades surgió Vagrant2, que ha ganado gran popularidad por su facilidad para la automatización y recreación de entornos virtuales; mediante un proceso sencillo, reproducible y generando artefactos portables con soporte para varios servicios de IaaS y gestores de virtualización como: AWS, VirtualBox, VMWare y Hyper-V. Emplea imágenes base sobre las que aplicar los cambios y abstrae a los desarrolladores de los requerimientos de preparación del entorno que trabaja con la VM como cajas negras. Además facilita la cooperación entre desarrolladores e ingenieros de sistemas. 2. Vagrant: Producto creado a principios del 2010 por Mitchell Hashimoto para la automatización de la gestión de Sandbox en durante el desarrollo. Luego con la creación de la compañía HASHICORP (finales de 2012), Vagrant gano mayor fuerza brindándose soporte profesional, entrenamiento y componentes adicionales integrados en el ecosistema de trabajo propuesto por la empresa. Se mantiene como un proyecto de código abierto. 28.
(36) Capítulo I (Mullaguru, 2015) permitiéndoles en pocos minutos tener un entorno más cercano al de producción con independencia del proveedor de virtualización empleado en su SO. Con el empleo de la virtualización y la automatización con Vagrant paulatinamente desaparecieron los problemas de “funciona en mi host” pues cada desarrollador cuenta con el mismo entorno de desarrollo y los administradores de sistema emplean las mismas recetas para provisionar el entorno de producción. Algunas de las características que destacan en Vagrant son: . Despliegue portable entre máquinas: define una forma para construir una aplicación junto a todas sus dependencias en un simple objeto denominado ‘box’ que viene siendo una VM empaquetada que puede ser transferido a cualquier host que tenga instalado Vagrant.. . Construcción automática: contiene herramientas para que los desarrolladores automáticamente construyan sus VM desde su código fuente, con control total de sus dependencias, herramientas de construcción, empaquetado.. . Reutilización de componentes: cualquier box puede emplearse como imagen base para construir otros componentes más especializados, lo que facilita la creación de ecosistemas de desarrollos por tipos de aplicaciones según sea necesario.. . Capacidad para compartir recursos: se puede acceder fácilmente a un repositorio público3 en el cual la comunidad puede compartir las imágenes que se han creado.. . Herramientas de apoyo: define una API para la creación y gestión de VM. Suele emplearse de conjunto con otras herramientas de aprovisionamiento como: Chef, Puppet y Ansible. Adicionalmente la compañía HASHICORP cuenta con varias herramientas que facilitan varios de los procesos involucrados en la liberación de aplicaciones mediante VM: Packer, Serf, Terraform, Nomad.. Desventajas de Vagrant Aunque los beneficios son mayores, el trabajo con la virtualización empleando Vagrant presenta algunas deficiencias dentro de las que destaca la eficiencia, debido a que. 3. https://atlas.hashicorp.com. 29.
(37) Capítulo I usualmente los recursos necesarios en el host físico son inferiores a los requeridos para el despliegue en producción de la VM. Estas diferencias se reflejan luego a la hora de hacer los test de carga durante las pruebas, o incluso en el entorno de producción mismo en el que se necesita aumentar los recursos para brindar el servicio adecuado. Por otra parte, algunas combinaciones de SO y proveedores de virtualización tienen reconocidos problemas de trabajo, como por ejemplo el tiempo de acceso a directorios compartido en VirtualBox es lento, aunque existen alternativas para sortear estas dificultades. 1.2.3 Docker Los contenedores4 han existido desde hace tiempo, pero en los últimos años han ganado fuerza en gran medida por la posibilidad de su gestión sencilla para desarrolladores y administradores de sistemas mediante un conjunto de herramientas y mecanismos de trabajo que viabilizan el empleo de la tecnología en entornos de desarrollo, prueba y producción. Las máquinas virtuales utilizan el núcleo del SO (kernel) completo dentro de un sistema aislado (VM), mientras que los contenedores utilizan el kernel del host y aíslan solamente el espacio de usuario y de aplicaciones en su propio Sandbox (ver Figura 12); esto logra reducir drásticamente la sobrecarga en los host debido a que solo se está ejecutando un único kernel en lugar de varios. Docker también hace uso de la capa de sistema de ficheros pues construye las imágenes de forma tal que une muchas capas inmutables y crea un espacio aislado de escritura para el contenedor. Esto significa que, aunque se existan cientos de contenedores basados en Ubuntu 14.04, solamente se estará consumiendo el espacio del disco para la única imagen de Ubuntu; y el espacio de disco generado para guardar los cambios realizados por el contenedor que está en ejecución.. 4. Imagen y contenedor: Una imagen de docker es una plantilla inmutable creada por un grupo de instrucciones, la imagen no cambia luego de ser construida y sirve como base para la ejecución de un contenedor. Cuando un contenedor está en ejecución, significa que se crea una copia de la imagen base y a partir de aquí se comienzan a escribir los nuevos cambios sobre una nueva capa que puede ser volátil o persistente.. 30.
(38) Capítulo I Existen varias razones que justifican el rápido crecimiento de la comunidad de Docker. En primer lugar, ayuda a resolver el problema del empaquetado. Por muchos años, se ha mantenido la pregunta sobre qué debería ser un paquete desplegable y cuan dependiente del sistema operativo subyacente debería ser. Docker ofrece la habilidad de crear un desplegable con todas las dependencias del sistema operativo, manejadas fácilmente como un artefacto. En segundo lugar, Docker facilita el escalado de las aplicaciones de forma elástica. En gran medida esto se debe a que los contenedores son generalmente pequeños y se inician rápidamente, por lo que ocupan la mayor parte del tiempo de inicio en la descarga inicial de la imagen (solo ocurre la primera vez) elemento que puede ser mitigado fácilmente con la creación de un registro local de imágenes. Docker está escrito en el lenguaje Go y está construido empleando las capacidades de los kernels de Linux referentes a LXC, Cgroups y los namespaces (Chapter 1. Introduction to Control Groups (Cgroups) - Red Hat Customer Portal, no date; Petazzoni, 2015) adicionando las siguientes características: . Despliegue portable entre máquinas: define una forma para construir una aplicación junto a todas sus dependencias en un simple objeto que puede ser transferido a cualquier host que corra Docker y ejecutarla con la certeza que el entorno de ejecución expuesto a la aplicación es el mismo siempre.. . Construcción automática: contiene herramientas para que los desarrolladores automáticamente construyan sus contenedores desde su código fuente, con control total de sus dependencias, herramientas de construcción, empaquetado.. . Versionado: incluye capacidades para seguir las versiones sucesivas de un contenedor, inspeccionar las diferencias entre versiones, marcar una nueva versión, restablecer una versión anterior. El historial puede mostrar cómo el contenedor fue construido y brinda un registro trazable desde el despliegue en producción hasta el desarrollador. Docker también implementa envíos y descargas incrementales por lo que solo se envían las diferencias entre el registro y los hosts.. . Reutilización de componentes: cualquier contenedor puede emplearse como imagen base para construir otros componentes más especializados, lo que facilita. 31.
(39) Capítulo I la creación de ecosistemas de desarrollos por tipos de aplicaciones según sea necesario. . Capacidad para compartir recursos: se puede acceder fácilmente a un repositorio público5 en el cual la comunidad puede compartir las imágenes que se han creado. El equipo de Docker suele dar soporte a las principales imágenes marcándolas como oficiales llegando a construir una biblioteca estándar. En la actualidad, existen servicios como GitHub que permiten la integración con este registro, automatizando la publicación de las nuevas versiones de una imagen. Este registro en sí mismo es de código abierto por lo que cualquiera puede desplegar su registro privado para el despliegue de sus servidores privados o despliegues sin conexión a internet.. . Herramientas del apoyo: existe una API para la automatización y personalización de la creación y despliegue de contenedores. Existe un gran número de herramientas que se integran con Docker para extender sus capacidades, como, por ejemplo: PaaS para el despliegue (Dokku, Deis, Flynn), orquestadores multinodos (maestro, Salt, Mesos, OpenStack Nova), Dashboards de gestión (Docker-ui, OpenStack Horizon, Shipyard), herramientas de gestión de la configuración (Chef, Puppet) y de integración continua (Jenkins, Strider, Travis), entre otros.. Alrededor de Docker existen una serie de aplicaciones que facilitan el trabajo y gestión de los contenedores en un host, desde la creación hasta el manejo de contenedores en múltiples host y forma un clúster para los despliegues (docker-machine, docker-swarm, etc.). Prácticamente al mismo tiempo que surgía Docker, aparecían nuevas alternativas para manejar clúster de host como DC/OS de Mesosphere6 que es un sistema operativo distribuido que soporta el despliegue de contenedores de Docker de una forma sencilla con las premisas de escalabilidad y recuperación ante fallas; por otra parte se encuentra. 5. https://hub.docker.com Sitio web que funciona como un repositorio de imágenes de Docker para el intercambio entre servidores y permite el desarrollo de la comunidad de usuarios. 6. https://mesosphere.com/ Mesosphere es una compañía estadounidense de tecnología con sede en San Francisco, California que desarrolla software para centros de datos basados en Apache Mesos. Llama a su producto Datacenter Operating System.. 32.
(40) Capítulo I CoreOS7 como otro sistema operativo distribuido que permite el despliegue de aplicaciones en contenedores de Docker. Desde el surgimiento de Docker aparecieron herramientas que permiten declarativamente reflejar los componentes o microservicios necesarios para un despliegue (bases de datos, balanceador de carga, aplicaciones) facilitando la creación, destrucción y escalado de los mismo. Dentro de ellos se pueden encontrar: Crane y Fig que recientemente fue adquirido por docker y rebautizado como docker-compose. Con estas herramientas poco a poco se generalizó la utilización de Docker en el proceso de desarrollo y despliegue de software. Algunos estudios se han realizado comparando las máquinas virtuales versus los contenedores en diferentes escenarios corroborando algunas de sus características antes mencionadas y mostrando en varios casos los beneficios de Docker sobre la virtualización cuyos elementos fundamentales se resumen la Figura 12.. Figura 12 Docker vs Máquinas virtuales (elaboración propia). 7. https://coreos.com/ CoreOS es un sistema operativo ligero de código abierto basado en el kernel de Linux y diseñado para proporcionar la infraestructura para los despliegues en clúster, mientras se centra en la automatización, facilidad de despliegue de aplicaciones, seguridad, fiabilidad y escalabilidad.. 33.
(41) Capítulo I En términos generales, alineados con el uso del Sandbox para el desarrollo de aplicaciones, tenemos los siguientes que a continuación se enumeran e ilustran en la Figura 13: 1. Preparación del Sandbox de desarrollo 2. Implementación y ejecución de pruebas locales 3. Proceso de integración continua ejecutándose batería de test. 4. Despliegue en entornos de prueba para pruebas de aceptación y validación con el cliente. 5. Despliegue en producción.. Figura 13 Sandboxes en el proceso productivo de software (elaboración propia). Para hacer uso de Vagrant se emplea el box oficial de CentOS 7 como imagen de base y aprovisionar la máquina virtual (VM) con las dependencias necesarias para el desarrollo de aplicaciones Rails (instalador de Ruby) y compartir el directorio donde radica el código del proyecto con la VM. Posteriormente se desarrolla la aplicación con el IDE deseado y para realizar las pruebas solo se necesita acceder a la VM y ejecutar la batería de test propuesto garantizándose que con la versión del Sistema Operativo de producción y las 34.
(42) Capítulo I dependencias instaladas la aplicación funciona correctamente. Luego para finalizar, se salva esta VM y se traslada hacia pruebas y luego hacia producción. En el caso de Docker funciona de forma similar. Se referencia la imagen oficial de CentOS 7 en el Dockerfile y a partir de aquí se declaran todas las dependencias que se necesitan para el desarrollo y puesta en funcionamiento de la aplicación (instalador de Ruby) y se especifica el volumen sobre el que se montará el directorio de la aplicación a desarrollar. Posteriormente, en la fase de implementación, se construye esta imagen en base al Dockerfile y se crea un contenedor donde se desarrolla la aplicación. Finalmente, luego de pasar por las pruebas locales se publica esta imagen previamente construida para ser empleada en los entornos de pruebas y producción. Conclusiones parciales Las tecnologías de sandboxing constituyen un elemento efectivo en la agilización del desarrollo, prueba y puesta en producción de soluciones de software. En el caso de Vagrant se valora su utilidad durante la creación y aprovisionamiento de host en entornos de pre-producción y producción debido al costo en recursos asociado a la virtualización. En el caso de Docker se extienden los beneficios evidenciando su empleo cada vez más frecuente en la ejecución de pruebas hasta la explotación en producción. Tomando en cuenta las características de ambas tecnologías se recomienda su empleo de conjunto, aportando un mayor grado de automatización al desarrollo de una solución informática y su despliegue continuo. 1.3 Infraestructura como Código Actualmente existen algunos enfoques de automatización en la ingeniería de software tales como la integración continua y la liberación continua. Sin embargo, la implementación técnica real o un marco de trabajo (framework) no están definidos, dejando al administrador del sistema desarrollar herramientas locales complejas basadas únicamente en la descripción del proceso. Por otra parte, los conceptos sólo se ocupan de la automatización de componentes, prueba y despliegue, pero no cubren otros conceptos vitales como la recuperación ante fallos y la optimización de servicios. 35.
Figure
+7
Documento similar