Jetty

このドキュメントでは、Google Cloud Managed Service for Prometheus を使用して Jetty から指標を収集できるように、Google Kubernetes Engine の Deployment を構成する方法について説明します。このドキュメントでは、次の方法について説明します。

  • Jetty のエクスポータを設定して、指標を報告する。
  • エクスポートされた指標を収集するために、Managed Service for Prometheus の PodMonitoring リソースを構成する。
  • Cloud Monitoring のダッシュボードにアクセスして指標を表示する。
  • 指標をモニタリングするようにアラートルールを構成する。

以下の手順は、Managed Service for Prometheus でマネージド コレクションを使用している場合にのみ適用されます。セルフデプロイ コレクションを使用する場合は、JMX エクスポータのソース リポジトリでインストール情報をご覧ください。

以下の手順は一例であり、ほとんどの Kubernetes 環境で機能します。セキュリティ ポリシーや組織のポリシーの制限により、アプリケーションやエクスポータのインストールに問題がある場合は、オープンソース ドキュメントでサポート情報を確認することをおすすめします。

Jetty の詳細については、Jetty をご覧ください。

前提条件

Managed Service for Prometheus とマネージド コレクションを使用して Jetty から指標を収集するには、Deployment が次の要件を満たしている必要があります。

  • クラスタで Google Kubernetes Engine バージョン 1.21.4-gke.300 以降を実行している必要があります。
  • マネージド コレクションを有効にして、Managed Service for Prometheus を実行する必要があります。詳細については、マネージド コレクションを使ってみるをご覧ください。

  • Jetty とのインテグレーションに Cloud Monitoring で利用可能なダッシュボードを使用するには、jmx-exporter バージョン 0.17.0 以降を使用する必要があります。

    利用可能なダッシュボードの詳細については、ダッシュボードを表示するをご覧ください。

Jetty エクスポータをインストールする

Jetty エクスポータ(jmx-exporter)を Jetty ワークロードのサイドカーとしてインストールすることをおすすめします。サイドカーの使用方法については、マルチコンテナ Pod を使用した Kubernetes での拡張アプリケーションをご覧ください。

Jetty にサイドカーとして jmx-exporter をインストールするには、Jetty の構成を次のように変更します。

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: ConfigMap
metadata:
  name: jetty-exporter
data:
  config.yaml: |
    hostPort: 127.0.0.1:1099
    rules:
    - pattern: "org.eclipse.jetty.deploy<(.*)><>(.*)"
      name: "jetty_deploy_$2"
      labels:
        labelList: "$1"
    - pattern: "org.eclipse.jetty.deploy.providers<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_deploy_providers_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.io<context=(.*), type=(.*), id=(\\d+)><>(\\w+)"
      name: "jetty_io_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.io<type=(.*), id=(\\d+)><>(\\w+)"
      name: "jetty_io_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.jmx<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_jmx_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.logging<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_logging_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.server<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_server_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.server<context=(.*), type=(.*), id=(\\d+)><>(\\w+)"
      name: "jetty_server_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.server.handler<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_server_handler_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.server.session<type=(.*), id=(\\d+)><>(\\w+)"
      name: "jetty_server_session_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.server.session<context=(.*), type=(.*), id=(\\d+)><>(\\w+)"
      name: "jetty_server_session_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.util<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_util_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.util.component<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_util_component_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.servlet<context=(.*), type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_servlet_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.servlet<context=(.*), type=(\\w+), name=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_servlet_$5"
      labels:
        id: "$4"
        type: "$2"
        name: "$3"
        context: "$1"
    - pattern: "org.eclipse.jetty.util.thread<type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_util_thread_$3"
      labels:
        id: "$2"
        type: "$1"
    - pattern: "org.eclipse.jetty.util.thread.strategy<context=(.*), type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_util_thread_strategy_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.webapp<context=(.*), type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_webapp_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.websocket.common<context=(.*), type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_websocket_jakarta_common_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.websocket.jakarta.common<context=(.*), type=(\\w+), id=(\\d+)><>(\\w+)"
      name: "jetty_websocket_jakarta_common_$4"
      labels:
        id: "$3"
        type: "$2"
        context: "$1"
    - pattern: "org.eclipse.jetty.(.*)"
      name: jetty_metric_$1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jetty
spec:
  selector:
    matchLabels:
+      app.kubernetes.io/name: jetty
  replicas: 1
  template:
    metadata:
      labels:
+        app.kubernetes.io/name: jetty
    spec:
      containers:
      - name: jetty
        image: jetty:11-jdk17-alpine
+        ports:
+        - containerPort: 1099
+          name: jmx
+        env:
+        - name: JAVA_OPTIONS
+          value: "-Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099"
+        args:
+        - "--module=jmx"
+        - "jetty.threadPool.maxThreads=500"
+      - name: exporter
+        image: bitnami/jmx-exporter:0.17.0
+        ports:
+        - containerPort: 9000
+          name: prometheus
+        command:
+          - java
+          - -jar
+          - jmx_prometheus_httpserver.jar
+        args:
+          - "9000"
+          - /opt/jmx_exporter/config.yaml
+        volumeMounts:
+        - mountPath: /opt/jmx_exporter/config.yaml
+          subPath: config.yaml
+          name: jetty-exporter
+      volumes:
+      - name: jetty-exporter
+        configMap:
+          name: jetty-exporter
+          items:
+          - key: config.yaml
+            path: config.yaml
---

+ 記号で始まるすべての行を構成に追加する必要があります。

構成の変更をローカル ファイルから適用するには、次のコマンドを実行します。

kubectl apply -n NAMESPACE_NAME -f FILE_NAME

Terraform を使用して構成を管理することもできます。

PodMonitoring リソースを定義する

ターゲット ディスカバリの場合、Managed Service for Prometheus Operator には、同じ名前空間内の Jetty エクスポータに対応する PodMonitoring リソースが必要です。

次の PodMonitoring 構成を使用できます。

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: jetty
  labels:
    app.kubernetes.io/name: jetty
    app.kubernetes.io/part-of: google-cloud-managed-prometheus
spec:
  endpoints:
  - port: prometheus
    scheme: http
    interval: 30s
    path: /metrics
  selector:
    matchLabels:
      app.kubernetes.io/name: jetty

ラベルセレクタとポートが、Jetty エクスポータをインストールするで使用されているセレクタとポートと一致していることを確認します。

構成の変更をローカル ファイルから適用するには、次のコマンドを実行します。

kubectl apply -n NAMESPACE_NAME -f FILE_NAME

Terraform を使用して構成を管理することもできます。

ルールとアラートを定義する

次の Rules 構成を使用して、Jetty 指標に関するアラートを定義できます。

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: monitoring.googleapis.com/v1
kind: Rules
metadata:
  name: jetty-rules
  labels:
    app.kubernetes.io/component: rules
    app.kubernetes.io/name: jetty-rules
    app.kubernetes.io/part-of: google-cloud-managed-prometheus
spec:
  groups:
  - name: jetty
    interval: 30s
    rules:
    - alert: JettyLongThreadQueue
      annotations:
        description: |-
          Jetty long thread queue
            VALUE = {{ $value }}
            LABELS: {{ $labels }}
        summary: Jetty long thread queue (instance {{ $labels.instance }})
      expr: jetty_util_thread_queueSize >= 10
      for: 5m
      labels:
        severity: critical
    - alert: JettyNoThreadsAvailable
      annotations:
        description: |-
          Jetty no threads available
            VALUE = {{ $value }}
            LABELS: {{ $labels }}
        summary: Jetty no threads available (instance {{ $labels.instance }})
      expr: jetty_util_thread_idleThreads == 0
      for: 5m
      labels:
        severity: critical

構成の変更をローカル ファイルから適用するには、次のコマンドを実行します。

kubectl apply -n NAMESPACE_NAME -f FILE_NAME

Terraform を使用して構成を管理することもできます。

ルールをクラスタに適用する方法については、マネージド ルールの評価とアラートをご覧ください。

アラートのしきい値は、アプリケーションに合わせて調整できます。

構成を確認する

Metrics Explorer を使用すると、Jetty エクスポータが正しく構成されていることを確認できます。Cloud Monitoring が指標を取り込むまでに 1~2 分かかる場合があります。

指標が取り込まれていることを確認します。

  1. Google Cloud コンソールで、[Metrics Explorer] ページに移動します。

    Metrics Explorer に移動

    検索バーを使用してこのページを検索する場合は、小見出しが [Monitoring] である結果を選択します。

  2. クエリビルダー ペインのツールバーで、[MQL] または [PROMQL] という名前のボタンを選択します。
  3. [言語] で [PromQL] が選択されていることを確認します。言語切り替えボタンは、クエリの書式設定と同じツールバーにあります。
  4. 次のクエリを入力して実行します。
    up{job="jetty", cluster="CLUSTER_NAME", namespace="NAMESPACE_NAME"}

ダッシュボードを表示

Cloud Monitoring インテグレーションには、Jetty Prometheus の概要ダッシュボードが含まれています。ダッシュボードは、インテグレーションを構成すると自動的にインストールされます。インテグレーションをインストールすることなく、ダッシュボードの静的プレビューを表示することもできます。

インストールされているダッシュボードを表示する手順は次のとおりです。

  1. Google Cloud コンソールで [ダッシュボード] ページに移動します。

    [ダッシュボード] に移動

    検索バーを使用してこのページを検索する場合は、小見出しが [Monitoring] の結果を選択します。

  2. [ダッシュボード リスト] タブを選択します。
  3. [統合] カテゴリを選択します。
  4. ダッシュボードの名前(Jetty Prometheus の概要 など)をクリックします。

ダッシュボードの静的プレビューを表示する手順は次のとおりです。

  1. Google Cloud コンソールで [統合] ページに移動します。

    [インテグレーション] に移動

    検索バーを使用してこのページを検索する場合は、小見出しが [Monitoring] の結果を選択します。

  2. [デプロイメント プラットフォーム] フィルタの [Kubernetes Engine] をクリックします。
  3. Jetty インテグレーションを見つけ、[詳細を表示] をクリックします。
  4. [ダッシュボード] タブを選択します。

トラブルシューティング

指標の取り込みに関する問題のトラブルシューティングについては、取り込み側の問題のトラブルシューティングエクスポータからの収集に関する問題をご覧ください。