Llegamos a ustedes gracias a:



Reportajes y análisis

Cómo las herramientas DevOps aceleran la entrega de software

[01/09/2017] Érase una vez un desarrollador que necesitó escribir código contra una base de datos. Así que le pidió al administrador de la base de datos el acceso a la base de producción.

"Oh, querido mío, no", dijo el DBA -siglas en inglés para administrador de base de datos. "No puedes tocar nuestros datos. Necesitas tu propia base de datos. Pregúntale a operaciones.

"Oh, querido mío, no", dijo el gerente de operaciones. "No tenemos una licencia de Oracle de repuesto, y se necesitarían seis meses obtenerla y ejecutar el servidor. Pero haré lo que pueda.

Puede notar hacia dónde va esto. Incluso puede escuchar "muajaja" después de cada respuesta. Por supuesto, el DBA y el gerente de operaciones solo están haciendo su trabajo, pero el desarrollador -y las necesidades del negocio- están atrapados en el carril lento.

¿Qué pasa si el desarrollador hubiera creado una máquina virtual ya configurada con versiones de prueba del sistema operativo correcto, la base de datos correcta, los esquemas de tabla y de índice correctos y los datos de prueba sintácticamente válidos? ¿Y si todo esto pasó bajo el control de un archivo de configuración y scripts mientras preparaba y bebía una taza de café? ¿Qué tan "ágil" sería?

Conozca DevOps. Básicamente, DevOps ofrece una gran caja de herramientas que automatiza el camino alrededor de las solicitudes que solían dar como resultado a un "no" como respuesta. Los desarrolladores obtienen lo que necesitan para hacer su trabajo, y el área de operaciones pueden aguantar su propuesta sin problemas hasta el final. Estas herramientas se pueden dividir en conjuntos que soportan cada paso del ciclo de vida del desarrollo de software, desde la codificación hasta la integración, la implementación, el monitoreo y el reporte de errores.

Herramientas de desarrollo

Para un desarrollador, la vida de trabajo gira en torno a un entorno de desarrollo. Que tiene varias piezas, que podrían ser integradas o podría ser una selección de herramientas independientes.

El código existente vive en un repositorio, como Git o Team Foundation Server (TFS) y la primera tarea del desarrollador todos los días (después de la reunión diaria que tienen las organizaciones ágiles) es retirar o clonar todo el código de interés del repositorio compartido. En un mundo ideal, los registros o impulsos ajenos tendrían un impacto en el código del desarrollador, ya que el código de todos ya estaría fusionado, integrado y probado. En el mundo real, no siempre sucederá eso, y la fusión, integración y pruebas de los cambios de ayer podría quedan en segundo plano en el orden de prioridades de los negocios.

En un mundo ideal, todo el código sería perfecto. En el mundo real, no hay tal cosa como código perfecto -lo más cerca que podemos llegar a ello es el código que no tiene ningún error conocido.

Desde el punto de vista del desarrollador, observar el gestor de defectos (ya sea Bugzilla, JIRA, Redmine, TFS o cualquier otro rastreador) y atender cualquier "demanda" (informes de errores o asignaciones de tareas) es el orden adecuado de lo que se debe hacer.

Un IDE como Eclipse o Visual Studio a menudo tiene una ventana en el gestor de defectos o, posiblemente, vínculos más profundos, pero al menos el desarrollador tiene una pestaña del navegador abierta para ver sus entradas. El desarrollador continuará el proyecto de ayer, o archivará y manejará una alerta de prioridad, si la hay. De la misma manera, los IDE a menudo se integran estrechamente con los repositorios. Mediante el mismo token, el desarrollador tiene una consola de línea de comandos abierta para el check-in y check-outs. Y para completar el triángulo, los rastreadores de errores a menudo se integran con los repositorios de código fuente. ?

El editor de código suele ser el componente principal de un IDE. Los mejores editores de código para DevOps muestran el estado del repositorio de código que están examinando, por lo que puede decir de inmediato si está buscando en el código fuente obsoleto. También actualizarán su copia antes de introducir conflictos de fusión.

Las herramientas construidas por los desarrolladores dependen del idioma (s) de programación que está escribiendo, pero en el caso de los lenguajes compilados, los desarrolladores quieren tener la capacidad de desactivar las construcciones del IDE y capturar los errores y las advertencias con fines de edición. También ayuda si el editor de código conoce acerca de la sintaxis de la lengua, de modo que pueda marcar los errores de fondo durante la codificación y resaltar la sintaxis con colores para ayudar a que los desarrolladores visualmente confirmen que, por ejemplo, el nombre que desean utilizar para una variable ya definida es correcto.

Cuando los desarrolladores escriben y prueban código, a menudo pasan la mayor parte del día ejecutando un depurador. Cuando están en una organización que ha implementado DevOps, a menudo tienen el lujo de depurar en un entorno virtualizado que refleja fielmente el entorno de producción. Sin eso, los desarrolladores tendrían que utilizar código stub para representar acciones del servidor o tener bases de datos locales para bases de datos remotas.

Las pruebas ayudan a que los desarrolladores ejecuten sus pruebas unitarias y de regresión fácilmente y de forma regular. Idealmente, el marco de pruebas se integra con el IDE y cualquier repositorio local, de modo que cualquier nuevo código puede ser probado inmediatamente después del check-in, mientras que el desarrollador tiene el diseño firmemente en mente. Las pruebas del desarrollador deben fluir en el entorno de integración de código a través del repositorio compartido, junto con el código fuente que el desarrollador ha depurado y probado.

DevOps

Herramientas de integración de código

Las herramientas de integración de código toman el código en un repositorio compartido, lo construyen, ponen a prueba e informan sobre los resultados. Esto se hace a menudo usando un servidor de integración continuo, como Jenkins, que se unirá a herramientas automatizadas de compilación, testeadores automatizados, informes automatizados por correo electrónico y administradores de defectos, y acciones en el repositorio.

Por ejemplo, si la compilación tiene éxito y todas las pruebas pasan, todo el código fuente actual y las librerías y los ejecutables construidos se pueden etiquetar con el número de compilación actual en el repositorio. Si las pruebas críticas fallan, las comprobaciones pertinentes se pueden retirar del repositorio compartido y devolverse al desarrollador responsable para solucionar los errores.

DevOPs

Algunos proyectos implementan integración continua para cada impulso de código, si el tiempo de construcción incremental es pequeño. En otros proyectos, se introduce un retraso después de un empuje de código para que se puedan combinar varios impulsos en la siguiente generación. La mayoría de los proyectos, independientemente de que utilicen o no compilaciones y pruebas automáticas, y si se integran o no después de impulsar el código o cuando lo solicitan a lo largo del día, también ejecutan pruebas y compilaciones "limpias" todas las noches, a menudo en entornos de prueba recién implementados.

Herramientas y entornos de implementación

Si el servidor de integración continua está configurado para desplegar compilaciones, después de pasar todas las pruebas, a menudo dependerá de la implementación de software y herramientas de administración de configuración. Estos a menudo varían dependiendo de la plataforma de tiempo de ejecución y la infraestructura adicional.

Por otro lado, algunas herramientas de gestión de configuración -como Ansible, Chef, Puppet, Salt y Vagrant- trabajan en una amplia gama de plataformas utilizando lenguajes ampliamente soportados. Ansible y Salt son sistemas basados en Python; Chef, Puppet y Vagrant están basados en Ruby.

Ansible toma recetas en YAML y administra nodos a través de SSH. Chef utiliza un lenguaje Ruby específico de dominio para sus recetas de configuración y utiliza un servidor Erlang, así como un cliente Ruby.

Puppet utiliza un lenguaje declarativo personalizado para describir la configuración del sistema; Puppet normalmente utiliza una arquitectura de agente/maestro para configurar sistemas, pero también puede ejecutarse en una arquitectura autónoma. Hay más de 2.500 módulos predefinidos listados en Puppet Forge.

Salt, originalmente una herramienta para la administración remota de servidores, ha evolucionado hasta convertirse en una aplicación de ejecución remota y administración de configuraciones open source, cloud-agnostic y galardonada. Salt puede administrar e implementar sistemas Linux, Unix, Windows y MacOS, y puede orquestar recursos en muchas nubes. Vagrant es una herramienta de gestión de configuración especializada para entornos de desarrollo que actúa como un contenedor para VirtualBox, VMware y otros gestores de máquinas virtuales. Vagrant se encarga de la reproducción de errores dependientes de la configuración.

La PaaS (plataforma como un servicio, por sus siglas en inglés) ocupa un nicho interesante en el ecosistema de la nube. Es básicamente una plataforma de desarrollo, prueba y despliegue que se encuentra encima de la IaaS (infraestructura como servicio, por sus siglas en inglés). La PaaS puede ser implementada en un local u ofrecido como servicio por un proveedor de nube pública. Por ejemplo, el Pivotal Cloud Foundry PaaS se puede implementar en locales en la parte superior de la versión de VMware de una nube privada, o puede ejecutarse en una nube IaaS pública como Amazon EC2.

PaaS incluye infraestructura, almacenamiento, base de datos, información y proceso como un servicio. Piense en PaaS como proveedor de computadoras, discos, bases de datos, flujos de información y procesos de negocio o meta-aplicaciones, todo ello empacado en una "stack" o "sandbox". Cuando una PaaS agrega valor sobre IaaS es para automatizar todo el aprovisionamiento de recursos y aplicaciones, lo cual puede representar un gran ahorro de tiempo.

Existen dos tipos de máquinas virtuales o VMs: VM de sistema, como VMware, y máquinas virtuales de proceso, como Java Virtual Machine. Para los propósitos de las herramientas de despliegue, estamos interesados en las máquinas virtuales del sistema, en las que podemos implementar un PaaS, como Cloud Foundry o una aplicación de servidor, como PostgreSQL. A su vez, las VM se pueden implementar en hardware de servidor dedicado, ya sea en locales o fuera de las instalaciones, o en una nube IaaS. Las máquinas virtuales del sistema ofrecen un aislamiento de software excelente, a expensas de incurrir en una sobrecarga de hipervisor bastante pesada y usar una gran cantidad de RAM. Varios hipervisores e infraestructuras IaaS ofrecen diferentes cantidades de aislamiento de cargas y diferentes algoritmos para asignar el exceso de capacidad de la CPU a las máquinas virtuales que lo necesitan.

Los contenedores de software como Docker ofrecen un aislamiento de software lo suficientemente bueno en la mayoría de los casos, con mucho menos gastos generales que las máquinas virtuales. Todos los sistemas PaaS con los que estoy familiarizado envuelven aplicaciones en contenedores de software. Por ejemplo, OpenShift solía ejecutar aplicaciones en contenedores denominados engranajes, y utilizaba SELinux para aislamiento de engranajes; hoy en día utiliza Docker como su formato de contenedor nativo y tiempo de ejecución. De manera similar, Cloud Foundry usaba aplicaciones en contenedores Warden Linux, pero ha introducido un nuevo sistema de gestión de contenedores, llamado Diego, que soporta Docker y otros contenedores que se ajustan a la especificación Open Container Initiative.

Por otro lado, Docker puede trabajar independientemente de los sistemas PaaS y puede simplificar enormemente la implementación para DevOps. Docker puede hacer que las nubes múltiples se vean como una gran máquina, y se puede utilizar para la automatización de la construcción, la integración continua, las pruebas y otras tareas de DevOps. Si bien Docker comenzó como una solución solo para Linux, recientemente también ganó soporte para Windows.

En el gran esquema del ciclo de vida del software, cada característica pasa del diseño al desarrollo, pasando por la fase de ensayo, hasta la producción, mientras que los informes de errores se devuelven a los desarrolladores para su triaje y arreglos en cada etapa. Para los productos que se liberan cada año, pasar de una etapa a otra puede que sea un proceso manual. Para los productos ágiles que se publican semanalmente o quincenales, la gestión de la liberación es a menudo automatizada. Parte de lo que necesita ser automatizada es la gestión del proceso de liberación; además, los equipos necesitan automatizar sus pruebas, el seguimiento de errores, la construcción, el embalaje, la configuración y los procesos de promoción.

Herramientas de monitorización en tiempo de ejecución

Las pruebas de aceptación de los productos suelen incluir pruebas de rendimiento, que pueden ir hasta la prueba de carga completa con perfiles de usuario realistas. Aun así, el rendimiento de la aplicación puede cambiar en la producción por varias razones: un aumento en el uso, una pérdida de memoria que se manifiesta en el tiempo, un punto defectuoso en un disco, un servidor sobrecargado o un índice de base de datos poco considerado que ralentiza las actualizaciones después de que su tabla subyacente crezca.

El monitoreo del rendimiento de la aplicación está diseñado para crear continuamente métricas para los indicadores de rendimiento clave que son importantes para su aplicación. Normalmente se dividen en métricas de usuario, como el tiempo de vista en una página o completar una transacción; y las métricas del sistema, como la utilización de la CPU y la memoria. Las métricas del sistema suelen estar disponibles todo el tiempo. Las métricas de usuario pasivas, que a menudo se recogen utilizando dispositivos de supervisión de red, son de gran valor cuando la aplicación se utiliza intensamente; las métricas de usuario activas, recogidas mediante la generación de solicitudes de aplicación y la medición de los tiempos de respuesta, se reservan a menudo para periodos que no son de carga máxima.

Cuando su aplicación no está funcionando como desea, determinar la causa raíz puede ser un proceso frustrante y que consume mucho tiempo. Hasta hace poco, los agentes DDCM (monitoreo de componentes profundos, por sus siglas en inglés) que pretendían ayudarle con el análisis de la causa raíz se sobrecargaban demasiado para ser utilizadosen producción; tendría que encenderlos por un período corto para intentar capturar el problema, luego apagarlos para permitir que la producción se reanude a plena capacidad. En los últimos años, sin embargo, los nuevos productos DDCM del mercado aseguran poder monitorear una amplia selección de lenguajes y marcos con un mínimo de gastos generales, simplificando el proceso de análisis de causa raíz.

Herramientas para reportar y reproducir errores

Anteriormente mencionamos administradores de defectos, pero no dimos detalles sobre su uso. En el mejor de los casos, un defecto notificado irá acompañado de una descripción detallada, una causa raíz, un script para reproducir el problema y será asignado al desarrollador que esté más familiarizado con el código correspondiente. En el peor de los casos, un reporte de errores provendrá de un usuario frustrado llamando al soporte técnico e incluirá una conversación a lo largo de estas líneas:

Soporte técnico: ¿Qué pasa?
Usuario: Se malogró.
Soporte técnico: ¿Qué estaba haciendo?
Usuario: Lo que siempre hago. Funcionó ayer.
Soporte técnico: ¿Ha cambiado algo desde ayer?
Usuario: No he cambiado nada.

No es necesario decir que tales informes requieren alguna habilidad por parte del soporte técnico para profundizar lo suficiente en una descripción, y en los pasos para reproducir el problema con el fin de permitir que un desarrollador trabaje en el problema. También puede requerir la entrada y la ejecución remota de diagnósticos en la máquina del usuario.

A veces estos problemas no se reproducen en la máquina de un desarrollador. Una razón común para esto es que la caja de desarrollo es demasiado rápida y tiene demasiada memoria para mostrar el problema. Otra posibilidad es que el desarrollador tiene una biblioteca instalada que carece de usuario. Y un tercero es que el usuario tiene instalada otra aplicación que interfiere con la suya.

Una vez que haya determinado el entorno de tiempo de ejecución del usuario, el desarrollador puede utilizar herramientas de administración de configuración para crear un entorno de ejecución similar en una VM. Vagrant, en particular, está destinada a tales fines. La VM de prueba puede ejecutarse localmente en la máquina del desarrollador, en un servidor o en una nube IaaS.

En algunos casos, los pasos para reproducir el problema del usuario cambiarían la base de datos de producción. En estas situaciones, es útil tener una copia reducida de la aplicación de producción que se ejecuta en PaaS, de modo que los cambios nunca se propaguen al entorno de producción.

Una vez que se ha identificado una corrección para el problema y se ha agregado un conjunto de cambios al repositorio de código, la aplicación revisada debe ser sometida a prueba de regresión, preferiblemente, todas las pruebas de aceptación se ejecutarán. Si se acepta el cambio, el gestor de liberaciones o el gestor de servicios de atención al cliente debe decidir si propaga el cambio a la producción o la programa para una integración posterior y si debe proporcionar al usuario un parche o una solución operativa.

El círculo sin fin

Si el ágil moderno ciclo de vida de la aplicación suena un poco como la visión de Ezekiel de un carro con ruedas dentro de las ruedas, está bien: lo es. Un conjunto de ruedas representa los sprints -típicamente una a dos semanas- después de las cuales se libera una versión de la aplicación en desarrollo para ser probada. Otro conjunto de ruedas representa la subida de una construcción dada desde el desarrollo hasta la prueba, la puesta en escena y la producción. Un conjunto de rueda interior representa el ciclo de vida de una tarjeta de historia o función de aplicación. Y las ruedas más pequeñas representan informes y correcciones de errores.

En este complicado entorno, las tiendas de desarrollo pueden fácilmente descomponerse en cualquier etapa. El propósito de DevOps es ver que las cosas de rutina, como la creación de una base de datos de prueba limpia o la promoción de una construcción, sean rápidas y fáciles para que los desarrolladores puedan concentrarse en la construcción de características reales y solucionar errores reales.

Artículos relacionados