K8S 中使用 Prometheus 监控 JVM (一)

操作场景

Prometheus 社区开发了 JMX Exporter 用于导出 JVM 的监控指标,以便使用 Prometheus 来采集监控数据。当您的 Java 业务容器化至 Kubernetes 后,可通过本文了解如何使用 Prometheus 与 JMX Exporter 来监控 Java 应用。

 

JMX Exporter 简介

Java Management Extensions,JMX 是管理 Java 的一种扩展框架,JMX Exporter 基于此框架读取 JVM 的运行时状态。JMX Exporter 利用 Java 的 JMX 机制来读取 JVM 运行时的监控数据,然后将其转换为 Prometheus 可辨识的 metrics 格式,以便让 Prometheus 对其进行监控采集。

JMX Exporter 提供启动独立进程JVM 进程内启动(in-process)两种方式暴露 JVM 监控指标:

  1. 启动独立进程
    JVM 启动时指定参数,暴露 JMX 的 RMI 接口。JMX Exporter 调用 RMI 获取 JVM 运行时状态数据,转换为 Prometheus metrics 格式,并暴露端口让 Prometheus 采集。
  2. JVM 进程内启动(in-process)
    JVM 启动时指定参数,通过 javaagent 的形式运行 JMX Exporter 的 jar 包,进程内读取 JVM 运行时状态数据,转换为 Prometheus metrics 格式,并暴露端口让 Prometheus 采集。

说明:

官方不建议使用启动独立进程方式,该方式配置复杂且需单独的进程,进程本身的监控又引发了新的问题。本文以 JVM 进程内启动(in-process)方式为例,在 Kubernetes 环境下使用 JMX Exporter 暴露 JVM 监控指标。

 

操作步骤

使用 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 启动时会读取 JAVA_OPTS 环境变量,作为额外的启动参数,部署时可为应用增加该环境变量。

  • 启动参数格式: -javaagent:<jar>=<port>:<config>
  • 该示例使用8088端口暴露 JVM 的监控指标,您可按需自行更改。

下面以Tomcat为示例:

  1. 编写tomcat的Deployment文件。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tomcat
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: tomcat:jdk8-openjdk-slim
        env:
        - name: JAVA_OPTS
          value: "-javaagent:/jmx_prometheus_javaagent-0.15.0.jar=8088:/jmx/prometheus-jmx-config.yaml"
        resources:
          requests:
            cpu: 300m
            memory: 512Mi
          limits:
            cpu: 500m
            memory: 1024Mi
        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
  1. 编写tomcat的 Service 文件
apiVersion: v1
kind: Service
metadata:
  name: tomcat
  labels:
    app: tomcat
  annotations:
    prometheus.io/port: "8088"
    prometheus.io/jvm: "true"
spec:
  type: NodePort
  selector:
    app: tomcat
  ports:
  - name: http
    port: 8080
    protocol: TCP
  - name: jmx-metrics
    port: 8088
    protocol: TCP

注意

在 Service 中添加的 annotations 字段,作用是为了在 Promethues 配置文件的 RawJobs 中对标签做一些重新标记配置等。

 

添加 Prometheus 监控配置

配置 Prometheus,使监控数据可被采集。示例如下:

- job_name: jvm
  scrape_interval: 5s
  kubernetes_sd_configs:
  - role: endpoints
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_jvm]
    action: keep
    regex: true
  - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
    action: replace
    target_label: __address__
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
  - source_labels: [__meta_kubernetes_service_name]
    action: replace
    regex: (.+)
    target_label: application
    replacement: $1
  - action: labelmap
    regex: __meta_kubernetes_service_label_(.+)

 

添加 Grafana 监控面板

采集数据后可进行数据展示。若熟悉 Prometheus 和 Grafana,则可自行根据指标设计所需面板。您也可直接使用社区提供面板,例如 JVM dashboard。可直接导入使用。

不过上面这个Dashboard,有一些地方使用起来不太友好,所以在其基础上进行了一些修改。

模板下载链接,下载后直接把文件的json内容复制导入Grafana,面板效果图如下:

prometheus-grafana-jmx_exporter

注意

由于这个Dashboard是根据 Promethues 中 RawJobs 定制的,若要使用这个Dashboard,Prometheus 中的 RawJobs 规则需要与文中一致,建议不要修改。否则可能会出现某些功能不生效的情况。(当然,如果你熟悉Promethues,也可以根据自己需求进行调整)

 

参考资料

点赞

发表回复