[DOCKER] Différences de comportement par défaut de la mémoire et de la reconnaissance du processeur sur kubernetes (GKE) pour chaque version de Java

introduction

Même en Java 8 [Oracle Blogs Japanese Summary- [Java] Java SE support for Docker CPU and memory limits](https://orablogs-jp.blogspot.com/2017/05/java-se-support-for-docker-cpu- et.html) Dans l'article, après 8u131, pouvez-vous voir container.resource.limit.cpu et container.resource.limit.memory dans une certaine mesure et bien faire? Je pensais que ce n'était pas un bon comportement, alors j'ai étudié la reconnaissance du processeur par java8, java10, java11 (ea) lors de l'exécution avec kubernetes, et la partie pour sécuriser la taille de la mémoire.

En particulier, le comportement de Runtime # availableProcessors, qui affecte l'exécution parallèle de GC (nombre de threads) et le nombre de pools de différents threads parallèles, change-t-il en fonction de la version? Est la partie https://bugs.openjdk.java.net/browse/JDK-8140793 Même si vous le regardez, au 31 juillet 2018, la version corrigée n'a pas encore été publiée, je me demandais donc si une version fonctionnerait correctement.

Conclusion

--Lors de l'exécution d'une application Java avec kubernetes, si vous souhaitez reconnaître correctement le processeur et la mémoire, java10 ou une version ultérieure la reconnaîtra correctement.

Application Java prérequise

Vérifiez les informations de métrique lorsque vous exécutez l'application Spring Boot appropriée et les informations lorsque vous exécutez java -XX: + PrintGCDetails -XX: + PrintFlagsFinal -XX: + UnlockExperimentalVMOptions sur le conteneur.

Application Spring Boot https://github.com/h-r-k-matsumoto/spring-boot-sample Basé sur, chacun a été modifié comme suit. De plus, l'allocation des ressources au cointainer est la suivante.

020_deployments.yml


        resources:
          requests:
            cpu: 150m
            memory: 512Mi
          limits:
            cpu: 900m
            memory: 512Mi

Le texte intégral des déploiements https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/master/kubernetes/020_deployments.yml est.

java8 (no cgroup option) Remplacez l'image de pom.xml par la suivante. En particulier, les options Java ne contrôlent rien. Laissez la valeur par défaut.

pom.xml


  <image>openjdk:8u171-jre-alpine</image>

java8 Remplacez l'image de pom.xml par la suivante.

pom.xml


  <image>openjdk:8u171-jre-alpine</image>

De plus, ajoutez l'option jvmFlag suivante. Le point est ʻUseCGroupMemoryLimitForHeap`. Le reste ... c'est ce que je porte toujours lorsque je cours dans un environnement 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 Remplacez l'image de pom.xml par la suivante. Aucune option n'est spécifiée.

pom.xml


  <image>openjdk:10-jre-slim</image>

java11 (ea) Remplacez l'image de pom.xml par la suivante. Aucune option n'est spécifiée.

pom.xml


  <image>openjdk:11-jre-slim</image>

Contenu de la mesure

Métriques Spring Boot Actuator

PrintFlagsFinal


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

Utilisez les informations obtenues en exécutant.

Spring Boot Actuator - metrics

system.cpu.count http://pod-ip:port/actuator/metrics/system.cpu.count Obtenez-le avec. C'est le résultat de l'exécution de Runtime # availableProcessors. La source est [micromètre --ProcessorMetrics.java](https://github.com/micrometer-metrics/micrometer/blob/35890bdc64614c24a8117099b0dcdaa003eab798/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/system/binder ProcessorMetrics.java # L83).

jvm.memory.max (heap) http://pod-ip-port/actuator/metrics/jvm.memory.max?tag=area:heap Obtenez-le avec. La taille maximale de la zone de tas. La source est [micromètre --JvmMemoryMetrics.java](https://github.com/micrometer-metrics/micrometer/blob/cff2e23445812852b5fa97b414958dbe595f0ae2/micrometer-core/src/main/java/io/micrometer/inder/jinder/instrument/ /JvmMemoryMetrics.java#L77-L96). C'est le résultat de MemoryUsage # getMax.

PrintFlagsRésultat final

MaxHeapSize La taille de la zone de gestion maximale du tas. Il doit être identique à [jvm.memory.max](# jvm.memory.max? Tag = area: heap).

UseParallelGC S'il faut exécuter GC en parallèle. Référence: https://docs.oracle.com/javase/jp/8/docs/technotes/guides/vm/gctuning/collectors.html

ParallelGCThreads Le nombre de threads pour GC parallèle.

Résultat de la mesure

La spécification du nœud à exécuter est vCPUx2 et mémoire 7,5 Go.

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

Sauf si une option est spécifiée, java11 et java10 sont calculés correctement à partir de la taille de mémoire 512Mi allouée aux conteneurs, et MaxRAMFraction = 4, donc 512/4 = 128. De plus, le processeur est réglé sur 900 m, mais il est considéré comme un cœur. java11 et java10 semblent fonctionner correctement sur le conteneur sans spécifier Xmx ou Xms.

Dans le cas de java8, vous pouvez contrôler la mémoire. Cependant, concernant le nombre de processeurs, il semble qu'il n'est pas possible de bien faire ... Il semble préférable de définir la partie qui est calculée à partir de Runtime # availableProcessors et sécurise à chaque fois les ressources dans les propriétés système etc.

Je m'en fiche s'il y a une légère différence entre jvm.memory.max (tas) et MaxHeapSize! Veuillez préciser si vous dites "Il vaut mieux spécifier une telle option" ou "C'est faux".

référence

--FookJoinPool et nombre de spécifications de pool: https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/ForkJoinPool.html#ForkJoinPool--

Recommended Posts

Différences de comportement par défaut de la mémoire et de la reconnaissance du processeur sur kubernetes (GKE) pour chaque version de Java
Liens pour chaque version (version japonaise) de l'API Java SE
[Pour les débutants] Explication des classes, des instances et des statiques en Java
[Java] Rendre les variables de l'instruction for étendue et de chaque instruction immuables
Définir des méthodes abstraites dans l'énumération Java et écrire leur comportement
Une note sur les différences entre les interfaces et les classes abstraites en Java
Mesure de la mémoire des applications Java sous Windows
Comportement inattendu du message par défaut dans org.springframework.context.MessageSource.getMessage ()
Discrimination d'énum dans Java 7 et supérieur