Personne* ne met Java dans un containeur

Personne* ne met Java dans un containeur

Cette discussion porte sur les problèmes de mettre Java dans un conteneur et comment, dans sa dernière version 9, le JDK est maintenant plus conscient du conteneur dans lequel il s’exécute. La présentation est dirigée par Joerg Schad, ingénieur logiciels distribués de Mesosphere, à l’OpenSource Summit 2017 de Prague.

Quels sont les problèmes de mettre Java dans un conteneur?
Comment la JVM interagit-elle avec l’isolation fournie par le conteneur?

Conteneurs

Un conteneur est un moyen pratique de déployer des applications facilement. En s’appuyant directement sur le noyau, l’isolation fournie par un conteneur est plus faible qu’une machine virtuelle en échange de performances supérieures.

Un conteneur est donc très rapide au lancement et lors de son exécution et utilise moins de ressources (mémoire, cpu, réseau) qu’une VM.

Deux technologies complémentaires permettent d’isoler un conteneur dans le système: les CGroups et les espace de nom appelés Namespaces. Combinés, ils offrent une solution légère et puissante pour isoler les processus du reste du système.

Namespaces

Un Namespace fournit à un processus sa propre vue du système. Par exemple, un processus ne connaît que ses propres PID, points de montage et systèmes de fichiers.

CGroups

Alors que les Namespaces contrôlent la vue du système pour un processus, les CGroups limite les ressources utilisées par un processus (ou un groupe de processus). De tels exemples incluent:

  • Utilisation du processeur
  • Limites de mémoire
  • Réseau et disque IO
  • Hardware

Java

Les problèmes actuels concernent la façon dont la JVM interagit avec les CGroups pour rassembler les ressources système.

Mémoire

Un programme Java n’utilise pas seulement la mémoire pour la taille du tas, mais aussi pour les threads Garbage Collector, le *compilateur just in time* (JIT), …

Avant Java 8u131, pour obtenir la quantité de mémoire disponible sur l’hôte, la JVM déterminait la taille de la stack en regardant dans /proc. Cependant, dans un environnement conteneur, cette valeur reflète la mémoire du système et non la mémoire disponible pour le conteneur, en contradiction avec la valeur allouée au conteneur par sa définition CGroups.

La conséquence d’un tel comportement est simple mais problématique. La taille maximale de la stack est par défaut de 1/4 de la mémoire physique . Comme cette mémoire est basée sur la mémoire physique de l’hôte, un processus Java s’exécutant à l’intérieur du conteneur pourrait bien allouer plus que la mémoire disponible à l’intérieur du conteneur. Ainsi, il recevra un signal d’arrêt à la suite du dépassement des limites imposées par le CGroup.

Deux solutions existent:

  • utilisez les options JAVA -Xmx<Value>  pour définir manuellement la taille maximale du tas, ce qui réduit la portabilité offerte par les conteneurs
  • utilisez JDK8u131 ou JDK9 et -XX:+UseCGroupMemoryLimitForHeap -XX:+UnlockExperimentalVMOptions  afin de rendre la taille de la JVM consciente du CGroup

CPU

Le problème est très similaire pour l’utilisation du processeur. Il existe deux façons de limiter l’utilisation du processeur d’un processus à l’aide des CGroups:

  • Unités de CPU: attribuez un nombre de CPU à un processus
  • Partages CPU: attribuez un poids qui agit pour limiter en pourcentage l’utilisation de la CPU.

La JVM ne sait pas qu’elle s’exécute dans un conteneur et basera ses paramètres par défaut sur le nombre de CPU disponibles sur l’hôte au lieu de ceux appliqués par le CGroup. Sur la base de cette valeur, la machine virtuelle Java démarrera trop de threads GC et JIT, ce qui entraînera des problèmes de performances.

Ce problème est également résolu dans le JDK le plus récent. Puisque la JVM est maintenant consciente du nombre de processeurs disponibles via CGroups. Il n’est donc pas recommandé d’utiliser des partages de CPU.

Conclusion

Contrairement à la technologie VM, les conteneurs ne cachent pas le matériel sous-jacent du processus. Le problème avec les conteneurs et CGroups est principalement résolu depuis la JDK8u131.

Les références

By | 2017-11-22T17:41:04+00:00 November 21st, 2017|Open Source Summit Europe 2017|0 Comments

About the Author:

Leave A Comment

Time limit is exhausted. Please reload the CAPTCHA.