Environment variables not being resolved in Kubernetes Java deployment

10/3/2018

After learning about arguments that can be passed to a Java 8 Virtual Machine to make it container-aware (i.e. -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap), I am trying to add these arguments to my Kubernetes deployment for a Spring Boot service.

In containers section of my deployment YAML file, I have the following:

resources:
    requests:
        memory: "256Mi"
        cpu: "50m"
    limits:  
        memory: "512Mi"
        cpu: "200m"
env:
- name: JVM\_OPTS
  value: "-Xms256M -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1"

In my Dockerfile, I have:

ENV JVM\_OPTS="-Xmx256M"
ENV JVM\_ARGS="-Dspring.profiles.active=kubernetes"
EXPOSE 8080
ENTRYPOINT \[ "sh", "-c", "java $JVM\_ARGS $JVM\_OPTS -jar testservice.jar" \]

I can't seem to figure out why the max heap sized does not get sized properly:

$ kubectl exec test-service-deployment-79c9d4bd54-trxgj -c test-service -- java -XshowSettings:vm -version' VM settings: Max. Heap Size (Estimated): 875.00M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_171" OpenJDK Runtime Environment (IcedTea 3.8.0) (Alpine 8.171.11-r0) OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)

What am I doing wrong here?

On a local Docker install, I can see the JVM max heap set correctly:

$ docker run openjdk:8-jre-alpine java -Xms256M -Xmx512M -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm -version VM settings: Min. Heap Size: 256.00M Max. Heap Size: 512.00M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_171" OpenJDK Runtime Environment (IcedTea 3.8.0) (Alpine 8.171.11-r0) OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)

-- JJ_Mind
java
kubernetes

3 Answers

10/3/2018

The only I see is that you are missing is the actual max on your command line arguments on your Kubernetes pod definition. You are passing it to your docker run ... command line:

env:
- name: JVM_OPTS
  value: "-Xms256M -Xmx512M -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1"

instead of:

env:
- name: JVM_OPTS
  value: "-Xms256M -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1"
-- Rico
Source: StackOverflow

10/3/2018

While building your docker image from docker file your java env variables are resolved and passed to enterypoint and then the image is built with the resolved values. Which in your dockerfile are:

JVM_OPTS="-Xmx256M"

JVM_ARGS="-Dspring.profiles.active=kubernetes"

If you want to use kubernetes env variable for java arguments, then give entrypoint as some script.sh, and in script.sh you use env variables which will be resolved while running the image in kubernetes, instead of at build time.

-- Sumit
Source: StackOverflow

10/3/2018

When running java -XshowSettings:vm -version in container, JVM_OPTS is not include in your command.

Try with this one

kubectl exec test-service-deployment-79c9d4bd54-trxgj -c test-service \
          -- sh -c 'java $JVM_OPTS -XshowSettings:vm -version'
-- silverfox
Source: StackOverflow