Use JMX Exporter to expose JVM monitoring metrics¶
JMX-Exporter provides two usages:
- Start a standalone process. Specify parameters when the JVM starts, expose the RMI interface of JMX, JMX Exporter calls RMI to obtain the JVM runtime status data, Convert to Prometheus metrics format, and expose ports for Prometheus to collect.
- Start the JVM in-process. Specify parameters when the JVM starts, and run the jar package of JMX-Exporter in the form of javaagent. Read the JVM runtime status data in the process, convert it into Prometheus metrics format, and expose the port for Prometheus to collect.
Note
Officials do not recommend the first method. On the one hand, the configuration is complicated, and on the other hand, it requires a separate process, and the monitoring of this process itself has become a new problem. So This page focuses on the second usage and how to use JMX Exporter to expose JVM monitoring metrics in the Kubernetes environment.
The second usage is used here, and the JMX Exporter jar package file and configuration file need to be specified when starting the JVM. The jar package is a binary file, so it is not easy to mount it through configmap. We hardly need to modify the configuration file. So the suggestion is to directly package the jar package and configuration file of JMX Exporter into the business container image.
Among them, in the second way, we can choose to put the jar file of JMX Exporter in the business application mirror, You can also choose to mount it during deployment. Here is an introduction to the two methods:
Method 1: Build the JMX Exporter JAR file into the business image¶
The content of prometheus-jmx-config.yaml is as follows:
...
ssl: false
lowercaseOutputName: false
lowercaseOutputLabelNames: false
rules:
- pattern: ".*"
Note
For more configmaps, please refer to the bottom introduction or Prometheus official documentation.
Then prepare the jar package file, you can find the latest jar package download address on the Github page of jmx_exporter and refer to the following Dockerfile:
FROM openjdk:11.0.15-jre
WORKDIR /app/
COPY target/my-app.jar ./
COPY prometheus-jmx-config.yaml ./
RUN set -ex; \
curl -L -O https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.17.2/jmx_prometheus_javaagent-0.17.2.jar;
ENV JAVA_TOOL_OPTIONS=-javaagent:/app/jmx_prometheus_javaagent-0.17.2.jar=8088:/app/prometheus-jmx-config.yaml
EXPOSE 8081 8999 8080 8888
ENTRYPOINT java $JAVA_OPTS -jar my-app.jar
Notice:
- Start parameter format: -javaagent:=:
- Port 8088 is used here to expose the monitoring metrics of the JVM. If it conflicts with Java applications, you can change it yourself
Method 2: mount via init container container¶
We need to make the JMX exporter into a Docker image first, the following Dockerfile is for reference only:
FROM alpine/curl:3.14
WORKDIR /app/
# Copy the previously created config file to the mirror
COPY prometheus-jmx-config.yaml ./
# Download jmx prometheus javaagent jar online
RUN set -ex; \
curl -L -O https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.17.2/jmx_prometheus_javaagent-0.17.2.jar;
Build the image according to the above Dockerfile: docker build -t my-jmx-exporter .
Add the following init container to the Java application deployment Yaml:
Click to view YAML file
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-demo-app
labels:
app: my-demo-app
spec:
selector:
matchLabels:
app: my-demo-app
template:
metadata:
labels:
app: my-demo-app
spec:
imagePullSecrets:
- name: registry-pull
initContainers:
- name: jmx-sidecar
image: my-jmx-exporter
command: ["cp", "-r", "/app/jmx_prometheus_javaagent-0.17.2.jar", "/target/jmx_prometheus_javaagent-0.17.2.jar"] ➊
volumeMounts:
- name: sidecar
mountPath: /target
containers:
- image: my-demo-app-image
name: my-demo-app
resources:
requests:
memory: "1000Mi"
cpu: "500m"
limits:
memory: "1000Mi"
cpu: "500m"
ports:
- containerPort: 18083
env:
- name: JAVA_TOOL_OPTIONS
value: "-javaagent:/app/jmx_prometheus_javaagent-0.17.2.jar=8088:/app/prometheus-jmx-config.yaml" ➋
volumeMounts:
- name: host-time
mountPath: /etc/localtime
readOnly: true
- name: sidecar
mountPath: /sidecar
volumes:
- name: host-time
hostPath:
path: /etc/localtime
- name: sidecar # Share the agent folder
emptyDir: {}
restartPolicy: Always
After the above modification, the sample application my-demo-app has the ability to expose JVM metrics. After running the service, we can access the prometheus format metrics exposed by the service through http://lcoalhost:8088
.
Then, you can refer to Java Application Docking Observability with JVM Metrics.