Mackerelとjolokiaを利用してKafkaのメトリクスを取得する

最近仕事でKafkaを触っていて、モニタリングの整備をしている中で、

「Mackerel Kafka 監視」

とかで検索してもそれらしい情報が出てこなかったので、Java周りから調べて実装した。僕自身はJavaを通らずに生きてきたので大変ためになった。

まずJavaにはJMXという仕組みがあり、ヒープメモリの情報やソフトウェアが独自のメトリクスをJMXの仕様に沿って出力することができる。

これらのメトリクスはJConsoleなどのツールで参照できるらしいのだが、ざっくり調べた感じCUIの情報が多く、現状の自分のスキルと組み合わせる遠回りになる気がしたので、jolokiaというJMXにHTTPを経由してアクセスできるソフトウェアを利用した。

今回の構成としては confluentinc/cp-kafka のDockerイメージを用いて、Kafkaクラスタを構成している。

docker-composeをこんな感じで書く。

version: '3.1'
services:
  kafka:
    image: confluentinc/cp-kafka:5.1.0-1
    network_mode: "host"
    environment:
      ~
      KAFKA_OPTS: "-javaagent:/opt/jolokia-jvmagent.jar=port=8778,host=localhost"
    volumes:
      - /opt/jolokia/jolokia-jvm-1.6.0-agent.jar:/opt/jolokia-jvmagent.jar

jolokia-jvm-1.6.0-agent.jar公式サイトからダウンロードできる。

正常に動けばcurlでアクセスができます。

# curl -s http://127.0.0.1:8778/jolokia/read/kafka.*:* | jq '.value' | head
{
  "kafka.cluster:name=InSyncReplicasCount,partition=37,topic=__consumer_offsets,type=Partition": {
    "Value": 1
  },
  "kafka.network:name=ResponseQueueTimeMs,request=ListGroups,type=RequestMetrics": {
    "Mean": 0,
    "StdDev": 0,
    "75thPercentile": 0,
    "98thPercentile": 0,
    "Min": 0,

これらをMackerelに投稿すれば、グラフが見れるのだが、いかんせん項目が多いので、公式のモニタリング指標に従って、ある程度キーを絞る実装を書いた。

#!/bin/bash
json=$(curl -s http://127.0.0.1:8778/jolokia/read/kafka.*:* | jq '.value | to_entries[] | 
select(.key | test("kafka.controller:name=OfflinePartitionsCount,type=KafkaController") or
test("kafka.server:name=UnderReplicatedPartitions,type=ReplicaManager") or
test("kafka.controller:name=OfflinePartitionsCount,type=KafkaController") or
test("kafka.controller:name=ActiveControllerCount,type=KafkaController") or
test("kafka.server:name=FailedProduceRequestsPerSec,type=BrokerTopicMetrics") or
test("kafka.server:name=FailedFetchRequestsPerSec,type=BrokerTopicMetrics") or
test("kafka.server:name=MaxLag,clientId=Replica,type=ReplicaFetcherManager"))' | jq -s .)

len=$(echo $json | jq length)
for i in $( seq 0 $(($len - 1)) ); do
  key=$(echo $json | jq -r ".[$i].key"| sed -e 's/:name=/./g' -e 's/,type=/./g')
  for vk in $(echo $json | jq -r  ".[$i].value | keys[]"); do
    value=$(echo $json | jq -r  ".[$i].value.$vk")
    echo -e "$key.$vk\t$value\t`date +%s`"
  done
done

こういうときにシュッと書くのにはShell便利。Mackerelにこんな感じ設定をいれるとシュッとグラフが見れるし、監視設定してFailしたらすぐ気づけますね。

[plugin.metrics.kafka]
command = "/usr/bin/mackerel-plugin-kafka"

自分でやってみて、KafkaやJavaの理解が深まってよかった。もちょい外でも必要になったらRustあたりでなんか書こうかな。