スクエニ ITエンジニア ブログ

JMX MBean metrics の可視化を試す

今回は Observability の例として、ふとしたきっかけで知った JMX MBean metrics を扱ってみます。
JMX (Java Management Extensions) というと、Java program の debug や一時的な状態確認のような用途の印象があったのですが、これを用いて metrics を公開する application があるのははじめて知りました。この仕組みを利用することにより、application 特有の指標情報を収集して可観測性を向上できます。

検証環境をつくる

Docker Compose を使います。

末尾に compose.yaml を置いておきますが、以下のような構造にしています。

workspace
├─ compose.yaml
├─ jmxexporter.yaml
└─ prom-data
    └─ prometheus.yaml

JMX MBean metrics を公開する application として、Kafka を例にとっています。ちょっと大仰ですが、ちゃんと Kafka を cluster で起動しているので yaml (記事末尾) が大きくなっています。また、動作の様子を視覚的に確認できるように Kafka UI も使えるようにしています。

JMX Exporter

今回のポイントです。

JMX metrics を可視化するにあたり、今回は Prometheus を使ってみました。Prometheus は JMX metrics をそのまま扱うことはできず、その間の橋渡しが必要になるようです。

そこで、JMX Exporter を使います。

以下のような設定 jmxexporter.yaml を使いました。
usernamepassword の指定が可能ですが、認証無しで使用する場合は空欄のまま (下の例のまま) でだいじょうぶです。

startDelaySeconds: 3
hostPort: kafka0:1099
username:
password:

whitelistObjectNames: ["kafka.server:*"]
rules:
  - pattern: ".*"

一番目の Kafka node に JMX で接続するように設定しています。
Kafka には、compose.yaml で以下のように JMX の設定を入れています。

      KAFKA_JMX_OPTS: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka0 -Dcom.sun.management.jmxremote.rmi.port=1099"
      JMX_PORT: 1099

認証や metrics の filtering 設定は最小限になっています (ほとんどしていません)。 whitelistObjectNames は、 ["kafka.server:type=BrokerTopicMetrics,*"] のようにして一部の metrics に限定することもできるようです。このあたりは、実運用環境に入れる際には慎重に設定が必要です。

この設定により、Kafka に JMX で接続し、取得した metrics を Prometheus に対して公開するようになります。

Prometheus

最終的に可視化を確認するために Prometheus を起動します。
以下の設定を使っています。

global:
  scrape_interval: 10s
  evaluation_interval: 10s

scrape_configs:
  - job_name: 'jmx'
    static_configs:
      - targets:
        - jmxexporter:5556

上で説明した、JMX Exporter に接続するように設定しています。

結果

Prometheus の UI で、Kafka の metrics が参照できるようになりました。

Prometheus

参考に、Kafka UI の画像も貼っておきます。
今回はじめて動作させたのですが、きれいにできていて開発・運用などで便利に使えそうですね。

Kafka UI - Brokers
Kafka UI - Topics

まとめ

JMX metrics の取得について調べ、Kafka が公開する metrics を視覚化してみました。安定して値が取れると監視に大きく役立ちそうです。実際に運用に入れる前には、パフォーマンスやセキュリティも確認が必要そうです。

参考

ほか、様々なサイトを参考にさせていただきました。

compose.yaml

最後に、ちょっと長くなってしまいましたが compose.yaml の全体を置いておきます。

version: "3.7"

# create Zookeeper service to manage Kafka
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:5.2.2
    environment:
      ZOOKEEPER_CLIENT_PORT: "2181"

# create first Kafka node
  kafka0:
    image: confluentinc/cp-kafka:5.2.2
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 0
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka0:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092"
      KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
      KAFKA_JMX_OPTS: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka0 -Dcom.sun.management.jmxremote.rmi.port=1099"
      JMX_PORT: 1099
    depends_on:
      - "zookeeper"

# create second Kafka node
  kafka1:
    image: confluentinc/cp-kafka:5.2.2
    ports:
      - "9093:9093"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka1:19093,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9093"
      KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
    depends_on:
      - "zookeeper"

# create third Kafka node
  kafka2:
    image: confluentinc/cp-kafka:5.2.2
    ports:
      - "9094:9094"
    environment:
      KAFKA_BROKER_ID: 2
      KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
      KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka2:19094,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9094"
      KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
    depends_on:
      - "zookeeper"

  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    ports:
      - "8080:8080"
    depends_on:
      - "kafka0"
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka0:19092

  jmxexporter:
    image: bitnami/jmx-exporter
    command:
      - "5556"
      - "/opt/bitnami/jmx-exporter/config.yaml"
    volumes:
      - ./jmxexporter.yaml:/opt/bitnami/jmx-exporter/config.yaml

  prometheus:
    image: prom/prometheus
    command: --config.file=/prometheus-data/prometheus.yaml
    ports:
      - "9090:9090"
    volumes:
      - ./prom-data:/prometheus-data

この記事を書いた人

記事一覧
SQUARE ENIXでは一緒に働く仲間を募集しています!
興味をお持ちいただけたら、ぜひ採用情報ページもご覧下さい!