Problemas comunes con el rendimiento de los contenedores y cómo solucionarlos

Por septiembre 13, 2018

Los contenedores permiten un enfoque de DevOps robusto, posibilitando que los desarrolladores monten software en contenedores de fácil implementación y rendimiento consistente en entornos de desarrollo y producción.

Pequeños y ligeros, los contenedores utilizan menos recursos que los hosts virtuales. Se inician, se detienen y migran rápidamente entre los servidores y ayudan a dividir las aplicaciones monolíticas en componentes menores, en una arquitectura de microservicios.

Sin embargo, los contenedores también pueden presentar nuevos desafíos, como los relacionados con el rendimiento. En este artículo, analizo algunos problemas que he tenido en el desempeño de contenedores y explico cómo resolverlos o evitarlos.

Los contenedores son como “cajas negras”

Los contenedores llevan al extremo el desarrollo y la prueba de caja negra y tienden a ser subestimados en revisiones de códigos, en la monitorización de componentes internos e incluso en revisiones de diseño de nivel superior. Cada etapa proporciona una oportunidad para garantizar el rendimiento necesario (es decir, los acuerdos de nivel de servicio o SLAs), identificar posibles problemas y obstáculos de desempeño lo más rápido posible y mejorar el rendimiento antes de la implementación de los contenedores.

La solución es, sobre todo, cultural y está relacionada con el proceso. Aunque un contenedor incorpore alguna área de la funcionalidad de producción, no deja de someterla a revisiones de diseño y códigos a lo largo de todo el proceso.

Pruebas de estrés subestimadas

Los contenedores permiten la migración e identificación de un servidor con facilidad, rapidez y dinamismo, expandiéndose de forma flexible para satisfacer las necesidades del usuario y del sistema según la demanda (generalmente en entornos en la nube que también ofrecen soporte a este recurso). Esto puede hacer que los desarrolladores, e incluso los gerentes de QA, crean que la prueba de estrés no sea necesaria – la herramienta de gestión de contenedores simplemente genera instancias adicionales. Un “corolario” es la falta de pruebas en distintos ambientes, ya sea entre proveedores o entre diferentes soluciones de un proveedor o datacenter.

Nuevamente, la solución es sobre todo, cultural y relacionada con el proceso: utilice las herramientas para simular un gran número de usuarios tanto en escenarios aleatorios como definidos con estándares de uso. No se olvide de considerar además los valores promedios, ya que estos encubren los valores atípicos. Hay herramientas, como Blazemeter (Figura 1), que hacen un excelente mapeo de promedios, creando histogramas mapeados para mostrar la carga a lo largo del tiempo. Estas herramientas se vuelven aún más valiosas cuando se incorporan a las herramientas de gestión de rendimiento de aplicaciones (APM – Application Performance Management), que proporcionan resultados de prueba de carga y rendimiento y permiten la verificación y el análisis detallados.

Figura 1 – La prueba de carga efectiva es importante para evitar problemas de desempeño del contenedor.

Además, las pruebas de rendimiento se deben realizar continuamente para todas las versiones. También es interesante realizar combinaciones aleatorias de pruebas de rendimiento, no sólo pruebas individuales. La interferencia y la limitación de algún recurso pueden ayudar a simular eventos simultáneos aleatorios que ocurren en la realidad.

Problemas relacionados con el tamaño del contenedor

El tamaño del contenedor puede afectar negativamente la migración y la generación de instancias del mismo. Pruebas precisas pueden ayudar a identificar qué contenedores necesitan ser desmontados para evitar pérdidas. Por otra parte, existen herramientas y técnicas que ayudan a hacer que el proceso de migración de instancia de contenedor sea más eficiente, como las técnicas de transferencia y paginación de memoria.

Falta de desarrollo de contenedores estandarizados

Las diversas estructuras de contenedores y microservicios se ven afectadas de formas diferentes en términos de rendimiento. Los entornos de host del contenedor, la capacidad de RAM física, la infraestructura de red, el sistema operativo de la plataforma y la arquitectura de los entornos en la nube que afectan el desempeño de la estructura varían mucho. Siempre que sea posible, utilice estructuras y herramientas de contenedores consistentes. La agregación de log, por ejemplo, es importante cuando cada uno de los componentes de contenedores separados registra mensajes que forman parte de una transacción de aplicaciones. La estandarización de una única estructura de log con soporte a contenedores aumentará la confiabilidad y la transparencia.

Cómo manejar la interferencia

Este problema se relaciona principalmente con las implementaciones de “contenedor como servicio” (CaaS – Container as a Service) en el entorno en la nube pública, en la que los servidores host subyacentes e incluso la infraestructura de red se comparten en un entorno de multi-tenancy, es decir, con varios elementos. No hay mucho qué hacer para protegerse de eso, en el caso de servicios o aplicaciones basadas en contenedores particularmente sensibles, la solución puede ser evitar un proveedor de nube específico o negociar un SLA para limitar o evitar este problema.

La monitorización y las pruebas realizadas durante el desarrollo con herramientas que simulan interferencia y carga del host alertan sobre el impacto de este posible problema. De la misma forma, la implementación de herramientas de monitorización de contenedores para capturar interferencias ruidosas de otros componentes garantiza el servicio adecuado de su proveedor.

Limitaciones de recursos del host

Al profundizarse en la monitorización de implementaciones de host de contenedor, usted debe estar consciente de la actividad y la carga en los servidores de host subyacentes, independientemente de la implementación. Ya he visto un impacto negativo cuando el host subyacente del contenedor presenta una limitación de recursos. Aunque un enfoque basado en contenedores pueda ser más ligero que la virtualización por sí misma, la ejecución de una gran cantidad de contenedores generalmente sobrecarga su infraestructura más que la ejecución de una aplicación monolítica.

Por ejemplo, generalmente conviene dividir procesos y servicios individuales en contenedores separados. Su implementación en un conjunto limitado de servidores físicos, con agentes de equilibrio de carga asociados, servicios de monitorización y servicios de failover, resulta en un mayor uso y demanda de los recursos del host.

Para resolver o evitar esto, utilice soluciones de un solo proveedor para el almacenamiento en cluster y la monitorización de contenedores y servicios para los distintos contenedores, como el registro en log. Asimismo, es necesario adoptar una monitorización que tenga en cuenta las estadísticas del host y del sistema, como el uso de la CPU del host, métricas de I/O, memoria disponible, ancho de banda de la red e incluso detalles de la arquitectura interna del sistema operativo. No lo deje para cuando su aplicación esté en producción para confiar solamente en la monitorización, pues será demasiado tarde. En su lugar, utilice herramientas como JMeter y Selenium (u otras específicas para su plataforma) para simular la carga real con precisión.

Prueba de interacciones del contenedor

Yendo un poco más allá, he notado que muchos problemas de rendimiento implican la falta de una visión holística del rendimiento y, en su lugar, el rendimiento se considera en contenedores individuales. Las estrategias de prueba deben comenzar con recursos basados en contenedores y pruebas de carga (y monitorización de producción) y también considerar la visión del usuario del sistema. Por ejemplo, los problemas generalmente surgen cuando los contenedores y los sistemas interactúan, y solamente las pruebas de punta a punta lo muestran.

Observe este caso: una aplicación en la que trabajé usaba muchos contenedores, pero dos de ellos interactuaban de una manera que afectaba el desempeño, algo difícil de descubrir sin las pruebas adecuadas. En este ejemplo, los dos contenedores usaban recursos basados en un sistema de archivos, y aunque cada uno de ellos trabajara con archivos distintos y de formas diferentes, los efectos causados por uno de ellos en el kernel del sistema operativo afectaban al otro.

Esto demuestra que la prueba de aislamiento de contenedores no es suficiente. Es fundamental ejecutar el análisis de la causa raíz en el caso de problemas de rendimiento que afectan a toda la aplicación. También es necesario realizar pruebas de interacciones para saber lo que está sucediendo en todas las capas de su implementación. Además, al aplicar el análisis de la causa raíz, la creación de imágenes Docker generalmente obstaculiza la identificación del origen del problema. Para resolverlo, evite crear imágenes de contenedores en ejecución o el uso de las dependencias más recientes. Utilice versiones específicas de la capa de contenedor y genere imágenes utilizando una fuente de contenedor conocida.

Demandas de la red relacionadas con el contenedor

La gran escala de contenedores en grandes implementaciones provoca mucho estrés en la red. Las aplicaciones basadas en contenedores tienden a distribuirse más, dependiendo más del rendimiento de la red en un entorno virtualizado o SDN. Ignorar el desempeño de la red (y centrarse sólo en el rendimiento de la aplicación y de la base de datos, por ejemplo) puede convertirse rápidamente en un gran problema.

Los desarrolladores generalmente crean y prueban los contenedores en su entorno local con un puente de red o basado en NAT. Esto funciona bien, pero puede encubrir problemas de desempeño que surgen cuando se utilizan en datacenters de producción o en implementaciones basadas en la nube. La solución es incluir pruebas de integración continua que simulen con precisión el entorno de producción (a propósito, este es un principio básico del DevOps) para descubrir problemas de comportamiento y rendimiento de red y descubrir complejidades en la actividad de red que dificultarán la monitorización.

Utilice una herramienta que permita generar un tráfico de red real para probar los efectos en diferentes configuraciones de red antes de la implementación. Por ejemplo, puede probar diferentes técnicas de conexión de red, algoritmos de equilibrio de carga, configuraciones de cluster y la comunicación entre contenedores.

API legadas

Con relación al aspecto presentado anteriormente, las aplicaciones basadas en contenedores generalmente se originan a partir de aplicaciones monolíticas o corporativas ya existentes. Por lo tanto, las API internas pueden no ser ideales para el uso entre contenedores que cubren toda la red. El resultado de esto puede ser el acceso remoto ineficiente, desplazamientos excesivos o datos transmitidos en formatos no optimizados. Además de las ineficiencias de datos y de red, el procesamiento interno del contenedor puede no haber sido construido para el acceso remoto, resultando en una alta utilización de los recursos.

Por ejemplo, cuando las solicitudes asincrónicas de API se extienden entre contenedores, pueden resultar en un gran número de threads generados para REST u otra comunicación. Los estándares N+1 generalmente utilizados para la redundancia también pueden causar problemas de rendimiento de la red con los contenedores que se extienden a las bases de datos, dispositivos REST, servicios Web, almacenamiento en caché, y otros ítems.

Conclusión: Una estrategia de rendimiento de contenedores

Una buena estrategia de rendimiento de contenedores empieza con las especificaciones de su aplicación y las garantías de SLA del usuario, que deben incluir procesos, como revisiones de definición de código y contenedor, pruebas específicas de contenedor y pruebas de punta a punta de estrés/carga del usuario, además de métricas de sistema operativo, red y hardware. Las estrategias de expansión de desempeño en el futuro también incluyen soporte de hardware, integración continua y pruebas, además de automatización de versiones y el modelado de tiempo de ejecución de contenedor para ayudar a predecir problemas de rendimiento antes de llegar a los usuarios.

Independientemente de su aplicación, el proceso de desarrollo o estrategia de prueba de rendimiento, alianzas con los proveedores y el uso de las herramientas correctas (como las mencionadas aquí) contribuyen en gran manera a atender los requisitos de desempeño del contenedor.

Eric Bruno es autor y editor de varias publicaciones online, con más de 20 años de experiencia en el área de Tecnología de la Información. Asimismo, es un moderador y orador muy solicitado para una gran cantidad de conferencias y otros eventos sobre tecnologías que varían desde desktop hasta datacenter. Desde hace más de diez años escribe artículos, textos para blogs, white papers y libros sobre arquitectura y desarrollo de software. También es arquitecto corporativo, desarrollador y analista del sector con experiencia en ciclo de vida completo, arquitectura, diseño y desarrollo de software de gran escala para empresas de todo el mundo. Su trabajo incluye el desarrollo de sistemas altamente distribuidos, desarrollos para la web en varias capas, desarrollos en tiempo real y el desarrollo de software transaccional. Vea su trabajo editorial online en www.ericbruno.com.