JDK11: JVM MaxRAM wrong value on Kubernetes

709 Views Asked by At

I'm facing a problem with JDK 11 with a container running Tomcat 9.0.68.

Short story: the pod get evicted beacuse it exceeds the maximum memory.

I have the following container set up on helm (I know that limits and requests should be the same, but I noticed this way the restart count is lower):

  containers:
    tomcat:
      resources:
        limits:
          cpu: 1000m
          memory: 2000Mi
        requests:
          cpu: 50m
          memory: 2000Mi

And I've enabled the following memory related JAVA_OPTS:

-XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport -XX:MaxRAMPercentage=50.0

The heap got sized correctly but I guess my problem is related to the non-heap part of the allocation. In fact if I run: java -XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport -XX:MaxRAMPercentage=50.0 -XX:+PrintFlagsFinal -version | grep -Ei 'Heap|RAM|version'

This is the result:

   bool AggressiveHeap                           = false                                     {product} {default}
    ccstr AllocateHeapAt                           =                                           {product} {default}
   size_t EpsilonMinHeapExpand                     = 134217728                            {experimental} {default}
   size_t EpsilonPrintHeapSteps                    = 20                                   {experimental} {default}
   size_t ErgoHeapSizeLimit                        = 0                                         {product} {default}
   size_t G1HeapRegionSize                         = 0                                         {product} {default}
    uintx G1HeapWastePercent                       = 5                                         {product} {default}
    uintx GCHeapFreeLimit                          = 2                                         {product} {default}
   size_t HeapBaseMinAddress                       = 2147483648                             {pd product} {default}
     bool HeapDumpAfterFullGC                      = false                                  {manageable} {default}
     bool HeapDumpBeforeFullGC                     = false                                  {manageable} {default}
     bool HeapDumpOnOutOfMemoryError               = false                                  {manageable} {default}
    ccstr HeapDumpPath                             =                                        {manageable} {default}
    uintx HeapFirstMaximumCompactionCount          = 3                                         {product} {default}
    uintx HeapMaximumCompactionInterval            = 20                                        {product} {default}
    uintx HeapSearchSteps                          = 3                                         {product} {default}
   size_t HeapSizePerGCThread                      = 43620760                                  {product} {default}
   size_t InitialHeapSize                          = 33554432                                  {product} {ergonomic}
    uintx InitialRAMFraction                       = 64                                        {product} {default}
   double InitialRAMPercentage                     = 1.562500                                  {product} {default}
    uintx InitiatingHeapOccupancyPercent           = 45                                        {product} {default}
   size_t LargePageHeapSizeThreshold               = 134217728                                 {product} {default}
    uintx MaxHeapFreeRatio                         = 70                                     {manageable} {default}
   size_t MaxHeapSize                              = 1048576000                                {product} {ergonomic}
 uint64_t MaxRAM                                   = 137438953472                           {pd product} {default}
    uintx MaxRAMFraction                           = 4                                         {product} {default}
   double MaxRAMPercentage                         = 50.000000                                 {product} {command line}
   size_t MinHeapDeltaBytes                        = 196608                                    {product} {ergonomic}
    uintx MinHeapFreeRatio                         = 40                                     {manageable} {default}
    uintx MinRAMFraction                           = 2                                         {product} {default}
   double MinRAMPercentage                         = 50.000000                                 {product} {default}
    uintx NonNMethodCodeHeapSize                   = 5825164                                {pd product} {ergonomic}
    uintx NonProfiledCodeHeapSize                  = 122916538                              {pd product} {ergonomic}
     bool PostLoopMultiversioning                  = false                             {C2 experimental} {default}
     bool PreserveFramePointer                     = false                                  {pd product} {default}
     bool PrintClassHistogram                      = false                                  {manageable} {default}
     bool PrintHeapAtSIGBREAK                      = true                                      {product} {default}
    uintx ProfiledCodeHeapSize                     = 122916538                              {pd product} {ergonomic}
   size_t ShenandoahSoftMaxHeapSize                = 0                                      {manageable} {default}
     bool ShrinkHeapInSteps                        = true                                      {product} {default}
openjdk version "11.0.16.1" 2022-08-12
OpenJDK Runtime Environment Temurin-11.0.16.1+1 (build 11.0.16.1+1)
OpenJDK 64-Bit Server VM Temurin-11.0.16.1+1 (build 11.0.16.1+1, mixed mode, sharing)

I think the problem is the JVM is not reading correctly the RAM assigned to the POD, correct me if I'm wrong.

I found that I can force the MaxRAM with the -XX:MaxRAM flag and I can also force the maximum metaspace size with the -XX:MaxMetaspaceSize parameters.

That said I guess that if set something like -XX:MaxRAM=2G and -XX:MaxMetaspaceSize=1G the problem should solve right? (couldn't try this yet)

Anyway this solution would require to set options based on the limits assigned and I didn't find any way to set the heap with percentage and still it would be not applicable as long as the JVM reads 137GB of RAM.

So I would like to know if anyone has faced the same problem and how to solve this without hardcoding the memory limits.

Note: I saw also this question: why is java showing MAXRAM to 128gb

But the only answer doesn't explain how to avoid this

0

There are 0 best solutions below