Cómo establecer límites de memoria para aplicaciones Java en contenedores Docker
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:
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)