En el post anterior hemos sentado las bases de qué es el chaos engineering y por qué debemos tenerlo en cuenta. Es hora de comenzar la iniciativa.

Antes de empezar a implementar nada, debemos analizar, junto con todos los grupos implicados en la organización, cómo vamos a abordar la estrategia de chaos engineering.

El método (ciclo de vida)

Una iniciativa de este tipo debemos llevarla a cabo de manera iterativa e incremental, como adelantamos en el anterior post. No podemos planificar la ejecución de experimentos directamente contra el entorno de producción ni sobre toda nuestra plataforma. Debemos diseñar un modelo que nos permita realizar experimentos sobre pequeñas partes de la misma, con un blast-radius limitado, y ser capaces de escalar a medida que vayamos generando confianza. No olvidemos que queremos aumentar la resiliencia de nuestras aplicaciones, por lo que será conveniente comenzar por los servicios más críticos.

Nos basaremos en el siguiente método para establecer nuestra estrategia de chaos engineering:

Podemos comenzar con la ejecución de experimentos sencillos. Suponiendo que nos encontramos en un entorno CNA, podríamos empezar provocando reinicios inesperados en algunas de las réplicas de uno de los microservicios que componen nuestra aplicación en el entorno de preproducción para comprobar cómo afecta este experimento. ¿Sigue funcionando la aplicación correctamente? ¿Provoca errores en cascada a otros microservicios? ¿Cómo afecta al rendimiento?

Durante la ejecución de este experimento, a la vez, estamos poniendo a prueba nuestro sistema de observabilidad ya que debemos ser capaces de entender cómo está afectando la ejecución del mismo a nuestras aplicaciones y a la plataforma en la que se ejecutan. Observando los resultados, comprobaremos si la hipótesis que hemos definido para nuestro experimento se ha cumplido. En caso contrario, debemos analizar las correcciones necesarias para que se cumpla, que pueden estar en múltiples elementos: configuraciones en los sistemas, en la red, código fuente de las aplicaciones… También puede ocurrir que no estemos interpretando correctamente las métricas obtenidas, en cuyo caso aprenderemos y mejoraremos nuestro sistema de monitorización durante este viaje.

Una vez ganemos confianza, podemos hacer crecer la complejidad de nuestros experimentos para hacerlos más sofisticados: introducir latencias de red, degradar el rendimiento provocando consumos inesperados de CPU y memoria, donde empezaremos a explorar las zonas grises de nuestra plataforma. También iremos ampliando poco a poco nuestro blast-radius, afectando a partes mayores de nuestras aplicaciones y siendo capaces de llegar incluso al entorno de producción.

Participantes

La preparación de la estrategia de caos afecta prácticamente a toda la compañía, y es por ello que el número de áreas que deben involucrarse en la definición es elevado aunque escalonado en función de sus distintas fases de preparación.

Negocio

La primera área involucrada, y desde la cual se debe comenzar a definir, es el área de negocio.

Como indicamos anteriormente, debemos analizar inicialmente los sistemas que consideramos más críticos, aquellos que realmente sustentan el negocio y sobre los que probablemente recaiga gran parte de la carga de trabajo a nivel global dentro del sistema.

Identificar los procesos críticos en una organización grande es, en muchas ocasiones, complicado. Contaremos distintas áreas de negocio involucradas, cada una con distintos objetivos y necesidades, por lo que obtendremos más de un flujo de negocio críticos.

Podremos obtener, además, información relacionada al volumen de negocio, distribución del mismo a lo largo del año, etc., que nos permitan priorizar y optimizar la estrategia en función de las distintas fases que diseñemos.

Responsables de tecnología

Durante todo el proceso de definición de la estrategia y ejecución del plan de chaos engineering es imprescindible que el equipo de tecnología esté involucrado. En muchas ocasiones, son ellos mismos los promotores de la iniciativa.

Trabajando de forma conjunta con negocio, los responsables de tecnología realizarán el mapeo entre los procesos identificados y los sistemas involucrados.

El equipo de responsables proporcionará, además, información sobre los sistemas, imprescindible a la hora de definir la estrategia: arquitectura utilizada, mecanismos de comunicación, tecnología sobre la que trabajan… de forma que podamos ir haciéndonos una idea de la envergadura del proyecto, del faseado a proponer y de los experimentos que deberíamos realizar.

Sistemas

Será pieza clave en este proceso. Normalmente recaerá sobre ellos la responsabilidad de implantar el sistema de ejecución de experimentos, desplegando las herramientas necesarias, así como la codificación de los experimentos a ejecutar mediante las mismas.

De forma adicional, serán normalmente los que mantengan la plataforma de observabilidad, generando también los dashboard necesarios para la correcta comprensión de los resultados o, bien, mejorando los ya existentes para que la interpretación de lo que está ocurriendo en los sistemas sea la adecuada.

Si el equipo de seguridad es independiente del de sistemas, es conveniente que se implique también en esta iniciativa, puesto que una de las responsabilidades de este equipo suele ser la de asegurar la continuidad del negocio.

Si bien la iniciativa de chaos engineering no puede sustituir otras orientadas a la certificación de ciertas normativas de seguridad, sí que puede complementarlas, convirtiéndose en un aliado que permita aumentar la resiliencia de nuestras aplicaciones.

Desarrollo

El equipo de desarrollo es el que ha implementado las aplicaciones y, por lo tanto, parte de las piezas que se van a testear.

Este equipo nos aportará detalles sobre los requisitos de cada uno de los servicios, limitaciones, mecanismos de comunicación (comunicación síncrona, asíncrona, envío de ficheros…).

Es importante comprobar que nuestros sistemas de observabilidad son capaces de trazar toda esta información, y debemos contar con el equipo de desarrollo para asegurar que los servicios proporcionan los datos necesarios.

Análisis de la infraestructura

El análisis de la infraestructura se realiza una vez se haya identificado un proceso de negocio sobre el que se quiere actuar y los sistemas que le dan soporte.

A partir de este punto, se requiere obtener información detallada para poder realizar un análisis adecuado. Desde nivel de infraestructura, comunicación, hasta las propias aplicaciones.

Empezaremos identificando todos los sistemas involucrados (directa e indirectamente) y generando un mapa de comunicaciones (a nivel de red) y distribución de la aplicaciones sobre los sistemas, además de indicar las dependencias de cada uno de ellos.

Algunas de las preguntas cuyas respuestas necesitaríamos conocer, y recorriendo la infraestructura desde el nivel más bajo al más alto, podrían ser las siguientes:

Infraestructura

Sabremos de esta forma qué tipo de integraciones y herramientas requeriremos para llevar a cabo los experimentos (no es lo mismo un experimento que trabaja sobre AWS que sobre VMWare por ejemplo).

En todo sistema va a haber límites conocidos, que por el hecho de ser conocidos debemos adherirnos a ellos (no tiene sentido probar algo que sabemos que no va a funcionar, pero sí que será necesario hacer que quede claro ese límite en los resultados del análisis que hagamos).

Estaríamos hablando de configuraciones activo/pasivo, del uso de balanceadores y de sus políticas, de cómo se comunican los distintos nodos (si es que hace falta), qué configuración de balanceo tienen, si existe posibilidad de que pueda suceder un split-brain… de todos los sistemas (incluyendo por supuesto bases de datos).

En este punto convendría también preguntar si es una “alta disponibilidad de verdad”. En más de una ocasión nos encontraremos ante una supuesta alta disponibilidad basada en varios nodos, pero en la que si un nodo cae, los nodos restantes no son capaces de asumir toda la carga de trabajo, haciendo que todo el sistema colapse.

Aplicaciones/Infraestructura

En caso de tenerla, es necesario conocer qué métricas se utilizan para autoescalar y cuáles son los límites configurados para el mismo. En este caso, estaríamos subiendo un poco más en el nivel y no hablamos únicamente de la propia infraestructura (un nodo), sino también del nivel de aplicación.

Es importante conocer el tiempo que tarda el sistema desde la detección de la necesidad de escalar hasta que el escalado es efectivo y, sobre todo, si el proceso de autoescalado conlleva algún incremento severo en la carga general del sistema. En muchas ocasiones, escalar un nodo implica el rebalanceo de información o de carga, lo que puede generar un estrés al sistema. Este tipo de escalado en un sistema ya estresado de por sí puede ser fatal.

Es interesante preguntar también si el auto-escalado conlleva, además, algún tipo de política de escalado desde el punto de vista de las comunicaciones.

Finalmente, conviene conocer si las capacidades de autoescalado son en los dos sentidos, tanto para incrementar recursos como para liberarlos.

Al igual que en el punto anterior, nos referimos a niveles de infraestructura (sistemas y comunicaciones) y de aplicación, e igualmente necesitamos saber cuánto tiempo se tarda en detectar un error / caída, cuánto tarda en recuperarse, qué medidas se toman para esta recuperación.

Aplicación

Es información que ya se debería saber, ya que generalmente son parámetros de configuración. Algunos de estos límites podrían ser: ¿Cuántas conexiones simultáneas permite (podría aplicar a base de datos o a servicios web)? ¿Utiliza un pool de conexiones? ¿Cuántas conexiones genera / necesita?

De igual manera que se ha comentado anteriormente, no tiene sentido probar cosas que se sabe de antemano que van a fallar, pero en este caso podríamos ir un paso más allá. Por ejemplo: si un servicio está llegando al límite de conexiones, ¿autoescala? O, incluso, si el servicio escala, los sistemas de los que depende (una base de datos, por ejemplo), ¿soportan el incremento en el número de conexiones?

Aquí estaríamos analizando no un fallo de un componente, sino la repercusión que tiene ese fallo en el resto: ¿existe algún mecanismo que gestione estos posibles fallos para que no se transmitan, generando un fallo en cascada de todos los demás?

En la pregunta anterior, estaríamos comprobando qué sucede cuando hay una respuesta de fallo. En esta buscaríamos ver qué sucede cuando directamente no hay respuesta, es decir, se hace una petición a un componente y este no responde hasta que se produce el time-out. Esta situación puede tener muchísimas consecuencias (acumulación de peticiones en cascada, generación consecutiva de time-outs componente por componente…).

Mecanismos de observabilidad

Todas estas cuestiones son, únicamente, una muestra de las preguntas comunes que deberíamos realizar cuando estamos analizando un sistema. Estas preguntas, en función del caso de uso, pueden ser totalmente distintas. Si os fijáis, no hemos incluido prácticamente ninguna respecto a problemas de simple degradación del servicio (que no pérdida), o gestión de comunicaciones asíncronas... por poner dos ejemplos.

Estas preguntas nos van a dar mucha información de cara a qué tipo de hipótesis debemos realizar y, en algunos casos, nos dirán exactamente la prueba y la configuración, por lo que son un buen comienzo de cara a preparar todo el trabajo.

Es importantísimo tener en cuenta que para cada una de estas preguntas necesitaremos conocer los mecanismos existentes para la detección de los mismos, es decir, con qué mecanismos de observabilidad contamos. Estos mecanismos son imprescindibles para poder evaluar el sistema y conocer si el resultado es o no aceptable.

Definición de objetivos y métricas

Cada hipótesis que debamos probar con nuestras pruebas debe venir acompañada de un objetivo (o varios) medible, que deben cumplirse para darla por cumplida o fallida.

Para hacernos una idea: supongamos que nuestra hipótesis plantea que nuestro sistema, basado en dos nodos activo / activo, cumple con el requisito de alta disponibilidad. En esta situación, nuestro experimento podría ser tan sencillo como deshabilitar un nodo (hacer que el balanceador dirija toda la carga hacia el otro), o podríamos complicarlo haciendo que uno de los nodos degradase su rendimiento (provocando alto consumo de CPU o añadiendo latencia en sus peticiones). Si nos vamos al caso extremo, podríamos matar uno de los nodos.

En todos estos casos, necesitamos definir unos objetivos que midan si el sistema funciona correctamente. Estos objetivos podrían ser:

Hay que tener en cuenta que cada hipótesis llevará asociada unos objetivos distintos. En este ejemplo nos hemos centrado principalmente en el volumen de tráfico, por ser generalmente la consecuencia más relevante.

Todos estos inputs nos permitirán generar una plantilla donde vamos a recoger toda esta información necesaria de cara a poder codificar los experimentos:

En los próximos posts aterrizaremos ejemplos concretos que aplicaremos a nuestra infraestructura.

Definición del plan de emergencia / rollback

Simular un entorno de producción no siempre es sencillo. Los volúmenes de carga de trabajo o las casuísticas propias de los entornos hacen que, en ocasiones, tenga sentido extender cierto tipo de pruebas a los entornos productivos.

En estas situaciones, siempre hay que tener presente un plan de emergencia o mecanismos para deshacer el caos producido por los experimentos que realicemos.

La forma de preparar este plan puede ser diverso: en algunos casos lo integraremos dentro de la propia herramienta / framework para generar el caos en el que nos basemos, y en otras es posible que tengamos que implementar algunos scripts o tener preparados comandos que hagan que el sistema vuelva a la normalidad.

Aunque parece obvio, vale la pena remarcarlo: todas las pruebas de caos, incluyendo el plan de emergencia / rollback, deben probarse y validarse en todos los entornos previos (desarrollo, integración, pre-productivo…). Una vez en el entorno productivo, utilizaremos las horas valle o las horas de baja carga para comprobar tantos los experimentos como el plan de emergencia.

Todos estas validaciones nos permitirán llegar con cierta confianza a las pruebas en un entorno productivo con una carga normal.

¿Cuándo se debe definir la estrategia de caos?

Nuestra iniciativa de chaos engineering va a cambiar la forma en la que diseñamos nuestras aplicaciones y sistemas, siempre pensando en aumentar su resiliencia. Es por ello que, si estamos diseñando una nueva aplicación o un nuevo sistema donde esta aplicación va a vivir, debemos tener en cuenta desde esta fase de diseño cuáles son los experimentos que vamos a realizar y ejecutar. Solo si pensamos de esta forma, la estrategia tendrá éxito. En este caso, puede ser interesante incluir la ejecución de pruebas de carga o de experimentos de chaos como parte de nuestro flujo de CI/CD, para que los equipos de desarrollo puedan beneficiarse, incluso desde etapas tempranas de sus flujos de desarrollo.

Por otro lado, si es nuestra primera incursión en una iniciativa de este tipo, tendrá también sentido realizar el proceso inverso: con las aplicaciones y sistemas en producción, tenemos que pensar en qué experimentos tendrían sentido, aprovechando nuestro conocimiento sobre las aplicaciones existentes y enfocados a mejorar su resiliencia, aprovechando problemas o, incluso, pérdidas de servicio ocurridas en el pasado.

Conclusión

El objetivo final de nuestra iniciativa de chaos engineering debería ser el construir una mejor plataforma que dé el mejor servicio posible a los usuarios, y por tanto, supone un reto común para todo el equipo.

Una planificación adecuada de la estrategia a seguir es un paso imprescindible para llevar a buen puerto una iniciativa de este tipo.

El ejercicio de selección y priorización de experimentos debe ser diseñado entre todas las áreas involucradas en el producto. Es un reto común de todos, no solo del área de operaciones o de desarrollo.

Se debe poner en el centro de todas las decisiones al usuario. El objetivo en sí mismo no debe ser romper partes de la plataforma, sino buscar mejorar la confianza en las áreas que más valor dan a nuestros clientes y a nuestro negocio. Por tanto, involucrar a negocio desde el inicio es fundamental, tanto para definir el steady-state como para priorizar los experimentos, interpretar los resultados y consolidar el conocimiento adquirido.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.