Y ahora verificando la performance (II)

Ok, esta vez si me he demorado en la segunda parte de esta serie sobre como agregar pruebas de performance a nuestros procesos de despliegue, en nuestro articulo anterior vimos como agregar configurar una prueba de carga sencilla, básicamente registrábamos una URL, el volumen de la prueba y listo… ya podíamos hacer una prueba preliminar que nos podría ser muy útil en algunos casos (como cuando todos los parámetros de una búsqueda están en el QueryString, por ejemplo), pero si queremos mayor granularidad en los parámetros de la prueba la alternativa es usar los Web Performance and Load Test Project que han ido evolucionando y que mediante el uso de Azure nos permiten desde Visual Studio tener unos resultados de prueba muy configurables, así:

Clipboard26

Y eso esta genial, pues nos permite (mediante nuestra cuenta de VSTS) provisionar recursos Azure que hagan la respectiva prueba mientras sea necesario, y que podamos ver dichos resultados desde nuestro Visual Studio, pero… ¿que tal si queremos que esta validación de carga decida si un despliegue ha ido bien o no? Pues eso es lo que trataremos de conseguir en este post.

En concreto lo que haremos sera agregar un proyecto de carga a nuestra solución, incluirla en el repositorio y de esta manera valernos de sus archivos para incluir un nuevo tipo de tarea durante nuestro proceso de despliegue, asumiremos que estamos trabajando con una solución Web que ya tiene configurado su repositorio asi como sus procesos de Build y Despliegue como hemos visto en anteriores artículos, ¿ok? Finish Reading: Y ahora verificando la performance (II)

Los dilemas de la Gestión de la Configuración en Entornos de despliegue

Si, se que les debo el como configurar la prueba de performance avanzada, pero en el interin quiero compartir unas reflexiones a propósito de la gestión de la configuración que vino a mi mente durante el DevDays.

Quienes han ido a mis diversas sesiones sobre VSTS o DevOps, sabrán que siempre hago referencia al lio que nos significa el gestionar los parámetros de configuración conforme una aplicación pasa de un entorno, el como manualmente uno tenia que tener mucho cuidado para asegurarse que la aplicación en Producción no apunte a la BD incorrecta, por mencionar el ejemplo mas claro.

Al empezar usar técnicas de Integración y Entrega Continua el primer enfoque que utilice para aliviar estos problemas fue el basarme en las Transformaciones, de esta manera se gestionaba un Web.Config «maestro» (en el caso de Java y Maven el escenario es muy similar solo que en este caso se trata de «pom»s»), que podía ser usado sin problemas en los equipos de desarrollo, pero al momento de efectuar la construcción de una nueva versión el compilador modificaba el Web.Config reemplazando porciones de este con contenidos especialmente definidos en archivos «delta» que contenían las variantes de cada destino al cual se iba a destinar la versión respectiva, en consecuencia ocurrían los siguientes hechos:

  • Se requiere hacer una Build Definition por cada potencial entorno al cual se iba destinar la aplicación, para de esta manera indicar que la construcción cogiera el «delta» correcto.
  • Si una versión puesta en un entorno es aprobada para ser «promovida» a un entorno superior, es necesario que dicha versión haya sido etiquetada o identificada adecuadamente a fin de poder recuperar el código fuente vigente entonces a fin de generar un paquete para el destino indicado.
  • Todos los «deltas» tienen que estar versionados en el código fuente, lo cual puede ser un problema si se desea mantener reserva sobre las cadenas de conexión a los entornos de Producción.

Aun así esto significa un gran avance con respecto a la gestión usual de editar y copiar a mano los archivos de configuración, donde revisas varias veces para ver que todo esta Ok. Otra opción, que no me gusta, es el de gestionar un repositorio (a veces separado del de código fuente) con todos los archivos de configuración de las diversas aplicaciones y que el proceso de despliegue simplemente copie el archivo respectivo en destino, y en algunos casos efectuar las mezclas necesarias de archivos.

La nube viene a significar una mejora en estos problemas, como vimos anteriormente  es muy sencillo configurar para que sea el Entorno (en este caso un Azure Web App, aunque AWS ofrece algo similar en su Elastic Beanstalk) sea quien almacene los mencionados parametros, y mas aun… gestionar ranuras de despliegue que permitan mover de manera sencilla el paquete de un lado a otro (en realidad mediante un cambio de DNS), conservando cada entorno su propio conjunto de parametros, sin que estos tengan que almacenarse en el código fuente.

Muy bien, parte de los problemas simplificados, uno solo creaba una Build Definition con paso de despliegue a un entorno y luego mediante la consola del entorno se encargaba de hacer los respectivos swaps o intercambios de contenidos, pero eso nos dejaba con los siguientes hechos:

  • Se salia fuera del ciclo automatizado de Integración y Entrega Continua para hacer el movimiento entre entornos.
  • Solo funciona en un entorno PaaS, si se trabaja con IaaS u On Premise, esta ventaja esta totalmente fuera de nuestro alcance.
  • Si se trabaja con AWS, hay que tener cuidado con no publicar valores en los archivos de configuración, pues (a diferencia de Azure) las variables definidas en el entorno solo funcionan si NO están definidas en los archivos de configuración, siendo que lo que este en los archivos tiene prioridad sobre el entorno.

El escenario ha mejorado bastante con la introducción de Release Management, que permite manejar el proceso de Build de una manera separada del de Despliegue, para que de esta manera uno genere un paquete, lo despliegue (cogiéndolo de un punto de contacto común), y si luego se aprueba su paso a otro entorno (mediante el flujo de aprobadores que ya hemos visto) el sistema efectuara la copia respectiva del paquete, y claro si seguimos trabajando aprovechando las ventajas de la gestión de parametros en el entorno… pues ya tenemos casi todo solucionado, solo que entre otras cosas… esto sigue siendo valido solo para PaaS.

En el ultimo DevDays tuve la ocasión de conversar con el gran Donovan Brown, el cual me ayudo con unos detalles de Release Management que no había configurado del todo bien, y en adición a ello le resumí brevemente sobre el enfoque de uso de Azure Web Apps para guardar parametros, y me dijo que es una buena opción para soluciones no complejas, pues solo podemos guardar AppSettings y Cadenas de Conexión, siendo que si requerimos grabar una entrada compleja (como la configuración de Redis) esto solo podríamos hacerlo mediante archivos de configuración, y como de nuevo esto nos regresa al tema de las transformaciones y las build independientes, me sugirió revisar el concepto de tokenización.

Investigando, pude entender (gracias a este interesante articulo) que mediante la tokenización lo que se pretende es que se despliegue un archivo de configuración con marcas (tokens) que luego en el proceso de despliegue (no en la compilación, ojo) sean sobreescritas por parámetros definidas en la Release Definition, resultando en que el web.config (por ejemplo) que llega al entorno destino ya tiene todos los valores correctos para dicho entorno, siendo que estos valores ya no son gestionados por el repositorio de código fuente, sino por el motor de Entrega Continua (en nuestro caso VSTS, pero el concepto es aplicable a otros motores), esta tendencia recién esta avanzando pero se simplifica mucho ahora que es posible definir tareas personalizadas a nuestro VSTS (y me imagino que ya habrá algún plugin Jenkins que logre el mismo efecto), ya que de momento no vienen de serie… pero eso no quita que en un futuro el proceso de tokenización venga de serie, de momento… tocara toquetear un poco… en el caso de ser necesario (cuando no se este usando PaaS y/o necesitemos gestionar valores complejos).

Asi pues, siempre hay formas de mejorar y afinar la solución para casos no cubiertos plenamente ¿qué otras opciones se les ocurren para estos dilemas?

 

Y ahora verificando la performance (I)

Varias cosas han pasado desde que empezamos a probar en nuevo modelo de Builds en VSTS, primero creamos una build sencilla que desplegaba a una Azure Web App, luego probamos como usar los Resource Groups para desplegar entornos, luego retiramos el paso de despliegue de la Build para trasladarlo a Release Management luego de su integración con VSTS, y hace poco agregamos Sonar como parte del proceso de análisis de nuestro código dentro de la compilación.

Y como el ciclo de evolución del proceso DevOps nunca para, en esta ocasión veremos como hacer algo a lo que le he tenido bastante respeto desde la época de las builds con el modelo XAML, en este caso la evaluación de la performance y estabilidad de nuestras aplicaciones web desplegadas.

En corto, la posibilidad de probar nuestras aplicaciones Web precede aun a .Net, recuerdo cuando probé Web Application Stress Tool (Homer) para hacer unas pruebas sencillas sobre ASP Clásico, de ahí le perdí el rastro pero la cosa se puso interesante desde Visual Studio 2013 se permite que los tests de carga se basen en las capacidades de la nube, lo cual significa que durante nuestras pruebas se provisionaran las maquinas virtuales que hagan falta para cubrir la cantidad usuarios y peticiones deseadas, esto ya lo había probado desde Visual Studio (revisar aquí y aquí), con buen resultado, pero… ¿como hacer que estas pruebas se ejecuten cuando se produzca cierto tipo de despliegue?

Antes de proseguir hay algunas consideraciones a tener en cuenta:

Los recursos que Azure provisiona para efectuar estas pruebas tienen un costo (si se va por encima de los minutos de carga incluidos con nuestra suscripción de VSTS) por lo que hay que tener cuidado de no lanzar estas pruebas por cada commit que los desarrolladores efectúen, así que la sugerencia general seria tener un sitio de DEV donde se despliegue continuamente pero sin efectuar las pruebas de cargar, luego definiríamos un sitio QA (por ejemplo) al cual se desplegara ya sea de manera manual o de manera programada el contenido existente en DEV (con Release Management lo que se despliega son paquetes que no necesariamente son recién compilados) y al efectuar ese despliegue se lanzaran las pruebas de carga, las cuales si son exitosas indicar que en el proceso de despliegue esta listo para ser sometido a aprobación (si lo hemos definido así) para decidir su pase a otro entorno.

Con estas consideraciones en mente procederemos con nuestra primera prueba para lo cual no sera necesario usar Visual Studio simplemente agregar un paso adicional a nuestro proceso de despliegue, esto es porque a veces lo que nos interesa es simplemente ver que tan bien resiste una URL en concreto a cierta petición.

Para esto vamos a la pestaña de Release de nuestra instalación de VSTS, elegimos nuestro plan actual, seleccionamos el «entorno lógico» sobre el cual agregaremos nuestra prueba de carga y agregamos el Step de Cloud-based Web Performance Test, así:

Clipboard01

Clipboard02

Ok, ahora toca parametrizar el paso para lo cual dejaremos los parámetros mas o menos así, en breve explicare el significado de cada parámetro:

Clipboard06

Antes de proseguir prestemos atención al parámetro Registered connection, lo que ocurre es que cada prueba de carga se hace con cargo a los recursos y facturación de una cuenta de VSTS y podría darse el caso de que la organización tenga mas de una instancia de VSTS, así que corresponde indicar explícitamente dicha cuenta, así que hagamos clic sobre el enlace que dice Manage, que nos abrirá una nueva pestaña en el navegador para agregar un Endpoint (como ya hicimos anteriormente para enlazar Sonar y la cuenta de Azure), y en este caso elegiremos Generic, así:

Clipboard04Y llenamos los parametros de configuración de nuestra instancia de VSTS, pero ojo, al hacerlo deberemos utilizar los datos de nuestra conexión alterna a VSTS, algo de lo que hablamos hace tiempo cuando empezamos a trastear con Git.

Clipboard05

Listo, ya hemos enlazado nuestra prueba de carga a nuestra cuenta de VSTS,  personalmente yo agregaria un checkbox que permita usar la instancia actual y no hacer nada mas, pero siempre es bueno tener una conexión alterna a VSTS especialmente de cara a la integración con herramientas de terceros en Git.

Ok, antes de grabar repasemos los parámetros que estamos configurando:

  • Registered connection: como lo vimos, la instancia de VSTS sobre la cual se hara la facturación de esta prueba de carga.
  • Website Url: La dirección que vamos a probar, en este caso estoy probando la raiz del site (o mejor dicho del slot) en que acabo de hacer el despliegue, cabe indicar que tranquilamente podria haber colocado cualquier URL interna de nuestro site, o peor aun, una URL totalmente externa no manejada por nosotros, pero eso no queremos ¿verdad?
  • Test Name: El nombre con el que identificaremos a esta prueba.
  • User Load: La cantidad de usuarios supuestos que se estarán conectando a nuestra URL.
  • Run Duration (sec): El tiempo de duración de la prueba.
  • Load Location: La zona geográfica de Azure desde donde se hará la prueba, es muy interesante y conveniente hacer la prueba desde una zona que no sea la que aloja a nuestro site, en mi caso la URL esta alojada en East-2, así que la prueba la estoy lanzando desde West.

Marcamos Enabled y grabamos, ya estamos listos para empezar, asi que lo mas sencillo sera hacer un cambio en nuestro codigo fuente, lanzar una nueva Build manualmente, o si queremos divertirnos relanzar un paquete antiguo al ciclo de Release, en todo caso esperamos un poco y veamos cuando nuestra Release se empieza a ejecutar y llega al paso que hemos agregado:

Clipboard08

Para después terminar:

Clipboard09Normalmente pasaríamos a aprobar o rechazar esta Release, pero ahora me interesa conocer los resultados de nuestra prueba, así que vamos a la pestaña Tests, y elegimos la opción LoadTest, para luego seleccionar la prueba mas reciente (en mi caso tengo algunas pruebas anteriores, pero si es la primera vez deberías tener una sola prueba en tu lista).

Clipboard10

Y así entramos a un detalle de los resultados de la prueba:

Clipboard11

Notemos algo interesante, aparentemente nuestra prueba salio ok (o sea, no hubo errores 500 o timeouts) pero el panel nos indica 2 errores, así que veamos el detalle:

Clipboard12

En mi caso el mensaje de error dice «The value 85.10138 exceeds the warning threshold value of 75«, lo cual nos viene a indicar no un error en el sitio que estamos probando sino un exceso en la capacidad de la instancia provisionada para hacer la prueba, esto apunta a que forzamos la maquina dandole 250 usuarios concurrentes, lo cual se relaciona a las pocas opciones de configuración que ofrece este tipo de prueba.

Listo, sencillo y ya podemos empezar a sacar conclusiones, pero como verán esta prueba es muy sencilla y en adición al ya mencionado problema del threshold no permite saber si por ejemplo el comportamiento es diferente desde un browser u otro, desde un tipo de red, etc, para lograr este tipo de análisis lo que se nos ofrece es la posibilidad de crear un test muy detallado desde dentro de Visual Studio y que cuando se efectúe el despliegue Visual Studio Team Services pueda «leer» todos estos parámetros archivados y ejecutar tras bastidores las pruebas programadas, esto sera tema de nuestro próximo post, de momento sugiero familiarizarse con este tipo de prueba, pues los conceptos siguen siendo validos cuando los escalemos, aparte de que estas pruebas tienen su lugar si  hacemos peticiones Get que luego repercuten a nuestra BD, o queremos probar la mejora si usamos un servicio de cache, etc.

Espero sus comentarios 😉

Completando el ciclo de ALM: Release Management (II)

Prosiguiendo con la entrega anterior, pasamos a los pasos 4 y 5 de este proceso que consiste en configurar cada uno de los entornos de despliegue en los que se va a desplegar la aplicación, la idea que implementaremos en esta ocasión sera la siguiente:

  • Cada vez que se efectué un cambio en el código fuente se disparara una Build (Integración Continua, esto ya lo tenemos bien sabido)
  • Si la Build es exitosa se disparara una Release
  • El primer paso de la Release sera desplegar automáticamente al entorno QA
  • Efectuado el despliegue a QA, un aprobador humano dará su conformidad, o no, al contenido desplegado
  • Si el despliegue en QA ha sido aprobado, recién entonces se efectuara el despliegue al entorno PRO

Obvio que este esquema puede extenderse para incorporar mas entornos, para añadir pruebas de carga en la nube, distintas categorías entre aprobadores, etc, pero para demostrar el concepto esta prueba sera suficiente.

De momento vamos a identificar correctamente nuestros entornos, así que nos vamos al entorno llamado por defecto «Default Environment» y le cambiamos el nombre…

Clipboard01

A QA:

Clipboard02

Finish Reading: Completando el ciclo de ALM: Release Management (II)

Completando el ciclo de ALM: Release Management (I)

Repasemos un poco lo que hemos aprendido hasta ahora: sabemos como configurar nuestro Visual Studio On… digo Visual Studio Team Services para crear un Team Project, desarrollar una aplicación en ASP.NET para finalmente compilar y desplegar dicha aplicación cada vez que efectuemos un cambio en el código fuente (Integración Continua).

Todo perfecto, pero recordemos que si queremos definir un conjunto de entornos (QA, DEV, STA, PRO…) entre los que sucesivamente vayamos escalando nuestra aplicación, hacíamos uso de la funcionalidad de Azure llamada «slots», la cual de una manera sencilla nos permitía intercambiar contenidos entre los diversos entornos, esta técnica es muy practica y nos permite cierto grado de protección a fin de poder revisar nuestros cambios antes de que hagamos el despliegue en el entorno definitivo.

Devops-release

Ahora tenemos una opción adicional, y es que desde la gestión que hace VSTS/TFS manejemos de manera separada la forma en que nuestro «paquete» va siendo desplegado y escalado en los entornos de aprobación hasta su destino «final»: producción, y al hacerlo logramos introducir un factor que sera de gran utilidad de cara al aseguramiento de la calidad de lo entregado: la aprobación de versiones, vale decir que a una persona (o grupo de personas) se le notifica que hay una nueva versión de la aplicación en determinado entorno y que le corresponde dar su conformidad a dicha versión, lo cual derivara en que la versión en cuestión sea propagada al siguiente entorno, y así sucesivamente. Adicionalmente este cambio nos va a permitir manejar ya no solo el historial de nuestras Builds sino tambien el historial de nuestros despliegues, pudiendo ver si todos los despliegues propuestos han pasado los tests de carga y/o fueron aprobados satisfactoriamente por QA o el cliente.

Finish Reading: Completando el ciclo de ALM: Release Management (I)