I see that you used OpenJDK Alpine to deploy a JAVA application, so you need to use this environment "JAVA_TOOL_OPTIONS" instead of "JAVA_OPTS", something like:
spec:
containers:
- name: jvm_options
image: xxx:xxx
env:
- name: JAVA_TOOL_OPTIONS
value: "-Xmx768m -XX:MaxMetaspaceSize=256m"
Once your application is running, you can check the application log and you will find the log below:
Picked up JAVA_TOOL_OPTIONS: -Xmx768m -XX:MaxMetaspaceSize=256m
Answer from HKBN-ITDS on Stack Overflowappending additional options to JAVA_TOOL_OPTIONS at runtime
docker - Passing java_opts to spring boot applications in kubernetes - Stack Overflow
Kubernetes args with java options
Java options within Kubernetes container - Stack Overflow
I see that you used OpenJDK Alpine to deploy a JAVA application, so you need to use this environment "JAVA_TOOL_OPTIONS" instead of "JAVA_OPTS", something like:
spec:
containers:
- name: jvm_options
image: xxx:xxx
env:
- name: JAVA_TOOL_OPTIONS
value: "-Xmx768m -XX:MaxMetaspaceSize=256m"
Once your application is running, you can check the application log and you will find the log below:
Picked up JAVA_TOOL_OPTIONS: -Xmx768m -XX:MaxMetaspaceSize=256m
You can use command and args under the containers section for this. for example:
containers:
- name: test
image: test:latest
command: ["java"]
args: ["-Xms256m","-Xmx768m","-jar","/app.jar"]
You can use command in k8s deployment manifest:
containers:
- name: mycontainer
env:
- name: NAME
value: VALUE
command: [ "java"]
args: ["-jar", "-D..."]
You could also include it in your kubernetes deployment yaml file alongside the rest of your environment variables that you wish to pass into your docker container:
- name: JAVA_OPTS
value: >-
-Djava.security.egd=file:/dev/./urandom
-Djsversion=1.0 -D<variable>=<service-1> -D<variable>=<service-2>
- name: SERVER_PORT
value: 8080
In your Helm chart, you need to split out the different low-level JVM settings into individual items in the command: list. The easiest way to do this is to make the Helm-level settings be a list of options, and then you can iterate over it.
# values.yaml
jvmOptions:
- -XX:UseSerialGC
- -Xmx256m
- -XX:MetaspaceSize=64m
# templates/deployments.yaml
command:
- java
{{- range .Values.jvmOptions }}
- {{ toJson . }}
{{- end }}
- -jar
- java_j.jar
Since .Values.jvmOptions is a list here, the template range construct loops through it, setting . to each item in turn. In the example here, I use the toJson extension function to ensure each item is properly quoted as a string that fits on a single line.
Nothing would stop you from having multiple lists of option settings that you combined this way.
If you really want the JVM options as a space-separated string, then you need to split that string into words. There is a splitList extension function (not mentioned in the Helm documentation but it's there) that can do this.
# values.yaml
jvmOptions: "-XX:UseSerialGC -Xmx256M -XX:MetaspaceSize=64m"
# templates/deployments.yaml
command:
- java
{{- range splitList " " .Values.jvmOptions }}
- {{ toJson . }}
{{- end }}
- -jar
- java_j.jar
The template part looks almost identical except for adding splitList in. Note that this is a fairly naïve splitting; there's not going to be any support for quoting or embedding spaces inside a single option or any non-space whitespace.
Finally: note that the standard JVMs do support passing options in environment variables; see for example What is the difference between JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS when using Java 11? You could just set this environment variable without trying to reconstruct command:. (IME if you have a choice, managing Kubernetes manifests tends to be easier if you can set environment variables as opposed to using command-line options.)
# values.yaml
jvmOptions: "-XX:UseSerialGC -Xmx256M -XX:MetaspaceSize=64m"
# templates/deployments.yaml
env:
{{- with .Values.jvmOptions }}
- name: JDK_JAVA_OPTIONS
value: {{ toJson . }}
{{- end }}
According to the Kubernetes docs, split the command array and the arguments array into command and args sections.
When you create a Pod, you can define a command and arguments for the containers that run in the Pod. To define a command, include the
commandfield in the configuration file. To define arguments for the command, include theargsfield in the configuration file. The command and arguments that you define cannot be changed after the Pod is created.The command and arguments that you define in the configuration file override the default command and arguments provided by the container image. If you define args, but do not define a command, the default command is used with your new arguments.
spec:
containers:
- name: test-java-service
image: <your_image_name_here>
command:
- java
args:
- {{ .Values.TEST_JAVA_MEMORY_OPTS | quote }}
- {{ .Values.TEST_JAVA_OPTS | quote }}
- "-jar"
- java_j.jar
When Helm populates values, don't specify the quotes yourself, or else the values replacement string will be interpreted literally as that string. Instead, pipe the Helm value to quote. Place quotes around any value that could be interpreted specially in YAML, such as values with - characters, like your Java options.