dockerkubernetesenvironment-variableskubernetes-helmjvm-arguments

How to access environment variables defined in dockerfile in helm chart value file


I have defined CATALINA_OPTS with default values in the Dockerfile and built a Docker image. While deploying to a Kubernetes cluster using a Helm chart, it seems that additional options cannot be appended to CATALINA_OPTS. The only option is to override CATALINA_OPTS entirely in the Helm chart values file.

Docker file :

ENV CATALINA_OPTS="$CATALINA_OPTS -XshowSettings:vm \
    --add-opens=java.base/java.io=ALL-UNNAMED \
    --add-opens=java.base/java.lang.invoke=ALL-UNNAMED \
    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED"

helm value file :

envVars:
  - name: CATALINA_OPTS
    value: "$CATALINA_OPTS -XX:+UseG1GC \
           -XX:+UnlockExperimentalVMOptions \
           -XX:InitialRAMPercentage=60.0 \
          -XX:MinRAMPercentage=60.0 \
          -XX:MaxRAMPercentage=60.0"

Error :

  Error: Could not find or load main class ${CATALINA_OPTS} Caused by: java.lang.ClassNotFoundException: ${CATALINA_OPTS} Could not load Logmanager "org.apache.juli.ClassLoaderLogManager" java.lang.ClassNotFoundException: org.apache.juli.ClassLoaderLogManager

Ok. Shell script string concatenations can't be used in helm value files.

Helm templates are processed before the container starts look like only override is possible. How to access environment variables defined in dockerfile in helm chart value file and amend additional jvm arguments? Thanks


Solution

  • Tell me if I understand correctly. You have already built docker image with env var set to default values and you want to add additional options to same env var at runtime using helm?

    If so, then I can think of two ways. First is to fully override env var with helm (that you try to avoid). Second option is to introduce new env var as @Lukman suggested but you will probably need to handle it with custom entrypoint inside docker image. Something like this:

    #!/bin/bash
    
    set -e
    
    if [[ -n $CATALINA_OPTS_EXTRA ]]; then
      echo "[INFO] Adding additional opts from CATALINA_OPTS_EXTRA"
      export CATALINA_OPTS="$CATALINA_OPTS $CATALINA_OPTS_EXTRA"
    fi
    
    echo "[INFO] Executing container command"
    
    exec "$@"
    

    Remember to first check if base image you are using already has one, then you will need to "extend" it.

    There is also slight change that this Catalina app you are using has support for additional opts using another env var out of the box so you could use that with helm. I could not find any though.

    //EDIT

    There is two more options I can think of. First is to use a script to exec Catalina then use it as container command (or default command).

    export CATALINA_OPTS="$CATALINA_OPTS -XshowSettings:vm
    --add-opens=java.base/java.io=ALL-UNNAMED
    --add-opens=java.base/java.lang.invoke=ALL-UNNAMED
    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
    $CATALINA_OPTS_EXTRA"
    
    exec my-actual-catalina-command
    

    Not Tomcat expert but another option could probably be to set default options in Tomcat config file inside container. It should read config file first and then CATALINA_OPTS as additional options so you could set this env var only in helm.