JDK Flight Recorderのコンテナでの自動化

Red Hat で Java Platform Advocate として OpenJDK を担当している伊藤ちひろ(@chiroito)です。

この記事は、Red Hat Developerのブログ記事、Automating JDK Flight Recorder in containers | Red Hat Developer の翻訳記事です。


https://developers.redhat.com/sites/default/files/styles/article_feature/public/2020_Java_ContainerJFR_Featured_Article__A-01.png?itok=K_g-UdJY

この記事は、Cryostat 2.0、またはコンテナ用JDK Flight Recorderを使用するためのハンズオンガイドのシリーズの一部です。この記事では、自動化されたルールのためのCryostatの新しいAPIを紹介します。この API の簡潔ながら強力なルール定義を際立たせる 2 つの使用例について説明します。ルール定義を使用して、1つまたは複数のターゲットJavaアプリケーションの条件式を指定する方法と、これらのターゲットで開始したいフライトレコーディングのタイプを構成する方法を説明します。

あなたがルールを作成したら、Cryostatはすぐにすべての既存の検出されたターゲットに対してそれを適用し、あなたのフライトのレコーディングを開始します。Cryostatはまた、その定義に合致する新たに発見されたターゲットにルールを適用します。あなたは、ターゲットの異なる部分集合に一致する、またはあなたの目的のために異なる記録オプションを重ねるために複数のルールを作成できます。

自動化されたルールAPIはCryostat 2.0の新機能で、我々はまだそのためのユーザインタフェース(UI)を開発してはいません。今のところ、Cryostat HTTP APIと直接対話するためにcurlを使用します。

このシリーズの全記事を読む

注意:Cryostat 2.0 の Red Hat ビルドは、現在技術プレビュー版として広く利用できます。Cryostat 2.0 は、自動化されたルール、JSON 形式によるレスポンスの優れた API 、カスタムターゲット、同時ターゲット JMX 接続、WebSocket プッシュ通知など、多くの新機能と改良点を導入しています。Red Hat ビルドには、OpenShift での Cryostat の導入を簡素化し、自動化するための Cryostat Operator が含まれています。

使用例1:コンテナ型JVMでの継続的な監視

以前は、コンテナ化されたJava仮想マシン(JVM)でJDK Flight Recorder(JFR)を使用して常時連続監視を有効にしたい場合、ターゲットアプリケーションにJVM起動引数を設定し、アプリケーションを再起動して監視を開始する必要がありました。Cryostatの自動化されたルールを使えば、JDK Flight Recorderを実行時に有効にして、すでに動作しているターゲットアプリケーションを継続的に監視することができ、再起動や再デプロイ、停止時間が不要になります。

また、停止時間なしで、実行時に連続監視イベントのテンプレートを修正できます。まず、使用したいテンプレートでルールを作成します。次に、新しいテンプレートと、新規または更新されたイベントテンプレートで新しいルールを作成します。最後に、clean=trueパラメータを指定して、元のルールを削除します。以下はそのソースです。

# このURLを実際のCryostatインスタンスのURLに置き換えます。
$ export CRYOSTAT=https://cryostat.example.com 

# Profiling テンプレートを使って firstRule という名前のルールを作成
$ curl -F name="firstRule" -F matchExpression=”target.alias==‘com.example.MainClass’” -F eventSpecifier=”template=Profiling,type=TARGET” $CRYOSTAT/api/v2/rules 

# Profiling テンプレートをコンピュータにダウンロード
$ curl $CRYOSTAT/api/v1/targets/$serviceUri/templates/Profiling/type/TARGET -o profiling.jfc 

# Profiling テンプレートを編集して、内部のイベント定義を更新し、Profiling から Demo に名前を変更
$ $EDITOR profiling.jfc 

# Demoプロファイルとして識別しやすいように、ファイル名をdemo.jfcに変更
$ mv profiling.jfc demo.jfc 

# 新しいDemoプロファイルをCryostatにアップロードする
$ curl -F template=@demo.jfc $CRYOSTAT/api/v1/templates 

# Demoプロファイルを使用して2つ目のRuleを作成
$ curl -F name="secondRule" -F matchExpression=”target.alias==‘com.example.MainClass’” -F eventSpecifier=”template=Demo,type=CUSTOM” $CRYOSTAT/api/v2/rules 

# Profilingテンプレートを使用した最初のRuleを削除し、それが作成したアクティブなレコーディングを削除
$ curl -X DELETE $CRYOSTAT/api/v2/rules/firstRule?clean=true 

使用例2:Kubernetesのラベルやアノテーションを使用したカスタム監視

Kubernetesのラベルやアノテーションなど、プラットフォーム固有の属性を持つターゲットアプリケーションに適用するルールを定義できます。以下はJSON記法による例です。

{
  "name": "k8sMonitoring",
  "description": "jfrMonitoring=trueアノテーションを使用して、任意のターゲットでDemoテンプレートを有効にします",
  "matchExpression": "target.annotations.platform[‘jfrMonitoring’]==’enabled’",
  "eventSpecifier": "template=Demo,type=CUSTOM",
  "archivalPeriodSeconds": 300,
  "preservedArchives": 12
}

このルール定義を作成すると、Cryostatは既存のターゲットアプリケーションを全て確認し、jfrMonitoring=enabledアノテーションが付いた新しいターゲットを探します。一致するターゲットが見つかると、最初の使用例で使用したカスタムDemoテンプレートを使用して、自動的にレコーディングが開始されます。5分ごとに保存されたスナップショットが作成され、1時間分のデータがストレージに保存されます。

このルール定義があれば、Kubernetes や Red Hat OpenShift のユーザーは、kubectl/ocや OpenShift コンソールなどの使い慣れたツールを使って、Cryostat API や UI と直接対話しなくても、監視対象のアプリケーションに目印を付けられるようになります。これは、作業工程のさらなる自動化への扉を開くものです。

例として、通信量やポッドの再起動を監視し、何らかの基準閾値を満たした後にポッドの監視を有効にし、対象アプリケーションの動作が正常に戻ったらその監視を再び無効にするOperatorを使用または実装することが考えられます。Kubernetes 管理者として、この現象が発生したときに通知を受け取り、Cryostat アーカイブをチェックして、問題が発生した期間に記録されたターゲット アプリケーションの JDK Flight Recorder データを取得したり、Cryostat の Grafana ダッシュボードでこれらの保存されたレコーディングを表示できます。

注意:重要な注意点として、CryostatはKubernetesのアノテーションやラベルの変更を監視するものではなく、ターゲットアプリケーションが現れたり消えたりするかどうかだけを監視しています。ターゲットアプリケーションにアノテーションを適用するには、デプロイではなく、アプリケーションポッド(Kubernetesに新しいレプリカを展開させる)にアノテーションまたはラベルを適用します。

Cryostatで条件式の使い方

ルール定義のmatchExpressionは、Cryostatが解釈し、与えられたターゲットにルールを適用すべきかどうかを判断するために使用する、Javaのようなコードの断片です。matchExpressionは論理値で評価されなければなりません。最も単純な matchExpressions は true か false という論理値で、true を使うと、ルールはすべてのターゲットに適用されます。この式は全体に対してターゲット・オブジェクトを持ち、JSON記法では次のような形になります。

{alias”: “myAppAlias”,
  “connectUrl”: “service:jmx:rmi:///jndi/rmi://cryostat:9091/jmxrmi”,labels”: {com.example/service”: “customer-login,
  },
  “annotations”: {platform”: {io.kubernetes/annotation”: “annotated},
    “cryostat”: {PORT”: 9091,
      “HOST”: “cryostat”,
      “NAMESPACE”: “myproject}
  }
}

aliasconnectUrllabelsannotations.platformannotations.cryostatプロパティはすべてターゲットオブジェクトに存在することが保証されています。aliasconnectUrlは空でない文字列になります。labelsplatformのアノテーションは、OpenShiftまたはKubernetesでは、これらはターゲットのPodに適用されたラベルとアノテーションから入力されます(もしあれば)。Cryostatのアノテーションのマップはプラットフォームごとに異なりますが、OpenShiftまたはKubernetesでは、HOSTPORTNAMESPACE、およびPOD_NAMEのキーが存在し、空でないことが期待されます。

以下はmatchExpressionsの例です。

target.alias == ’com.example.MainClass’

target.alias == ’myAlias’

target.labels[‘com.example/service’] == ’customer-login’

target.labels[‘com.example/service’] != ’customer-login’

target.annotations.cryostat.PORT > 3000

target.annotations.cryostat.PORT > 3000 && target.annotations.platform[‘io.kubernetes/annotation’] == ‘enabled’

!!target.annotations.platform[‘io.kubernetes/annotation’]

/^customer-login[0-9]*$/.test(target.alias)

まとめ

この記事では、条件式を使用して Cryostat 監視の自動化ルールを作成する方法について学びました。一度自動化ルールを設定すれば、Cryostat はそのルールで定義された基準を満たすアプリケーションを継続的に監視し、それらのアプリケーションを再起動または再デプロイする必要がありません。詳細については、Cryostat.ioをご覧ください。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。