How to override cassandra image jvm.opts in runtime

1/29/2019

We are deploying Cassandra docker image 3.10 via k8s as StatefullSet.

I tried to set GC to G1GC adding -XX:+UseG1GC to JAVA_OPTS environment variable, but Cassandra is using the default CMS GC as set in the jvm.opts file.

from running ps aux in the pod I'm getting Cassandra configuration:

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
cassand+       1 28.0 10.1 72547644 6248956 ?    Ssl  Jan28 418:43 
java -Xloggc:/var/log/cassandra/gc.log -ea -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -XX:+HeapDumpOnOutOfMemoryError -Xss256k -XX:StringTableSize=1000003 -XX:+AlwaysPreTouch -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+UseNUMA -XX:+PerfDisableSharedMem -Djava.net.preferIPv4Stack=true -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSWaitDuration=10000 -XX:+CMSParallelInitialMarkEnabled -XX:+CMSEdenChunksRecordAlways -XX:+CMSClassUnloadingEnabled -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:+PrintPromotionFailure -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -Xms2G -Xmx2G -Xmn1G -XX:CompileCommandFile=/etc/cassandra/hotspot_compiler -javaagent:/usr/share/cassandra/lib/jamm-0.3.0.jar -Dcassandra.jmx.remote.port=7199 -Dcom.sun.management.jmxremote.rmi.port=7199 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password -Djava.library.path=/usr/share/cassandra/lib/sigar-bin -javaagent:/usr/share/cassandra/jmx_prometheus_javaagent-0.10.jar=7070:/etc/cassandra/jmx_prometheus_cassandra.yaml 

there is no -XX:+UseG1GC property.

Is there a way to override the jvm.opts at runtime, so I don't have to build the image for every small change? or I must add the costume jvm.opts file to the docker image I'm building?

-- guy dadon
cassandra
cassandra-3.0
docker
java
kubernetes

3 Answers

1/30/2019

I think the best solution would be to use a initContainer and a configMap.

InitContainers are executed to completion before the main containers starts. You can copy the values injected using the configMap over the values specified in your config files and perform a pod restart. This is also good because you can do a rolling restart across all your nodes.

In the initContainer you will inject the configMap and from there, when the initContainer is executed, you can do a sed to replace the actual values in C* config files.

You could use a busybox image for the initContainer that has the linux basic commands in it.

The steps would be as follow:

  • change parameters on the configMap (which is injected in the initContainer)
  • do a rolling restart.
-- Horia
Source: StackOverflow

1/29/2019

Use docker entrypoint to execute a init-script that should update the jvm opts from. Environment variable in cassandra-env. sh script. Then start cassandra database service

-- P Ekambaram
Source: StackOverflow

1/29/2019

Best and ideal option is ConfigMap. You can create ConfigMap for that file so that jvm.opts file can be accessed and changed from outside of pod. So without recreating new pod or even touching pod, you can change configuration as many times as you want.

For more details refer : https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-files

-- Rajesh Deshpande
Source: StackOverflow