Docker镜像的jvm内存参数自动配置
需求背景
在k8s的集群中,往往有个这样的场景:容器启动时会对内存资源进行限制,因此我们一般也会在构建镜像的Dockerfile文件中固定配置好jvm的内存分配大小。这样存在一个问题,当我们容器存在jvm内存不足问题,需要紧急扩容时。容器中的jvm内存分配并不会自动随着容器内存资源的增加而调高,而是需要重新修改Dockerfile中的jvm参数,并构建镜像才行,并需要对整个应用集群进行滚动发版。这样会导致集群扩容的灵活性降低。
方案介绍
容器内应用启动一般都是先对容器环境进行初始化启动后,在对应用进行启动。容器启动后相应的容器自身的内存资源也已经完成分配。因此我们可以在构建镜像中,将应用的启动托管给容器内的一个shell脚本,由脚本根据容器的资源情况,计算出对应的jvm参数后,在由脚本来对jar应用进行启动,并自动携带计算好的jvm参数。前置要求
1、你需要把下列具体事项的shell代码复制到你的基础镜像中,重新构建为一个新的基础镜像。
2、容器内应用的启动方式应该修改为启动shell文件,由shell文件对jar包进行启动。例如
ENTRYPOINT [“/bin/bash”]
CMD [“/root/start.sh”]
3、为了让shell脚本可以启动你的jar,你需要在Dockerfile中配置一个环境变量,APP_PATH用于告诉脚本你的jar路径地址。例如:
ENV APP_PATH /app/auxt/
2、容器内应用的启动方式应该修改为启动shell文件,由shell文件对jar包进行启动。例如
ENTRYPOINT [“/bin/bash”]
CMD [“/root/start.sh”]
3、为了让shell脚本可以启动你的jar,你需要在Dockerfile中配置一个环境变量,APP_PATH用于告诉脚本你的jar路径地址。例如:
ENV APP_PATH /app/auxt/
具体实现
#!/bin/bash
##自动化配置jvm参数
limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
if [ "$limit_in_bytes" -ne "9223372036854771712" ];
then
limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
RESERVED_MEGABYTES=$(expr $limit_in_megabytes \* 5 \/ 10 )
heap_size=$(expr $limit_in_megabytes - $RESERVED_MEGABYTES)
if [ 4096 -le $limit_in_megabytes ];
then
echo "容器内存大于等于4096M,采用G1回收器."
export JAVA_OPTS="${JAVA_OPTS} -server -Xmx${heap_size}M -Xms${heap_size}M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=256M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+ParallelRefProcEnabled"
elif [ 4096 -gt $limit_in_megabytes ];
then
echo "容器内存小于4096M,采用ParallelGC回收器."
if [ 2048 -gt $limit_in_megabytes ];
then
MaxMetaspaceSize=128
else
MaxMetaspaceSize=256
fi
export JAVA_OPTS="${JAVA_OPTS} -server -Xmx${heap_size}M -Xms${heap_size}M -XX:MaxMetaspaceSize=${MaxMetaspaceSize}M -XX:MetaspaceSize=128M -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSClassUnloadingEnabled -XX:+ParallelRefProcEnabled -XX:+CMSScavengeBeforeRemark"
fi
echo -e "JAVA_OPTS IS : ${JAVA_OPTS}"
fi
JAR_NAME=$(ls -t ${APP_PATH}/*.jar | head -1)
echo -e "JAR_NAME IS : $JAR_NAME"
if [[ "" != "${JAR_NAME}" ]];
then
java -jar ${JAVA_OPTS} ${JAR_NAME}
else
echo "找不到jar文件!退出执行" && exit 1
fi
本文系作者 @Mr.Lee 原创发布在 维简网。未经许可,禁止转载。