GCP вызывает OOMKiller для приложения java, однако оно не использует максимально допустимую память - PullRequest
2 голосов
/ 10 января 2020

Ввод: GCP, Kubernetes, java 11 приложение с загрузочной пружиной 2

Контейнер запущен с ограничением памяти 1,6 ГБ. Java приложение также ограничивает память -XX: MaxRAMPercentage = 80.0. Под «большой» (не очень) нагрузкой - около 1 HTTP-запроса за 100 мс в течение около 4 часов приложение убивает OOMKiller Внутренняя диагностика c инструментов показывает, что объем памяти далек от предела:

enter image description here

Однако инструменты GCP показывают следующее:

enter image description here

Есть подозрение, что GCP измеряет что-то еще? POD содержит только приложение java (+ агент Jaeger). Странно, что после перезапуска GCP показывает почти максимальное использование памяти вместо того, чтобы медленно расти, если это была утечка памяти.

РЕДАКТИРОВАТЬ:

Docker файл:

FROM adoptopenjdk/openjdk11:x86_64-ubuntu-jdk-11.0.3_7-slim
VOLUME /tmp
VOLUME /javamelody
RUN apt-get update && apt-get install procps wget -y
RUN mkdir /opt/cdbg && wget -qO- https://storage.googleapis.com/cloud-debugger/compute-java/debian-wheezy/cdbg_java_agent_gce.tar.gz | tar xvz -C /opt/cdbg
RUN apt-get install fontconfig ttf-dejavu -y
ARG JAR_FILE
ARG VERSION
ARG MODULENAME
ENV TAG=$VERSION
ENV MODULE=$MODULENAME
COPY target/${JAR_FILE} app.jar
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD java -agentpath:/opt/cdbg/cdbg_java_agent.so \
            -Dcom.google.cdbg.module=${MODULE} \
            -Dcom.google.cdbg.version=${TAG} \
            -Djava.security.egd=file:/dev/./urandom \
            -XX:MaxRAMPercentage=80.0 \
            -XX:+CrashOnOutOfMemoryError \
            -XX:ErrorFile=tmp/hs_err_pid%p.log \
            -XX:NativeMemoryTracking=detail \
            -XX:+UnlockDiagnosticVMOptions \
            -XX:+PrintNMTStatistics \
            -XX:+HeapDumpOnOutOfMemoryError \
            -XX:HeapDumpPath=tmp/ \
            -jar /app.jar

и запустить его с Kubernetes (дополнительные сведения опущены):

apiVersion: apps/v1
spec:
  replicas: {{ .Values.replicas }}
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 50%
      maxUnavailable: 0
  template:
    spec:
      initContainers:
        bla-bla
      containers:
        lifecycle:
          preStop:
            exec:
              command: [
                # Gracefully shutdown java
                "pkill", "java"
              ]
        resources:
          limits:
            cpu: 1600
            memory: 1300
          requests:
            cpu: 1600
            memory: 1300

UPDATE в соответствии с верхним пределом памяти для команд также далек от предела, однако загрузка ЦП стала более 100% до того, как контейнер OOMKilled. Возможно ли, что Kubernetes убивает контейнер, который пытается получить больше ЦП, чем разрешено?

Tasks:   5 total,   1 running,   4 sleeping,   0 stopped,   0 zombie
%Cpu(s): 34.1 us,  2.0 sy,  0.0 ni, 63.4 id,  0.0 wa,  0.0 hi,  0.5 si,  0.0 st
KiB Mem :  7656868 total,  1038708 free,  2837764 used,  3780396 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  4599760 avail Mem
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      6 root      20   0 5172744 761664  30928 S 115.3  9.9  21:11.24 java
      1 root      20   0    4632    820    748 S   0.0  0.0   0:00.02 sh
    103 root      20   0    4632    796    720 S   0.0  0.0   0:00.00 sh
    108 root      20   0   38276   3660   3164 R   0.0  0.0   0:00.95 top
    112 root      20   0    4632    788    716 S   0.0  0.0   0:00.00 sh
command terminated with exit code 137

UPDATE2

# pmap -x 7
7:   java -agentpath:/opt/cdbg/cdbg_java_agent.so -Dcom.google.cdbg.module=engine-app -Dcom.google.cdbg.version= -Djava.security.egd=file:/dev/./urandom -XX:MaxRAMPercentage=80.0 -XX:+CrashOnOutOfMemoryError -XX:ErrorFile=tmp/hs_err_pid%p.log -XX:NativeMemoryTracking=detail -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=tmp/ -jar /app.jar
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000       4       4       0 r-x-- java
0000000000400000       0       0       0 r-x-- java
0000000000600000       4       4       4 r---- java
0000000000600000       0       0       0 r---- java
0000000000601000       4       4       4 rw--- java
0000000000601000       0       0       0 rw--- java
00000000006d5000    4900    4708    4708 rw---   [ anon ]
00000000006d5000       0       0       0 rw---   [ anon ]
00000000b0000000   86144   83136   83136 rw---   [ anon ]
00000000b0000000       0       0       0 rw---   [ anon ]
00000000b5420000  350720       0       0 -----   [ anon ]
00000000b5420000       0       0       0 -----   [ anon ]
00000000caaa0000  171944  148928  148928 rw---   [ anon ]
00000000caaa0000       0       0       0 rw---   [ anon ]
00000000d528a000  701912       0       0 -----   [ anon ]
00000000d528a000       0       0       0 -----   [ anon ]
0000000100000000   23552   23356   23356 rw---   [ anon ]
0000000100000000       0       0       0 rw---   [ anon ]
0000000101700000 1025024       0       0 -----   [ anon ]
0000000101700000       0       0       0 -----   [ anon ]
00007f447c000000   39076   10660   10660 rw---   [ anon ]
00007f447c000000       0       0       0 rw---   [ anon ]
00007f447e629000   26460       0       0 -----   [ anon ]
00007f447e629000       0       0       0 -----   [ anon ]
00007f4481c8f000    1280    1164    1164 rw---   [ anon ]
00007f4481c8f000       0       0       0 rw---   [ anon ]
00007f4481dcf000     784       0       0 -----   [ anon ]
00007f4481dcf000       0       0       0 -----   [ anon ]
00007f4481e93000    1012      12      12 rw---   [ anon ]
00007f4481e93000       0       0       0 rw---   [ anon ]
00007f4481f90000      16       0       0 -----   [ anon ]
...
00007ffcfcd48000       8       4       0 r-x--   [ anon ]
00007ffcfcd48000       0       0       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
ffffffffff600000       0       0       0 r-x--   [ anon ]
---------------- ------- ------- -------
total kB         5220936  772448  739852

этот pmap был вызван незадолго до OOMKilled , 5Гб? Почему топ не показывает это? Также не уверен, как интерпретировать результат команды pmap

Ответы [ 3 ]

3 голосов
/ 10 января 2020

Для каждого файла журнала существует более 10 000 запущенных потоков. Это много , даже если мы не смотрим на то, что 2 ЦП / ядра зарезервированы для контейнера (limit.cpu = request.cpu = 1600 милликоров).

Каждый поток, и его стек, выделяется в памяти отдельно от кучи. Вполне возможно, что большое количество запущенных потоков является причиной проблемы OOM.

JVM запускается с опциями, относящимися к Native Memory Tracking (-XX:NativeMemoryTracking=detail, -XX:+UnlockDiagnosticVMOptions, -XX:+PrintNMTStatistics), которые могут помочь увидеть использование памяти, включая что потребляется этими потоками. Это сделать c может быть отправной точкой для Java 11.

В любом случае, настоятельно рекомендуется не запустили столько потоков. Например, используйте пул, запускайте и останавливайте их, когда они больше не нужны ...

1 голос
/ 12 марта 2020

В моем случае проблема была с компонентом отладчика, который находится в строке CMD файла Docker

-agentpath:/opt/cdbg/cdbg_java_agent.so \
            -Dcom.google.cdbg.module=${MODULE} \
            -Dcom.google.cdbg.version=${TAG} \
            -Djava.security.egd=file:/dev/./urandom \

После удаления приложение перестало течь. Но исчезла только утечка родной памяти. Как выяснилось позже, была также утечка памяти в куче, вызванная компонентом jaegger tracer (к счастью, у нас гораздо больше инструментов). После его удаления приложение стало стабильным. Я не знаю, были ли эти компоненты протекающими сами по себе или в сочетании с другими компонентами, но факт в том, что теперь они стабильны.

1 голос
/ 13 января 2020

Существует две причины, по которым контейнер уничтожен OOM: квота контейнера и системная квота.

OOM Killer * только 1003 * вызывает проблемы с памятью.

Если ваша система в вашем контейнере, возможно, нет предела памяти. Для вашего процесса в модуле ограничение ресурса модуля похоже на то, что вся система является OOM.

  • Проверьте манифест модуля, возможно, в модулях достигнут предел, достигаемый в модулях.

Также стоит проверить запросы ресурсов, потому что по умолчанию они не установлены. Запросы должны быть меньше или равны ограничениям контейнера. Это означает, что контейнеры могут быть перенесены на узлы и уничтожены OOMK, если несколько контейнеров используют больше памяти, чем их соответствующие запросы одновременно.

  • Проверьте объем памяти, назначаемый каждому стручок и сколько памяти фактически использует процесс в течение какого времени. Может быть, он резервирует намного больше памяти, чем ему действительно нужно, и это заставляет ваше использование памяти начинать с более высоких уровней.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...