Practicas DevOps: Monitoreo

Una problemática común para aquellos que trabajamos en el mundo del software es la disponibilidad de nuestras aplicaciones. En primera instancia es imprescindible entender las necesidades de disponibilidad que debe cumplir nuestra aplicación. Esto es una definición que viene dada por una restricción del negocio. En ese sentido hay aplicaciones que solo deben están disponibles en horario de oficina (de lunes a viernes a 9 a 18), mientras que hay otras que puede que solo requieran estar disponibles ciertos días por mes. Y obviamente también están aquellas aplicaciones que tienen que estar disponibles 7 x 24. Esta es una cuestión de negocio que tiene un impacto enorme en las cuestiones técnicas. Desde el punto de vista de desarrollo tenemos que tomar cierta precauciones en el diseño y codificación de nuestra solución. Al mismo tiempo también debemos observar ciertas cuestiones en lo que respecta a la arquitectura física de la solución. Finalmente debemos tener presente una serie de cuestiones operacionales como ser backups, failover, escalamiento, etc. Como consecuencia de varias de estas cuestiones surge la necesidad de ser capaces de detectar una interrupción del servicio ANTES que se entere el usuario final.  Más aún, lo ideal es detectar en forma anticipada una posible interrupción para intentar evitarla. Esto implica implementar una estrategia de monitoreo.
Cuando hablamos de monitoreo tenemos distintos niveles:
  • Capa 1: hardware / sistema operativo, aquí miramos cpu, memoria, disco, red, etc.
  • Capa 2: middleware, aqui miramos métricas particulares del midddleware como ser métricas de la JVM, del web server, la DB, etc
  • Capa 3: aplicación, aquí miramos cuestiones más concretas cercanas al dominio de nuestra app. Incluyo aquí tiempo de respuesta, tiempo de carga de las páginas, y también cuestiones como cantidad de usuarios con sesión activa, etc.
Para monitorear cada una de estas capas hay distintas alternativas. Cuando uno corre con una infraestructura de cloud, el proveedor de cloud típicamente provee monitoreo de capa 1. El monitoreo a este nivel es transparente para la aplicación.
Para capa 2 el monitoreo también puede hacerse de forma transparente, y las herramientas para hacerlo dependen en gran medida de cual sea nuestro middleware, o sea, no es lo mismo monitorear tomcat que nginx. Una herramienta de uso común aquí es Nagios (aunque Nagios también puedeusarse en capa 1).
Para capa 3 implementar monitoreo requiere algunos ajustes a nivel de aplicación, o sea, las soluciones tienen cierto grado de intrusión en nuestra aplicación y suelen requerir algunos cambios en nuestro código. Las soluciones son diversas y pueden mezclase. Un caso típico es utilizar Google Analytics para medir tiempos de respuesta y permanencia de los usuarios en ciertas páginas.
Obviamente existen algunas soluciones que proveen la posibilidad de monitorear las 3 capas de manera unificada. A mi parecer la solución más popular a en este segmento es New Relic.
Por otro lado el monitoreo implica 2 cuestiones centrales:
  1. Recolección de datos
  2. Ejecución de acciones ante determinadas situaciones. De mínima tenemos el envió de alertas, pero también podríamos activar acciones de escalamiento.
Lo mencionado anteriormente sobre los niveles de monitoreo aplica a la recolección.  Respecto de la acciones a ejecutar, ahí también tenemos diferencia en la solución de monitoreo elegida. En este sentido, si la aplicación va a estar disponible 7×24, es posible que el envío de mails no sea suficiente y tengamos que echar mano de mensajes a directos a un teléfono de guardia.
Continuará…

Prácticas DevOps: unificación de ambientes

Una de las primeras recomendaciones que suelo hacer a quienes me contratan para ayudarlos con cuestiones de Continuous Delivery/Automazación de ambientes es la unificación/normalización de infraestructura. Lamentablemente suelo encontrarme con proyectos donde cada servidor/ambiente es una historia distinta: el servidor de producción corre una versión de sistema operativo distinta a la del servidor del producción, tomcat y apache instalados de distinta forma en distintas ubicaciones en cada uno de los ambientes. Situaciones de este tipo tienen dos problemas:

1. Existe cierto riesgo de que algo probado en testing luego no se comporte de la misma forma en producción debido a que los ambientes son distintos (y no me refiero a cuestiones de escala)

2. No es posible utilizar los mismo scripts de deployment/administración/monitoreo ya que muchas veces la ubicación de las aplicaciones/utilitarios es distinta en cada ambiente.

Ante situaciones así mi propuesta suele ser unificar ambientes/servidores siguiendo la heurística:

  1. Elegir un sistema operativo (y versión particular) en los posible que cuente con soporte de largo plazo. Ejemplo Ubuntu 14.04
  2. Automatizar el provisioning de base que tendran todos los servidores: configuración de usuarios, networking, etc. (es lo que seria automatización capa 1)
  3. Para cada componente (web server, base de datos, etc, etc) determinar la forma de instalarlo y generar los scripts correspondientes. (es lo que seria automatización capa 2)

De esta forma, cuando uno pretende avanzar sobre la automatización de despliegues, todo resulta mucho más simple ya que está claro el sistema operativo de base y la forma en que fue instalado cada componente. Al mismo tiempo, si todos los servers/ambientes se generan con los scripts de los pasos (2 y 3) entonces es muy factible poder reutilizar scripts de deploy entre distintos proyectos bajando de manera importante el esfuerzo de automatización.

Blue Green Deployment

En las últimas 2 semanas me encontré explicando la técnica de despliegue Blue/Green más de 5 veces. Cuando tomé conciencia de ello decidí hacer un video explicativo de modo de poder utilizarlo también en mis clases. Espero resulte de utilidad.

Ansible vs Puppet: mi opinión

Hace unos días escribí sobre el camino que recorrí con las herramientas de automatización de infraestructura y mencioné que luego de haber usado Puppet y Ansible, he decidido quedarme con este último. Esta decisión se debe principalmente a las cuestiones:

  • El DSL de Ansible me resultó mucho más amistoso que el de Puppet
  • Para trabajar en modo «standalone» Ansible incluye en su core un conjunto de utilidades/tareas que a mi me resultan muy útiles y que no están en el core de Puppet (a menos que uno instale módulos adicionales).
  • El modo de funcionamiento «push» de Ansible me gusta más que el modo pull de Puppet.

Resalté algunas partes de la frases anteriores para dejar bien en claro el nivel de subjetividad de las mismas.

Caminando las herramientas de automatización de infraestructura

En mi opinión hay 3 herramientas que han picado en punta en esta temática: Chef, Puppet y Ansible. Hay algunas otras (como por ejemplo CFEngine) pero toda la gente y casos que conozco utilizan alguna de las 3 mencionadas. En mi caso cuando comencé a meterme en este campo di una primera mirada a Chef, tenía por aquella época un cliente a quien yo estaba ayudando con otras cuestiones y que usaba Chef para administrar su infraestructura. A partir de ello hice algunas pruebas con Chef, pero nunca lo use en un «proyecto real».

Poco tiempo después me salió un proyecto para automatizar todo el pipeline de deployment de un aplicación incluyendo el proceso de provisioning de ambientes. Las pruebas que había hecho con Chef no me habían convencido, asi que decidí probar con Puppet. Usé Puppet durante un buen tiempo en diversos proyectos hasta que este año trabajé en un proyecto con Ale Ferrari quien venía utilizando Ansible y en mi siguiente proyecto decidí probarlo.

Hoy en día mi elección es Ansible, pero las razones las compartiré en otro post.

Cursos en la previa de Agiles 2015

Como de costumbre en la previa de Agiles 2015 habrá un conjunto de cursos organizados de forma independiente. En ese contexto estaré dictando en Montevideo mi Taller de Continuous Delivery y Prueba automatizada.

El términos generales el taller está divido en 2 partes. La primera enfocada en los conceptos centrales de la práctica de Continuous Delivery y un conjunto de técnicas y herramientas para su implementación que incluyen Jenkins, Puppet y Docker. La segunda se enfoca en la automatización de pruebas, lo cual constituye un punto fundamental en toda estrategia de Continuous Delivery. En esta segunda parte veremos herramientas tales como JUnit, Cucumber-JVM y FitNesse. Si bien el taller tiene una base conceptual independiente de toda tecnología, la parte práctica de automatización de pruebas se realiza con Java.

Los detalles de logística e inscripción están disponibles en la página de Evolución Ágil.

Prácticas DevOps: 3 repos por proyecto

Desde que empecé a trabajar fuerte con prácticas de DevOps, hace unos 2 o 3 años que todos mis proyectos tienen al menos 3 repositorios.

El primer repositorio es el que almacena el código fuente de la aplicación. En realidad dependiendo de la complejidad del proyecto, puede que haya más de un repositorio para el código fuente.

El segundo repositorio es el almacena la configuración de la aplicación. Este repositorio tiene típicamente un 1 branch por ambiente. Hay que destacar que estoy branches nunca se mezclan, sino que evolución a la par. Cuando la aplicación requiere de un nuevo parámetro de configuración, el mismo debe ser agregado simultáneamente a cada uno de los branches con el valor correspondiente para el ambiente asociado.

Finalmente el tercer repositorio es el que contiene los scripts de deploy. Dependiendo de la infraestructura del proyecto puede que sean simplemente scripts de bash, ansible, puppet o similar.

Capas de automatización

Este último año y medio he estado trabajando intensamente en cuestiones de automatización de pipelines e infraestructura en general, usando principalmente Jenkins, Puppet y herramientas afines.

En particular, estos últimos meses he trabajado en la automatización de despliegues de un producto software bastante complejo. La complejidad en este caso está dada por la gran cantidad de componentes de código e infraestructura involucrados: varias bases de datos relacionales, bus de servicios, sistema de colas, servidor de aplicaciones, servidor web, dispositivos móviles, etc. Al mismo tiempo el producto tiene un requerimiento de correr sobre distintos sabores de infraestructura (Oracle, IBM, OpenSource), lo cual requiere que cada ambiente (desarrollo, test, etc) tenga también varios sabores.

Para la generación de estos ambientes y el deploy de la solución a cada uno de ellos diseñamos una arquitectura de automatización/deploy de 3 capas la cual describo brevemente a continuación.

Capa 1: Sistema operativo

El primer paso es levantar los servidores con el sistema operativo correspondiente (para el caso mencionado CentOS y Oracle Linux) y realizar algunos ajustes de base sobre el mismo (configuración de red, usuarios, etc). En general esto se hace utilizando la API de la plataforma de virtualización y algunos scripts de base. Puntualmente en el mencionado caso usamos el Hypervisor de VMWare y Puppet.

Capa 2: Software de base

Ya con el sistema operativo instalado y servidor 100% funcional hay que instalar software de base: motor de base de datos, el service bus, el web server, etc. Cada uno de estos componentes hay que instalarlos y configurarlos acorde a seteos específicos de la solución. En el caso mencionado esto lo hicimos usando scripts Ansible que se disparan desde RunDeck

Capa 3: Aplicación

Lo último que resta es instalar la solución en cuestión, lo cual implica crear los schemas de base datos, desplegar las aplicaciones en los servidores/contenedores web, desplegar los flujos en el bus de servicios, etc. En el caso en cuestión esto lo tenemos implementado con simples bash scripts que lanzamos desde Jenkins.

La implementación de esta solución en este caso puntual requirió del trabajo de distintas áreas de la organización: gente de infraestructura (capa 1), gente de operaciones (capa2), gente del grupo de producto (capa3) y obviamente hubo también un cierto esfuerzo de coordinación de todos ellos.

Hay algunas cuestiones de la implementación de este caso que aún hoy no me convencen (como usar Puppet Y Ansible al mismo tiempo, hubiera preferido usar sólo 1 de ellos) y que son consecuencia de decisiones tomadas por los distintas áreas de la organización. Más allá de las herramientas particulares, creo que el esquema general de esta solución es replicable en otros contextos usando incluso otras herramientas, es por ello que decidí compartir estas líneas.

capas_automatizacion

Versionado de base de datos

Este es un tema que curiosamente para mi muchos equipos no tienen incorporado como práctica. A mi parecer en la actualidad la estrategia más común para esto es lo que desde hace años comenzó a hacer Ruby on Rails:

  • escribir los scripts incrementales de actualización de la base siguiendo una convención de naming incremental (números secuenciales o timestamp invertidos). Estos scripts al ser texto plano se pueden almacenar naturalmente en el repositorio de código junto al código de la aplicación
  • por otro lado se agrega una tabla en la propia base de datos para llevar registro de los scripts aplicados lo cual determina la versión de la base de datos.

En el caso de Ruby on Rails, uno debe encargarse de escribir los scripts (para escribir los puede usar un DSL en lugar de sql) y luego el propio framework brinda funcionalidades para crear la tabla de versión, ejecutar los scripts y llevar control de su ejecución. No estoy seguro si Rails fue el primer framework en implementar esta estrategia pero en la actualidad existen diversas herramientas en distintos lenguajes que la implementan como ser: FluentMigrator (con foco en C#), LiquidBase (con foco en Java/Grails).

Una herramienta que implementa esta estrategia y con la que he estado trabajando este último tiempo es Flyway, les comparto un video que muestra su uso y explica algunos detalles.

AOC: Vampiros, hombres-lobo y DevOps

Cuando el equipo organizador del AOC me propuso dar una de las charlas plenarias consideré inicialmente 2 o 3 temas posibles y luego de dar un par de vueltas decidí cortar por la sano y hablar sobre cuestiones de mi día a día. En ese sentido mi actividad actual se reparte entre desarrollo de aplicaciones y trabajo de consultoría en cuestiones relacionadas a automatización de pruebas y despliegue continuo.

Al tratarse de un tema de mi trabajo cotidiano ya tenia mucho material a mano pero tenía que sentarme a ordenarlo. Decidí utilizar el aplicativo de Google para armar las diapositivas y me puse a trabajar. A medida que iba armando los slides iba ensayando la presentación incrementalmente. Cuando logré un esqueleto mínimo de la presentación,lo compartí con mi pareja para tener feedback y a partir de eso seguí trabajando en el tramo final. Las cuestiones visuales fueron lo último que ajusté. Una vez conforme con el entregable generado, corrí un ensayo de punta a punta y di por cerrado el trabajo.

Llegado el momento de la charla plenaria, encendí mi cronómetro y empecé a hablar. Si bien había trabajado bastante en la presentación, yo mismo me sorprendí cuando terminé  la presentación y vi que en la cuenta regresiva del cronómetro restaban tan sólo 2 segundos. Creo que nunca en mi tuve tal precisión en un presentación.

Aquí están disponibles las diapositivas que utilicé.

mi_sesion_aoc_2015