LoginSignup
5
0

More than 3 years have passed since last update.

EC2で動作するKeycloakのJVMメトリクスをcloudwatchに送信する

Last updated at Posted at 2020-12-21

株式会社GxPの@rasahina-gxpです。
本記事はグロースエクスパートナーズアドベントカレンダーの21日目の記事です。

皆さんKeycloak使っていますでしょうか?
私の所属する部署でSSOを実現する場合、プロバイダとしてはKeycloakを利用することが多いです。
普段はSSOのクライアント側としてSpringBootでKeycloakAdapterを利用しての開発が多いのですが、今回KeycloakのJVMメトリクスを取得する作業を実施しましたのでご紹介させて頂きます。

Keycloakとは

Wildflyベースで作られているオープンソースのアイデンティティ管理ソフトウェアです。公式サイト
詳細はこちらの記事がわかりやすいのでご参照ください。
前述の様にSpringBoot向けにクライアントアダプターが用意されているように、
様々な言語、フレームワーク向けにクライアントアダプターが用意されています。

KeycloakのJVMメトリクス取得方法検討

ざっと調べてみた結果以下のメトリクス取得が考えられます。(SaaSを除く)

方法 特徴
Prometheusエクステンション 公式でも紹介されているエクステンションを追加することで利用可能
Wildfly設定ファイルで有効化 設定ファイルを変更することで利用可能
Jolokiaをエージェントとして利用 Keycloakに手を入れる必要がなく、Keycloakの外側から利用可能

どれを採用するかについて今回の要件を踏まえて以下の様に判断しました。

Prometheusエクステンション利用

Keycloak公式サイトにも記載されているエクステンションのため、安心感が高いです。
また、エクステンションを追加してからメトリクスを見れるようになるまでの手間が少ないです。(参考:https://qiita.com/t-mogi/items/3bac5e45afec8d5b4ed2)
ですが、今回メトリクス取得対象のKeycloakが存在する環境にはPrometheusが存在せず、Cloudwatchにてメトリクスを集中監視しているため、今回は対象外となります。

Wildfly設定ファイルで有効化

standalone.xmlなどで管理エンドポイントを有効化するだけです。
JConsoleではあっという間に接続できるようになるのですが、
jmx取得のクライアントツール(Command-line JMX ClientJmxterm等)ではそのまま取得できず、一工夫必要です。
また、監視対象Keycloakの構築はお客様にて行われているということもあり、Keycloak自体にはなるべく手を入れたくありません。
従ってこの手法については今回はデメリットとなるため、対象外とします。

Jolokiaエージェント利用

JolokiaはJMXメトリクスをHTTPで取得できるように公開するツールです。cURL等でアクセスすることでJSONにてメトリクスを取得することができます。
Keycloakの設定を変更することなく、JVMメトリクスを利用できるようになるものポイントです。

ということで今回は要件に最もマッチするJolokiaを利用する方法をご紹介したいと思います。

設定手順

前提

Keycloakのバージョンは7.0.0です。
ダウンロードし、stanndaloneモードで起動しておきます。1 
参考:https://qiita.com/ryota_i/items/69ded3fd950c7f9b70f5
また、サーバーにAWS CLIがインストールされている必要があります。
参考:https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html

Jolokiaダウンロード

こちらのページからJVM-Agentをダウンロードします。

Jolokia起動

Jololiaを起動するには二つの方法があります。

方法1:対象のプロセスIDを指定してプロセスにアタッチ

以下のコマンドを実行すると、アタッチ可能なJavaプロセスが一覧で表示されます。

$ java -jar jolokia-jvm-1.6.2-agent.jar list
23997   jolokia-jvm-1.6.2-agent.jar list
23838   /opt/oss/keycloak-7.0.0/jboss-modules.jar -mp /opt/oss/keycloak-7.0.0/modules org.jboss.as.standalon

続いて対象のプロセスIDをパラメータとして再度実行します。

$ java -jar jolokia-jvm-1.6.2-agent.jar start 23838
Couldn't start agent for PID 23838
Possible reason could be that port '8778' is already occupied.
Please check the standard output of the target process for a detailed error message.

8778が埋まっているのでスタートできないというエラーメッセージが出力されていますが、
Keycloak側のログには以下が出力されていますので、jolokiaの起動には成功しています。

02:50:55,576 INFO  [stdout] (JolokiaStart) I> No access restrictor found, access to any MBean is allowed
02:50:56,803 INFO  [stdout] (JolokiaStart) Jolokia: Agent started with URL http://127.0.0.1:8778/jolokia/

ではcURLでJVMメトリクスを取得してみましょう。
アクセス方法の詳細についてはこちらをご参照ください。

# ヒープ利用量の情報を取得
$ curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/HeapMemoryUsage | jq
{
  "request": {
    "mbean": "java.lang:type=Memory",
    "attribute": "HeapMemoryUsage",
    "type": "read"
  },
  "value": {
    "init": 268435456,
    "committed": 705691648,
    "max": 954728448,
    "used": 293532344
  },
  "timestamp": 1608432046,
  "status": 200
}

パスに属性を付けることで取得する結果を絞ることもできます。

# ヒープ利用量の最大値を取得
$ curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/HeapMemoryUsage/max | jq
{
  "request": {
    "path": "max",
    "mbean": "java.lang:type=Memory",
    "attribute": "HeapMemoryUsage",
    "type": "read"
  },
  "value": 954728448,
  "timestamp": 1608432086,
  "status": 200
}

方法2:JAVA_OPTSに-javaagentとして指定してアタッチ

JVMメトリクス取得対象アプリを実行する際の環境変数JAVA_OPTS-javaagentとして指定することでもJolokiaを対象プロセスにアタッチすることができます。
(Jolokiaのポートに外部からアクセスできないようにセキュリティグループやファイアーウォールで制御する必要があります。)

$ JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -javaagent:/home/centos/jolokia-jvm-1.6.2-agent.jar=port=8778,host=127.0.0.1" \
./standalone.sh
JAVA_OPTS already set in environment; overriding default settings with values:  -Djboss.modules.system.pkgs= -javaagent:/home/centos/jolokia-jvm-1.6.2-agent.jar=port=8778,host=127.0.0.1
=========================================================================

  JBoss Bootstrap Environment

  JBOSS_HOME: /opt/oss/keycloak-7.0.0

  JAVA: java

  JAVA_OPTS:  -server  -Djboss.modules.system.pkgs= -javaagent:/home/centos/jolokia-jvm-1.6.2-agent.jar=port=8778,host=127.0.0.1

=========================================================================

02:59:36,102 INFO  [org.jboss.modules] (main) JBoss Modules version 1.9.1.Final
I> No access restrictor found, access to any MBean is allowed
Jolokia: Agent started with URL http://127.0.0.1:8778/jolokia/
~~省略~~
02:59:48,945 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 7.0.0 (WildFly Core 9.0.2.Final) started in 13262ms - Started 589 of 884 services (601 services are lazy, passive or on-demand)

方法1と同じようにJolokia起動のメッセージが表示されていますね。
ポイントは-Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGSを指定する必要があるところです。
こちらを指定しないで-javaagenetを指定すると、logmanager関連の問題が発生しKeycloakが起動しません。
同じようにcURLで取得してみましょう。

$ curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/HeapMemoryUsage | jq
{
  "request": {
    "mbean": "java.lang:type=Memory",
    "attribute": "HeapMemoryUsage",
    "type": "read"
  },
  "value": {
    "init": 62914560,
    "committed": 361758720,
    "max": 883949568,
    "used": 136322976
  },
  "timestamp": 1608433444,
  "status": 200
}

こちらも同じように取得できました。

取得できるメトリクスの一覧

/jolokia/listにアクセスすることで取得できるメトリクスの一覧が取得できます。

$ curl -s http://localhost:8778/jolokia/list | jq
# 取得結果はかなり多いので注意が必要

メトリクスをCloudwatchに送信する

ここまで来ると後はCloudwatchに送信するだけです。
弊社メンバー@ttanaka-gxpによる2020年アドベントカレンダーの17日目の記事を参考にスクリプトを書きます。

send-metrics.sh
#!/bin/bash

function put_metics_data() {
    aws cloudwatch put-metric-data --dimensions $1 --timestamp $TIMESTAMP --namespace Jmx --metric-name JmxHeapMemoryUsageCommitted --value $HEAPUSAGE_COMMITED --unit Bytes
    aws cloudwatch put-metric-data --dimensions $1 --timestamp $TIMESTAMP --namespace Jmx --metric-name JmxHeapMemoryUsageUsed --value $HEAPUSAGE_USED --unit Bytes
    aws cloudwatch put-metric-data --dimensions $1 --timestamp $TIMESTAMP --namespace Jmx --metric-name JmxNonHeapMemoryUsageCommitted --value $NONHEAPUSAGE_COMMITED --unit Bytes
    aws cloudwatch put-metric-data --dimensions $1 --timestamp $TIMESTAMP --namespace Jmx --metric-name JmxNonHeapMemoryUsageUsed --value $NONHEAPUSAGE_USED --unit Bytes
}

# Set environment variables
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)

# jolokiaからメトリクスを取得する
# Heap
HEAPUSAGE_COMMITED=`curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/HeapMemoryUsage/committed | jq '.value'`
HEAPUSAGE_USED=`curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/HeapMemoryUsage/used | jq '.value'`

# NonHeap
NONHEAPUSAGE_COMMITED=`curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/NonHeapMemoryUsage/committed | jq '.value'`
NONHEAPUSAGE_USED=`curl -s http://localhost:8778/jolokia/read/java.lang:type=Memory/NonHeapMemoryUsage/used | jq '.value'`

# メトリクスをCloudwatchに送信する
put_metics_data $INSTANCE_ID

このスクリプトを定期的に実行することでCloudwatchにメトリクスを送信することができました。
image.png

まとめ

Jolokiaを使用してシンプルにKeycloakのJVMメトリクスを取得する方法を紹介させて頂きました。
Prometheusが使える環境ではPrometheusエクステンションを使用することを第一に考え、Prometheusを利用できない場合は上記のような方法でメトリクスを取得するのが良いかと思われます。

参考

WildFlyのJMXへスクリプトからアクセスする
https://nekop.hatenablog.com/entry/20140414/1397464827

LogstashからWildflyのJMX情報を取得する
https://qiita.com/mkyz08/items/928ff9089ce971470ef0

俺の Jolokia チートシート
https://cloudpack.media/10332


  1. 通常本番環境ではstandaloneモードは使用しません。 

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0