Наш текущий кластер Kubernetes, работающий в Google Container Engine (GKE), состоит из n1-standard-1
типы машин (1 виртуальный процессор и 3,75 ГБ памяти) под управлением Debian GNU / Linux 7.9 (wheezy), поддерживаемого Google. Из-за увеличения нагрузки и использования памяти нашими службами нам необходимо обновить наши узлы до более крупного типа. Пробуя это в нашем тестовом кластере, мы испытали кое-что, что (нам) кажется довольно странным.
Объем памяти, потребляемой приложением JVM при развертывании на узле Google, кажется, пропорционален количеству ядер, доступных на узле. Даже если мы установим максимальную память JVM (Xmx) на 128 МБ, она потребляет около 250 МБ на одноядерной машине (это понятно, поскольку JVM потребляет больше памяти, чем максимальный предел из-за GC, самой JVM и т. Д.), Но она потребляет около 700Мб на 2-х ядерной машине (n1-standard-2
) и около 1,4 ГБ на 4-ядерной машине (n1-standard-4
). Единственное, что отличается - это тип машины, используется тот же образ и конфигурации Docker.
Например, если я подключусь к машине по SSH, используя n1-standard-4
тип машины и запуск sudo docker stats <container_name>
Я получаю это:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
k8s.name 3.84% 1.11 GB / 1.611 GB 68.91% 0 B / 0 B
Когда я запускаю тем же Образ Docker с точным тем же (приложение) конфигурация локально (mac osx и докер-машина) я вижу:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
name 1.49% 236.6 MB / 1.044 GB 22.66% 25.86 kB / 14.84 kB 0 B / 0 B
Что гораздо больше соответствует тому, что я ожидал из-за Xmx
Установка (для записи у меня 8 ядер и 16Гб памяти). То же самое подтверждается, когда я бегу top -p <pid>
на экземпляре GKE, который дает мне выделение памяти RES / RSS от 1,1 до 1,4 ГБ.
Образ Docker определяется так:
FROM java:8u91-jre
EXPOSE 8080
EXPOSE 8081
ENV JAVA_TOOL_OPTIONS -Dfile.encoding=UTF-8
# Add jar
ADD uberjar.jar /data/uberjar.jar
CMD java -jar /data/uberjar.jar -Xmx128m -server
Я также пробовал добавить:
ENV MALLOC_ARENA_MAX 4
который я видел рекомендованным в нескольких потоках, таких как этот но похоже, что это не имеет никакого значения. Я также пытался перейти на другой базовый образ Java, а также использовать alpine linux, но это, похоже, тоже ничего не меняет.
Моя локальная версия Docker - 1.11.1, а версия Docker в Kubernetes / GKE - 1.9.1. Версия Kubernetes (если это важно) - v1.2.4.
Также интересно то, что если мы развернем несколько экземпляров модуля / контейнера на одном компьютере / узле, некоторые экземпляры будут выделять гораздо меньше памяти. Например, первые три могут выделять 1,1–1,4 ГБ памяти, но затем 10 последующих контейнеров выделяют только около 250 МБ каждый, что примерно соответствует тому, что я ожидал. каждый экземпляр выделить. Проблема в том, что если мы достигаем ограничения памяти машины, первые три экземпляра (те, которые выделяют 1,1 ГБ памяти), похоже, никогда не освобождают свою выделенную память. Если бы они освободили память, когда машина находится под повышенным давлением, я бы не стал беспокоиться об этом, но поскольку они сохраняют выделение памяти даже при загрузке машины, это становится проблемой (поскольку это запрещает планирование других контейнеров на этой машине и таким образом ресурсы тратятся зря).
Вопросы:
Когда вы указываете
CMD java -jar /data/uberjar.jar -Xmx128m -server
затем значения, которые вы хотите использовать в качестве аргументов JVM (-Xmx128m -server
) передаются как аргументы командной строки классу Main в файле .jar. Они доступны в виде аргументов в вашем public static void main(String... args)
метод.
Обратите внимание, что это также верно, если вы запускаете основной класс по имени, а не указываете исполняемый файл jar
файл.
Чтобы передать их в качестве аргументов JVM, а не аргументов в вашу программу, вам необходимо указать их перед -jar
арг.
Проблема заключалась в настройках JVM, указанных в Dockerfile
. Мы запустили нашу JVM так:
CMD java -jar /data/uberjar.jar -Xmx128m -server
но когда мы перешли на:
CMD java -Xmx128m -server -jar /data/uberjar.jar
настройки учтены. Я до сих пор не понимаю, почему я не видел это локально, но я просто рад, что нам удалось это решить.