背景说明

在上篇文章 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包和配置文件

  1. 准备 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
  2. 编写 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<type=OperatingSystem><>(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<type=OperatingSystem><>((?!process_cpu_time)\w+):'
    name: os_$1
    labels: {}
    type: GAUGE
    attrNameSnakeCase: true

    注意:

    更多配置项请参考 Prometheus 官方文档。

部署 Java 应用

部署应用至 Kubernetes 时,需修改 JVM 启动参数以便启动时加载 JMX Exporter。

需要在 JVM 启动参数中添加一项额外的参数,格式如下:

  • 启动参数格式: -javaagent:<jar>=<port>:<config>

配置 Deployment 文件

  1. 挂载 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
  2. 在启动参数中加入如下配置,以启用 jmx exporter 。

    -javaagent:/jmx_prometheus_javaagent-0.15.0.jar=8088:/jmx/prometheus-jmx-config.yaml
  3. 添加新标签,为了方便在 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

注意

在 Deployment 中添加的 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,面板效果图如下: