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?
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:
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
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