🕳️

Java VM(JVM)のパフォーマンスデータをCloudWatchに連携する方法

2022/11/01に公開

はじめに

こんにちは、山田です。
Java VM(JVM)のパフォーマンスデータをAmazon CloudWatchに連携する方法について記載していきます。
よろしくお願いします。

構成図

構成図は以下の通りです。

・EC2インスタンスに、Tomcatを起動しておき、 Java VM(JVM)のパフォーマンスデータをjstatコマンドにて取得し、Amazon CloudWatchに連携します。
・CloudWatchに連携するためのスクリプトを作成し、cronを用いて定期実行します。

OpenJDK・Tomcat・AWS CLIインストール

はじめに、対象のEC2インスタンスにOpenJDK,Tomcat,AWS CLIをインストールします。

OpenJDKインストール

OpenJDKをインストールします。

yum install java-1.8.0-openjdk

今回はjstatコマンドを使用したいので、開発環境もインストールします。

yum install java-1.8.0-openjdk-devel

OpenJDKがインストールされているか確認します。
以下のように表示されればOKです。

java -version
openjdk version "1.8.0_352"
OpenJDK Runtime Environment (build 1.8.0_352-b08)
OpenJDK 64-Bit Server VM (build 25.352-b08, mixed mode)

Tomcatインストール

Tomcatをインストールします。

cd /usr/local
wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.0.27/bin/apache-tomcat-10.0.27.tar.gz
tar -xvf apache-tomcat-10.0.27.tar.gz
mv apache-tomcat-10.0.27 tomcat10

Tomcatをインストールしたら、ユーザを追加し、権限を付与します。

useradd -r tomcat
chown -R tomcat:tomcat /usr/local/tomcat10

Tomcatを起動します

cd /usr/local/tomcat10/bin
./startup.sh

Tomcatが起動しているか確認します。
プロセスを確認して、以下のような記載があればOKです。

ps -aux | grep tomcat

root        3142  5.7 10.9 2152236 90432 pts/0   Sl   05:55   0:02 //bin/java -Djava.util.logging.config.file=/usr/local/tomcat10/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat10/bin/bootstrap.jar:/usr/local/tomcat10/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat10 -Dcatalina.home=/usr/local/tomcat10 -Djava.io.tmpdir=/usr/local/tomcat10/temp org.apache.catalina.startup.Bootstrap start

AWS CLIインストール

Pythonをインストールします。

yum install python38

AWS CLIをインストールします。

pip3 install awscli

パスを通します。

export PATH=/usr/local/bin:$PATH

AWS CLIのバージョンが確認できればOKです。

aws --vesion

aws-cli/1.26.5 Python/3.8.12 Linux/4.18.0-240.15.1.el8_3.x86_64 botocore/1.28.5

jstatコマンドについて

構築に行く前に、jstatコマンドについて少し記載します。
jstatコマンドは、設置されている HotSpot Java 仮想マシン (JVM) のパフォーマンス統計データを表示させるコマンドです。

今回は-gcオプションを使用し、ガベージコレクトされたヒープの動作に関する統計データを取得します。具体的に、今回取得する項目は以下の通りです。

説明
S0C Survivor領域0の現在の容量(KB)
S1C Survivor領域1の現在の容量(KB)
S0U Survivor領域0の使用率(KB)
S1U Survivor領域1の使用率(KB)
EC Eden領域の現在の容量(KB)
EU Eden領域の使用率(KB)
OC Old領域の現在の容量(KB)
OU Old領域の使用率(KB)
MC メタスペースの容量(KB)
MU メタスペースの使用率(KB)

https://docs.oracle.com/javase/jp/6/technotes/tools/share/jstat.html

IAMロール・エンドポイント作成

EC2からCloudWatchにメトリクスを送信できるようにIAMロールとエンドポイントを作成します。

IAMロール作成

IAMのコンソールを開いて、ロールを作成をクリックします。

許可ポリシーは以下を選択して、IAMロールを作成します。

CloudWatchAgentAdminPolicy

作成したIAMロールはEC2にアタッチしておきます。

エンドポイント作成

エンドポイントのコンソールを開いてエンドポイントを作成をクリックします。

エンドポイントは以下を選択して、エンドポイントを関連付けるサブネットを選択してエンドポイントを作成します。

com.amazonaws.ap-northeast-1.monitoring

スクリプト作成

EC2インスタンスにログインし、/usr/bin/jvm.shを作成します。

jvm.sh
export PATH=/usr/local/bin:$PATH

tomcat=`ps -aux | grep java | grep tomcat| tr -s ' '| cut -d ' ' -f 2`
S0CUtilization=`sudo jstat  -gc $tomcat | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 1`
S1CUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 2`
S0UUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 3`
S1UUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 4`
ECUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 5`
EUUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 6`
OCUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 7`
OUUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 8`
MCUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 9`
MUUtilization=`sudo jstat  -gc $tomcat  | tail -1 | tr -s ' ' | cut -c1-100 | cut -d ' ' -f 10`

instanceId=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
region=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//')

jvm_metric="--namespace JVM"
jvm_metric=${jvm_metric}" --metric-name S0CUtilization"
jvm_metric=${jvm_metric}" --dimensions InstanceId=${instanceId}"
jvm_metric=${jvm_metric}" --unit Kilobytes"
jvm_metric=${jvm_metric}" --region ${region}"
jvm_metric=${jvm_metric}" --value ${S0CUtilization}"

aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name S1CUtilization"
jvm_metric=${jvm_metric}" --value ${S1CUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name S0UUtilization"
jvm_metric=${jvm_metric}" --value ${S0UUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name S1UUtilization"
jvm_metric=${jvm_metric}" --value ${S1UUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name ECUtilization"
jvm_metric=${jvm_metric}" --value ${ECUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name EUUtilization"
jvm_metric=${jvm_metric}" --value ${EUUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name OCUtilization"
jvm_metric=${jvm_metric}" --value ${OCUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name OUUtilization"
jvm_metric=${jvm_metric}" --value ${OUUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name MCUtilization"
jvm_metric=${jvm_metric}" --value ${MCUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

jvm_metric=${jvm_metric}" --metric-name MUUtilization"
jvm_metric=${jvm_metric}" --value ${MUUtilization}"
aws cloudwatch put-metric-data ${jvm_metric}

cronを設定して、5分おきにスクリプトが実行されるようにします。

/etc/cron/cron.d/jvm
*/5 * * * * root sh /usr/bin/jvm.sh

動作確認

CloudWatchのコンソール画面を開き、メトリクスが取得できていれば完了です!

Discussion