Red de conocimiento informático - Conocimiento informático - Cómo establecer límites de memoria para aplicaciones Java en contenedores Docker

Cómo establecer límites de memoria para aplicaciones Java en contenedores Docker

Recientemente, hablé con algunos colegas de Alibaba sobre el escenario de usar Docker para implementar aplicaciones Java. Una de las preocupaciones comunes era cómo establecer el límite de memoria de la JVM en el contenedor.

Si utiliza la imagen oficial de Java o una imagen de Docker creada sobre la imagen de Java, puede configurar fácilmente los parámetros de memoria JVM pasando la variable de entorno JAVA_OPTS.

Por ejemplo, para la imagen oficial de Tomcat, podemos ejecutar el siguiente comando para iniciar una instancia de Tomcat con una memoria máxima de 512 M

docker run --rm -e JAVA_OPTS='-Xmx512m' tomcat:8

En los registros, está claro que la configuración ha tenido efecto "Argumento de línea de comando: -Xmx512m"

02-Apr-2016 12:46:26.970 INFO [main] org.apache .catalina.startup.VersionLoggerListener .log Versión del servidor: Apache Tomcat/8.0.32

02-abr-2016 12:46:26.974 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Servidor construido: 2 de febrero de 2016 19:34:53 UTC

02-abr-2016 12:46:26.975 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Número de servidor: 8.0.32.0

02-abr-2016 12:46:26.975 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Nombre del sistema operativo: Linux

02-abr-2016 12:46 :26.975 INFORMACIÓN [principal] ] org.apache.catalina.startup.OS versión: 4.1.19-boot2docker

02-Abr-2016 12:46:26.975 INFORMACIÓN [principal] org.apache.catalina. startup.VersionLoggerListener.log Arquitectura: amd64

02-Apr-2016 12:46:26.975 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Inicio de Java:/usr/lib/jvm/ java-7-openjdk -amd64/jre

02-abr-2016 12:46:26.976 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Versión de JVM: 1.7.0_95-b00

02-abr-2016 12:46:26.976 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Proveedor de JVM: Oracle Corporation

02-abr-2016 12: 46:26.977 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:/usr/local/ tomcat

02-abr-2016 12:46:26.977 INFORMACIÓN [principal] org.apache .catalina.startup.VersionLoggerListener.log CATALINA_HOME:/usr/local/tomcat

<

p>02-abr-2016 12:46:26.978 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Parámetros de la línea de comando: -Djava.util logging.config.file=/usr/local/tomcat/conf. /logging.properties

02-abr-2016 12:46:26.978 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log parámetros de línea de comando: -Djava.util.VersionLoggerListener.log línea de comando Parámetros: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

02-abr-2016 12:46:26.978 INFORMACIÓN [principal] org.apache.catalina.startup.VersionLoggerListener.log Parámetros de la línea de comando: -Xmx512m

...

Sin embargo, al implementar una aplicación contenedora Java en un clúster Docker, no basta con configurar los parámetros del montón de JVM; Es necesario restringir los recursos de memoria de los contenedores Docker:

1. Limitar la cantidad máxima de memoria utilizada por el contenedor para evitar daños al sistema u otras aplicaciones.

2. Posibilidad de programar Docker contenedores a la cantidad máxima de memoria disponible

2. Capacidad de programar contenedores Docker para que tengan la cantidad máxima de memoria disponible para que la utilice el sistema u otras aplicaciones. Programe el contenedor Docker en un nodo con suficiente memoria disponible para garantizar los recursos en ejecución requeridos por la aplicación

En cuanto al límite de asignación de recursos del contenedor, Docker proporciona los parámetros de inicio correspondientes

Para Memoria, lo más básico es limitar la cantidad de memoria utilizada por el contenedor mediante -meter

-m, --memory=""

Límite de memoria (formato: []). El número es un número entero positivo. El valor mínimo es 4M.

Entonces la pregunta es, para configurar correctamente el tamaño de la memoria del contenedor Docker, ¿no necesitamos pasar tanto el límite de memoria del contenedor como la variable de entorno JAVA_OPTS? El método es el siguiente:

docker run --rm -m 512m -e JAVA_OPTS='-Xmx512m' tomcat:8

Este método tiene dos problemas

1. Requiere que los administradores se aseguren de que la configuración de la memoria del contenedor y la memoria JVM coincidan; de lo contrario, se pueden producir errores

2 Al crear un contenedor, cuando se ajusta el límite de memoria del contenedor, las variables de entorno también necesitan. para restablecerse, lo que requiere reconstruir un nuevo contenedor

¿Hay alguna manera de hacer que la JVM en el contenedor se adapte automáticamente al límite de memoria del contenedor? Esto dará como resultado un enfoque más unificado para la gestión de recursos y simplificará la configuración.

Sabes que Docker implementa límites de recursos a través de CGroups. Desde la versión 1.7, Docker ha montado los cgroups locales del contenedor como de solo lectura en el sistema de archivos interno del contenedor, por lo que podemos usar la información de los cgroups dentro del contenedor para obtener los límites de recursos del sistema del contenedor actual.

Creé una imagen de muestra registro.aliyuncs.com/denverdino/tomcat:8-autoheap

cuyo código fuente está disponible en Github.

Se basa en la imagen oficial de Docker Tomcat y su script de inicio verifica los límites de memoria en el grupo CG y calcula el tamaño máximo del montón de JVM que se pasará a Tomcat. El código es el siguiente

#! /bin/bash

limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)

# Si no hay un limit_in_bytes predeterminado en el cgroup

if [ "$limit_in_bytes" -ne "9223372036854771712" ]

entonces

limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)

heap_size= $( expr $limit_in_megabytes - $RESERVED_MEGabytes)