美文网首页
限制容器中的JVM资源

限制容器中的JVM资源

作者: pilisiyang | 来源:发表于2019-11-18 14:31 被阅读0次

    java与容器

    之前用rancher部署就遇到过没限制容器内存大小导致K8S集群挂掉的问题,但是仅仅限制容器资源是不够的,jdk1.8中java程序是不能自动识别docker设置的内存,cpu限制的,这就会导致当java程序运行时占的内存过大时,容器会杀掉JVM进程,而健康检查又会拉起一个新的pod,进而导致服务一天重启很多次。

    jdk11默认支持了容器,由参数 UseContainerSupport = true 来设置,在之前的jdk中,Java 8u131 以上版本支持 Docker 的 cpu 和memory 限制,使用参数 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

    在容器中对JVM调优

    默认情况下,JVM的Max Heap Size是系统内存的1/4,实际中,这点heap是不够的,会导致受限制的容器启动失败,只有加大容器的资源才能正常启动,除此之外还有一种方法,就要对容器里面的 jvm 调优。

    但是这里遇到了一个问题,dockerfile 配置

    FROM openjdk:8-jdk-alpine
    ...
    ENTRYPOINT java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /$name
    

    这样启动后 JVM 的 pid 为1,使用 jmap,jinfo,jstack等命令时会报出错误:

    Unable to get pid of LinuxThreads manager thread

    openjdk issues

    docker容器默认会把容器内部第一个进程,也就是pid=1的程序作为docker容器是否正在运行的依据,所以这里可以用一个容器 init 解决:

    https://github.com/krallin/tini#tini---a-tiny-but-valid-init-for-containers

    修改 dockerfile 配置,使用 tini 来启动 jvm

    ...
    RUN apk add --no-cache tini
    ENTRYPOINT ["/sbin/tini", "--"]
    CMD java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker -jar /$name
    ...
    

    rancher 控制台中限制容器内存


    image.png

    进入容器查看jvm,可以看到pid=1的程序已经是tini了,接下来就可以使用jvm 命令查看各个参数,可以看到 MaxHeapSize=411041792 ,差不多392mb,正好是内存限制1568mb的1/4


    查看jvm详细信息



    Full GC 以后 Old Generation 大概占了254mb

    相关文章

      网友评论

          本文标题:限制容器中的JVM资源

          本文链接:https://www.haomeiwen.com/subject/gexbictx.html