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)
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"
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.
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'