search
LoginSignup
4
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Javaバージョン毎におけるkubernetes (GKE)上でのメモリ、CPU認識のデフォルト動作の違い

はじめに

Java 8においても、
Oracle Blogs 日本語のまとめ - [Java] Java SE support for Docker CPU and memory limits
の記事から、8u131以降はある程度 container.resource.limit.cpu、container.resource.limit.memoryを見て上手い事やってくれるのかな?
と思いきや、いまいちな挙動だったので、kubernetesで動かした際のjava8、java10、java11(ea)でのCPUの認識、及びメモリサイズの確保部分について調べてみました。

特に、GCの並列実行(スレッド数)や、各種並列スレッドのプール数等にも影響がある、 Runtime#availableProcessorsの動きがバージョンで変わるのか?という部分が
https://bugs.openjdk.java.net/browse/JDK-8140793
を見ても、2018/7/31時点でまだfixedVersionが出ていないのでどのバージョンでもまともに動かないのかどうかが気になった次第です。

結論

  • kubernetesでJavaアプリケーションを動作させる際、CPU、メモリを正しく認識させたいならjava10以降ならちゃんと認識してくれる。
  • java8でもメモリはXmx、Xmsなどで制御可能。
  • java8ではRuntime#availableProcessorsは正しく制限かける事はできないが、GCThread等は制御可能。

前提Javaアプリケーション

適当なSpring Boot アプリケーションを動かしてそのmetrics情報と、java -XX:+PrintGCDetails -XX:+PrintFlagsFinal -XX:+UnlockExperimentalVMOptions をcontainer上で動かした際の情報を確認します。

Spring Bootのアプリケーションは、
https://github.com/h-r-k-matsumoto/spring-boot-sample
をベースとして、それぞれ下記のように変更しています。また、cointainerに対するリソース割当は、下記のようになります。

020_deployments.yml
        resources:
          requests:
            cpu: 150m
            memory: 512Mi
          limits:
            cpu: 900m
            memory: 512Mi

deploymentsの全文は、
https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/master/kubernetes/020_deployments.yml
です。

java8 (no cgroup option)

pom.xmlのfrom imageを下記に変更します。特にJavaオプションでは何も制御しません。デフォルトのままです。

pom.xml
  <image>openjdk:8u171-jre-alpine</image>

java8

pom.xmlのfrom imageを下記に変更します。

pom.xml
  <image>openjdk:8u171-jre-alpine</image>

更に、下記jvmFlagオプションを追加します。ポイントは、 UseCGroupMemoryLimitForHeap です。
後は・・・私がいつもdocker 環境で動かす際につけているものです。

pom.xml
  <jvmFlag>-XX:+UnlockExperimentalVMOptions</jvmFlag>
  <jvmFlag>-XX:+UseCGroupMemoryLimitForHeap</jvmFlag>
  <jvmFlag>-XX:ParallelGCThreads=1</jvmFlag>
  <jvmFlag>-XX:CICompilerCount=2</jvmFlag>
  <jvmFlag>-Djava.util.concurrent.ForkJoinPool.common.parallelism=1</jvmFlag>

java10

pom.xmlのfrom imageを下記に変更します。オプションは指定無しです。

pom.xml
  <image>openjdk:10-jre-slim</image>

java11 (ea)

pom.xmlのfrom imageを下記に変更します。オプションは指定無しです。

pom.xml
  <image>openjdk:11-jre-slim</image>

計測内容

Spring Boot Actuatorのmetrics 機能と、

PrintFlagsFinal
 kubectl exec {pod-name} -- java -XX:+PrintGCDetails -XX:+PrintFlagsFinal -XX:+UnlockExperimentalVMOptions

を実行して取得した情報を利用します。

Spring Boot Actuator - metrics

system.cpu.count

http://pod-ip:port/actuator/metrics/system.cpu.count
で取得します。Runtime#availableProcessors の実行結果です。
ソースはmicrometer - ProcessorMetrics.java

jvm.memory.max (heap)

http://pod-ip-port/actuator/metrics/jvm.memory.max?tag=area:heap
で取得します。ヒープ領域の最大サイズです。
ソースは、micrometer - JvmMemoryMetrics.javaMemoryUsage#getMax の結果です。

PrintFlagsFinal結果

MaxHeapSize

最大ヒープ管理領域のサイズです。jvm.memory.maxと同じになる・・・はず。

UseParallelGC

GCを並列実行するかどうかです。
参考:https://docs.oracle.com/javase/jp/8/docs/technotes/guides/vm/gctuning/collectors.html

ParallelGCThreads

パラレルGCの際のスレッド数です。

計測結果

実行するノードのspecは、vCPUx2、メモリ7.5GBです。

java version system.cpu.count jvm.memory.max(heap):MiB MaxHeapSize:MiB UseParallelGC ParallelGCThreads
java 11(ea) 1 123.75 128.00 false 0
java 10 1 123.75 128.00 false 0
java 8 2 120.00 128.00 true 2
java 8 (no cgroup option) 2 1,857.00 1,870.00 true 2

※java 8でparallelになってしまっているのは、-XX:+UseSerialGC のオプションでserialに変更可能。というか -XX:ParallelGCThreads=1 が効いていない…。

java11、java10は、特にオプション指定をしなかった場合は、containersに割り当てられたメモリサイズの 512Mi から正しく計算され、MaxRAMFraction=4となるため、512/4 = 128 となっていました。
また、CPUに関しても、900mとしましたが、1コア分として判定されています。
java11、java10は、XmxやらXmsは指定せずとも、container上で正しく動きそうです。

java8の場合は、メモリに関しては制御可能です。ただし、CPU数に関しては上手い事手出しができないっぽいので…  Runtime#availableProcessors から計算していてリソース確保している部分は、都度システムプロパティ等で設定した方がよさそうです。

jvm.memory.max(heap)と、MaxHeapSizeで多少の誤差が出てるのは・・・気にしないです!
もし「このようなオプションを指定した方が良い」、「ここ、間違ってるよ」とかあればご指摘お願いします。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4
Help us understand the problem. What are the problem?