Cómo asignar memoria de forma dinámica al entorno de AWS Elastic Beanstalk contenedor multi-acoplador que ejecuta aplicaciones Java

8

Quiero exprimir cada onza posible del uso de la capa de frijol elástico libre.

Mi backend está construido como un conjunto de microservicios (usando ktor). Tengo 5 microservicios para ser precisos. Todos estos están acoplados y estoy tratando de ejecutarlos todos en la misma pequeña instancia t2.micro (gratuita) de beanstalk elástico con el entorno de imagen multi-acoplador

Java es Java, le gusta dejar inactivo alrededor de 200 MB de RAM por contenedor acoplable para incluso el microservicio más simple.

Entonces, t2.micro te da 1GB de RAM. Tengo 5 contenedores acoplables de microservicios que requieren al menos 200 MB cada uno = realmente cerca.

El problema es que la memoria casi siempre está cerca del 100% casi todo el tiempo.

Entonces, ¿hay alguna forma de asignar dinámicamente memoria a los contenedores acoplables dependiendo de cuánto es gratis y cuán desesperadamente lo necesita un contenedor?

Digamos que un contenedor está haciendo un trabajo pesado mientras que los otros están en su mayoría inactivos, quiero dirigir algo de RAM hacia el contenedor haciendo la tarea pesada y una vez que la tarea haya terminado, vuelva a la asignación de RAM igual por contenedor.

¿Hay alguna forma de hacer esto?

Aditya Anand
fuente

Respuestas:

1

Puede usar docker update --memory-reservation xxx <container>para cambiar la asignación de memoria de límite flexible para un contenedor mientras se está ejecutando. Docker empujará suavemente los contenedores hacia sus límites suaves cuando la memoria general sea baja. Por lo tanto, podría establecer límites suaves de, digamos 150 MB para todos sus contenedores, y luego aumentar uno de ellos cuando sepa que tiene trabajo adicional por hacer.

La documentación de Docker sobre límites suaves no es tan buena, la documentación del kernel para CGroup Memory lo explica mejor.

CantankerousBullMoose
fuente
Gracias, lo investigaré más. Aunque idealmente desearía una solución que, por ejemplo: supervise dinámicamente el uso de memoria de múltiples contenedores y brinde más memoria a la que se está ejecutando muy cerca de la más alta en cualquier momento (para maximizar el rendimiento). Entonces, en un servidor, no sería realmente factible seguir cambiando manualmente los límites, ya que podrían depender de la sincronización del trabajo cron, el tráfico, etc.
Aditya Anand
¿En qué se diferencia eso de no tener ninguna administración de memoria? Si una instancia de JVM en un contenedor solicita asignación de memoria y otra instancia de JVM en otro contenedor retiene espacio de almacenamiento dinámico no utilizado, la segunda JVM lo abandonará y dejará que el primero lo tenga ... ¿Verdad?
CantankerousBullMoose
¿Es eso así? ¿Se puede vincular a una fuente autorizada sobre el tema? En mi experiencia, parece ser un poco aleatorio. A veces, una instancia opta por retener el montón no utilizado, incluso si priva de hambre a la otra instancia, en cuyo caso las otras instancias comienzan a utilizar una mayor cantidad de memoria paginada, lo que ralentiza las cosas.
Aditya Anand
1
Esto está comenzando a parecer un problema más de Java que un docker. No he pasado mucho tiempo jugando con ellos, pero se supone que -XX: MaxHeapFreeRatio y -XX: MinHeapFreeRatio controlan cuán agresivamente toma la JVM y le da memoria al sistema operativo. ¿Quizás eso te daría resultados más consistentes? Los documentos de Oracle en Garbage Collection tienen algunos detalles sobre esas banderas.
CantankerousBullMoose
Sí, de nuevo, eso realmente solo controla la configuración estática inicial que puedo proporcionar a un proceso de Java, no cómo puedo administrar dinámicamente la memoria asignada a diferentes procesos según la necesidad.
Aditya Anand