Kubernetes, aplicación sencilla SpringBoot OOMKilled

William Añez :

Estoy trabajando con OpenJDK 11 y una aplicación SpringBoot muy simple que casi lo único que tiene es el actuador SpringBoot habilitado para que pueda llamar / actuador / de la salud , etc.

También tengo un clúster kubernetes en GCE muy simple con sólo una vaina con un recipiente (que contiene esta aplicación por supuesto)

Mi configuración tiene algunos puntos clave que quiero destacar, que tiene algunos requisitos y límites

resources:
  limits:
    memory: 600Mi
  requests:
    memory: 128Mi

Y tiene una sonda disposición

readinessProbe:
  initialDelaySeconds: 30
  periodSeconds: 30
  httpGet:
    path: /actuator/health
    port: 8080

También estoy estableciendo un JVM_OPTS como (que mi programa está utilizando obviamente)

env:
- name: JVM_OPTS
  value: "-XX:MaxRAM=512m"

El problema

Lanzo esto y se pone OOMKilled en aproximadamente 3 horas cada vez!

Nunca estoy llamando nada a mí mismo la única llamada es sondear la disposición cada 30 segundos que kubernetes hace, y eso es suficiente para agotar la memoria? Tampoco he implementado nada fuera de lo, sólo un método Get ordinaria que dice hola mundo a lo largo de todas las importaciones SpringBoot a tener los actuadores

Si me quedo vaina superior kubectl XXXXXX En realidad veo cómo llegar gradualmente más y más grande

He probado un montón de diferentes configuraciones, consejos, etc, pero nada parece funcionar con una aplicación básica SpringBoot

¿Hay una manera de limitar realmente difícil la memoria de una manera que Java puede plantear una excepción OutOfMemory? o para evitar que esto suceda?

Gracias por adelantado


EDIT: Después de 15 horas de funcionamiento

NAME                        READY   STATUS    RESTARTS   AGE
pod/test-79fd5c5b59-56654   1/1     Running   4          15h

describir la vaina dice ...

State:          Running
  Started:      Wed, 27 Feb 2019 10:29:09 +0000
Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137
  Started:      Wed, 27 Feb 2019 06:27:39 +0000
  Finished:     Wed, 27 Feb 2019 10:29:08 +0000

Ese último lapso de tiempo es de aproximadamente 4 horas y sólo tienen 483 llamadas a / actuador / de la salud, al parecer eso fue suficiente para hacer java superar la indirecta MaxRAM?


EDIT: Casi 17h

su punto de morir de nuevo

$ kubectl top pod test-79fd5c5b59-56654

NAME                    CPU(cores)   MEMORY(bytes)   
test-79fd5c5b59-56654   43m          575Mi      

EDIT: perder ninguna esperanza a las 23h

NAME                        READY   STATUS    RESTARTS   AGE
pod/test-79fd5c5b59-56654   1/1     Running   6          23h

describir las vainas;

State:          Running
      Started:      Wed, 27 Feb 2019 18:01:45 +0000
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Wed, 27 Feb 2019 14:12:09 +0000
      Finished:     Wed, 27 Feb 2019 18:01:44 +0000

EDIT: Un nuevo hallazgo

Ayer por la noche que estaba haciendo una lectura interesante:

https://developers.redhat.com/blog/2017/03/14/java-inside-docker/ https://banzaicloud.com/blog/java10-container-sizing/ https://medium.com/adorsys/ -memoria-Valores de JVM-in-a-envase-entorno-64b0840e1d9e

TL; DR decidí quitar el límite de memoria e iniciar el proceso de nuevo, el resultado fue bastante interesante (después de 11 horas como en ejecución)

NAME                    CPU(cores)   MEMORY(bytes)   
test-84ff9d9bd9-77xmh   218m         1122Mi  

Así que ... WTH con la CPU? Yo como esperando un número grande en el uso de memoria, pero lo que sucede con la CPU?

Lo único que se me ocurre es que la GC se ejecuta como una locura pensar que el MaxRAM es 512m y él está utilizando más de 1G. Me pregunto, se detecta la ergonomía de Java correctamente? (Estoy empezando a dudar de ella)

Para probar mi teoría se establece un límite de 512m y desplegar la aplicación de esta manera y me encontré con que desde el principio hay una carga de la CPU inusual que tiene que ser la GC funcionando con mucha frecuencia

kubectl create ...

limitrange/mem-limit-range created 
pod/test created

kubectl exec -it test-64ccb87fd7-5ltb6 /usr/bin/free
              total        used        free      shared  buff/cache   available
Mem:        7658200     1141412     4132708       19948     2384080     6202496
Swap:             0           0           0

kubectl top pod ..
NAME                    CPU(cores)   MEMORY(bytes)   
test-64ccb87fd7-5ltb6   522m         283Mi    

522m es demasiada CPU virtual, por lo que mi siguiente paso lógico era asegurarse de que estoy usando el GC más apropiado para este caso, he cambiado los JVM_OPTS de esta manera:

  env:
  - name: JVM_OPTS
    value: "-XX:MaxRAM=512m -Xmx128m -XX:+UseSerialGC"
  ...
    resources:
      requests:
        memory: 256Mi
        cpu: 0.15
      limits:
        memory: 700Mi

Y eso es llevar el uso de CPU virtual a un estado razonable de nuevo, después de kubectl top pod

NAME                    CPU(cores)   MEMORY(bytes)   
test-84f4c7445f-kzvd5   13m          305Mi 

Messing con -Xmx tener MaxRAM es, obviamente, afectando la JVM pero ¿no es posible controlar la cantidad de memoria que tenemos en contenedores virtualizados? Sé que freecomando reportará el anfitrión RAM disponible, pero debe ser OpenJDK usando cgroups rihgt ?.

Todavía estoy supervisión de la memoria ...


EDIT: Una nueva esperanza

Hice dos cosas, la primera fue de nuevo para eliminar el límite de mi contenedor, quiero analizar cuánto va a crecer, también he añadido una nueva bandera para ver cómo el proceso está utilizando la memoria nativa -XX:NativeMemoryTracking=summary

Al principio todo era normal, el proceso comenzó a consumir como 300 MB a través kubectl top pod, así que dejamos correr alrededor de 4 horas y luego ...

kubectl top pod

NAME                    CPU(cores)   MEMORY(bytes)
test-646864bc48-69wm2   54m          645Mi

tipo de espera, ¿verdad? pero luego he comprobado el uso de memoria nativa

jcmd <PID> VM.native_memory summary

Native Memory Tracking:

Total: reserved=2780631KB, committed=536883KB
-                 Java Heap (reserved=131072KB, committed=120896KB)
                            (mmap: reserved=131072KB, committed=120896KB)

-                     Class (reserved=203583KB, committed=92263KB)
                            (classes #17086)
                            (  instance classes #15957, array classes #1129)
                            (malloc=2879KB #44797)
                            (mmap: reserved=200704KB, committed=89384KB)
                            (  Metadata:   )
                            (    reserved=77824KB, committed=77480KB)
                            (    used=76069KB)
                            (    free=1411KB)
                            (    waste=0KB =0.00%)
                            (  Class space:)
                            (    reserved=122880KB, committed=11904KB)
                            (    used=10967KB)
                            (    free=937KB)
                            (    waste=0KB =0.00%)

-                    Thread (reserved=2126472KB, committed=222584KB)
                            (thread #2059)
                            (stack: reserved=2116644KB, committed=212756KB)
                            (malloc=7415KB #10299)
                            (arena=2413KB #4116)

-                      Code (reserved=249957KB, committed=31621KB)
                            (malloc=2269KB #9949)
                            (mmap: reserved=247688KB, committed=29352KB)

-                        GC (reserved=951KB, committed=923KB)
                            (malloc=519KB #1742)
                            (mmap: reserved=432KB, committed=404KB)

-                  Compiler (reserved=1913KB, committed=1913KB)
                            (malloc=1783KB #1343)
                            (arena=131KB #5)

-                  Internal (reserved=7798KB, committed=7798KB)
                            (malloc=7758KB #28415)
                            (mmap: reserved=40KB, committed=40KB)

-                     Other (reserved=32304KB, committed=32304KB)
                            (malloc=32304KB #3030)

-                    Symbol (reserved=20616KB, committed=20616KB)
                            (malloc=17475KB #212850)
                            (arena=3141KB #1)

-    Native Memory Tracking (reserved=5417KB, committed=5417KB)
                            (malloc=347KB #4494)
                            (tracking overhead=5070KB)

-               Arena Chunk (reserved=241KB, committed=241KB)
                            (malloc=241KB)

-                   Logging (reserved=4KB, committed=4KB)
                            (malloc=4KB #184)

-                 Arguments (reserved=17KB, committed=17KB)
                            (malloc=17KB #469)

-                    Module (reserved=286KB, committed=286KB)
                            (malloc=286KB #2704)

Esperar lo ? 2,1 GB reservado para hilos? y 222 MB están utilizando, ¿qué es esto? Yo actualmente no sé, acabo de ver que ...

Necesito tiempo tratando de entender por qué ocurre esto

William Añez :

Finalmente encontré mi problema y quiero compartirlo para que otros puedan beneficiarse de alguna manera de esto.

Como ya he encontrado en mi última edición que tenía un problema hilo que estaba causando todo el consumo de memoria en el tiempo, en concreto que estaba usando un método asíncrono de una biblioteca de terceros sin cuidar adecuadamente esos recursos (asegurar esas llamadas se terminan correctamente en este caso ).

Yo era capaz de detectar el problema porque he usado un límite de memoria en mi despliegue kubernete desde el principio (que es una buena práctica en entornos de producción) y luego objeto de riguroso control de mi consumo de memoria de aplicaciones utilizando herramientas como jstat, jcmd, visualvm, kill -3y lo más importante la -XX:NativeMemoryTracking=summarybandera que dio me tanto detalle en este sentido.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=175431&siteId=1
Recomendado
Clasificación