背景说明
在上篇文章 K8S 中使用 Prometheus 监控 JVM (一) 中,我们基于 Kubernetes 的 Service 实现了监控 Pod 中java应用的 JVM 信息。但其实这并不适用于所有的环境,因为在实际环境中并不是所有的 Pod(微服务)都会有自己对应的 Service,所以那些没有使用到 Service 的 Pod 就无法通过上篇文章那种实现来监控 JVM 信息了。现在我们就来解决这个问题。
本篇文章会基于 Pod 控制器的方式来实现 JVM 信息的监控,下面以 Deployment 控制器为例。
操作步骤
使用 JMX Exporter 暴露 JVM 监控指标
使用 JVM 进程内启动(in-process)方式,启动 JVM 需指定 JMX Exporter 的 jar 包文件和配置文件。jar 包为二进制文件,不便通过 ConfigMap
挂载,建议直接将 JMX Exporter 的 jar 包和配置文件都打包到业务容器镜像中。
这里为了方便演示,jar 包就简单用 hostPath
的方式直接挂载进容器里,配置文件使用 ConfigMap
的形式挂载到容器里。
准备jar包和配置文件
-
准备 jar 包文件,可前往 jmx_exporter 的 Github 页面获取最新的 jar 包下载地址。执行以下命令,下载到挂载指定的
hostPath
目录。$ mkdir -p /data/prometheus/jmx_exporter $ wget -O /data/prometheus/jmx_exporter/jmx_prometheus_javaagent-0.15.0.jar https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.15.0/jmx_prometheus_javaagent-0.15.0.jar
-
编写 JMX Exporter 配置文件
prometheus-jmx-config.yaml
。apiVersion: v1 kind: ConfigMap metadata: name: prometheus-jmx-config namespace: default data: prometheus-jmx-config.yaml: | lowercaseOutputLabelNames: true lowercaseOutputName: true whitelistObjectNames: ["java.lang:type=OperatingSystem"] blacklistObjectNames: [] rules: - pattern: 'java.lang
(committed_virtual_memory|free_physical_memory|free_swap_space|total_physical_memory|total_swap_space)_size:' name: os_$1_bytes labels: {} type: GAUGE attrNameSnakeCase: true - pattern: 'java.lang ((?!process_cpu_time)\w+):' name: os_$1 labels: {} type: GAUGE attrNameSnakeCase: true 注意:
更多配置项请参考 Prometheus 官方文档。
部署 Java 应用
部署应用至 Kubernetes 时,需修改 JVM 启动参数以便启动时加载 JMX Exporter。
需要在 JVM 启动参数中添加一项额外的参数,格式如下:
- 启动参数格式:
-javaagent:<jar>=<port>:<config>
配置 Deployment 文件
-
挂载 jmx exporter 配置文件、jar包。
首先需要把 jar 包 和 ConfigMap 挂载进 Deployment 中(路劲自行调整):
volumeMounts: - mountPath: "/jmx_prometheus_javaagent-0.15.0.jar" name: jmx-prometheus-javaagent - mountPath: "/jmx" name: prometheus-jmx-config volumes: - name: jmx-prometheus-javaagent hostPath: path: /data/prometheus/jmx_exporter/jmx_prometheus_javaagent-0.15.0.jar - configMap: name: prometheus-jmx-config name: prometheus-jmx-config
-
在启动参数中加入如下配置,以启用 jmx exporter 。
-javaagent:/jmx_prometheus_javaagent-0.15.0.jar=8088:/jmx/prometheus-jmx-config.yaml
-
添加新标签,为了方便在 Promethues 做匹配。
在
deployment.spec.template.metadata.labels.
下加入新的 label ,如下:prometheus.monitor/port: "8088" prometheus.monitor/jvm: "true"
Deployment 完整示例
下面以Spring Cloud中的Eureka服务为示例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: eureka-service
name: eureka-service
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: eureka-service
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: eureka-service
prometheus.monitor/port: "8088"
prometheus.monitor/jvm: "true"
spec:
containers:
- name: eureka-service
image: eureka:v3.0
args:
- java
- -Xmx2024m
- -javaagent:/jmx_prometheus_javaagent-0.15.0.jar=8088:/jmx/prometheus-jmx-config.yaml
- -jar
- app.jar
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
volumeMounts:
- mountPath: /data/gfs/
name: logs
- mountPath: "/jmx_prometheus_javaagent-0.15.0.jar"
name: jmx-prometheus-javaagent
- mountPath: "/jmx"
name: prometheus-jmx-config
restartPolicy: Always
volumes:
- hostPath:
path: /data/logs
name: logs
- name: jmx-prometheus-javaagent
hostPath:
path: /data/prometheus/jmx_exporter/jmx_prometheus_javaagent-0.15.0.jar
- configMap:
name: prometheus-jmx-config
name: prometheus-jmx-config
注意:
在 Service 中添加的
annotations
字段,作用是为了在 Promethues 配置文件的RawJobs
中对标签做一些重新标记配置等。
添加 Prometheus 监控配置
配置 Prometheus,使监控数据可被采集。
在配置文件中添加如下 RawJob 配置:
- job_name: jvm
scrape_interval: 5s
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_prometheus_monitor_jvm]
action: keep
regex: true
- source_labels: [__address__, __meta_kubernetes_pod_label_prometheus_monitor_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: application
regex: (.+)(-.+-.+)
replacement: $1
使用Grafana出图
模板下载链接,下载后直接把文件的json内容复制导入Grafana,面板效果图如下: