すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:HPA-based elastic scaling with ARMS Application Monitoring

最終更新日:Mar 26, 2026

API トラフィックが急増した場合、ご利用のアプリケーションは十分な速度でスケーリングする必要があります。このガイドでは、ARMS アプリケーションモニタリングによって収集されたライブ QPS (クエリ/秒) データから Horizontal Pod Autoscaler (HPA) を駆動する方法を示します。これにより、Pod は CPU やメモリだけでなく、実際のリクエスト負荷に基づいてスケーリングされます。

仕組み

ARMS アプリケーションモニタリングは、Java アプリケーションをインストルメント化し、API ごとのリクエスト数を Prometheus メトリックとして公開します。 ack-alibaba-cloud-metrics-adapter コンポーネントは、それらの Prometheus メトリックを読み取り、External Metrics API を介して Kubernetes HPA に提供します。 その後、HPA は、設定したしきい値に基づいてデプロイメントをスケールアップまたはスケールダウンします。

完全なデータパスは次のとおりです。

ARMS アプリケーションモニタリングは、ご利用の Java アプリケーションから API ごとのリクエスト数を収集します → Alibaba Cloud Prometheus はメトリックを保存します → ack-alibaba-cloud-metrics-adapter は Prometheus データを Kubernetes External Metrics API 形式に変換します → Kubernetes HPA はメトリックを読み取り、Deployment をスケールアップまたはスケールダウンします。

このガイドでは、arms-springboot-demo アプリケーションとその /demo/queryUser/10 エンドポイントを、全体を通して動作例として使用します。

前提条件

開始する前に、以下があることを確認してください。

  • ご利用のクラスターに Alibaba Cloud Prometheus モニタリングがデプロイされていること。「Alibaba Cloud Prometheus を使用したモニタリング」をご参照ください。

  • ack-alibaba-cloud-metrics-adapter コンポーネントが kube-system 名前空間にデプロイされ、その prometheus.url フィールドが設定されています。詳細については、「ack-alibaba-cloud-metrics-adapter のデプロイ」をご参照ください。`prometheus.url` を設定する

    1. ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

    2. [クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[アプリケーション] > [Helm] を選択します。

    3. [Helm] ページで、ack-alibaba-cloud-metrics-adapter を見つけ、[アクション] 列の [更新] をクリックします。

    4. [リリースの更新]」パネルで、alibabaCloudMetricsAdapter.prometheus.url をお使いの Prometheus データ要求 URL に設定し、「[OK]」をクリックします。> Prometheus データ要求 URL の取得方法については、「Prometheus データ要求 URL の取得方法」をご参照ください。完全な構成ファイルの説明については、「ack-alibaba-cloud-metrics-adapter 構成リファレンス」をご参照ください。

  • デモ用に作成された名前空間。このガイドでは、arms-demo を使用します。詳細については、「名前空間とクォータの管理」をご参照ください。

  • Java 開発キット (JDK) がインストールされていること。サポートされている JDK バージョンについては、「ARMS がサポートする Java コンポーネントとフレームワーク」をご参照ください。

hpa

ステップ 1: ARMS アプリケーションモニタリングコンポーネントのインストール

ack-onepilot コンポーネントをインストールして、アプリケーションを ARMS アプリケーションモニタリングに接続します。

  1. ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[アドオン] をクリックします。

  3. ack-onepilot を検索し、そのパラメーターを構成して、インストールを完了します。

ステップ 2: ARMS アクセス権限の付与

必要な権限付与は、ご利用のクラスタータイプによって異なります。

サーバーレス Kubernetes クラスターまたは ECI に接続されたアプリケーションの場合:

RAM クイック権限付与」ページで権限付与を完了し、その後、ack-onepilot コンポーネントのすべての Pod を再起動します。

標準 ACK クラスターの場合:

クラスターに ARMS アドオントークンが存在するかどうかを確認します。

  1. ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスタ] をクリックします。

  2. [クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[設定] > [シークレット] を選択します。

  3. ページの上部で、[名前空間]kube-system に設定し、addon.arms.token が存在するかどうかを確認します。

  • トークンが存在する場合: ARMS はパスワードなしの権限付与を自動的に実行します。

    ACK マネージドクラスターには、デフォルトで ARMS アドオントークンが含まれています。一部の古いマネージドクラスターにはトークンがない場合があります。その場合は、以下の手順を使用して手動で権限を付与してください。
  • トークンが存在しない場合: 手動で権限を付与します。

    1. 次の内容でカスタムポリシーを作成します。「ステップ 1: カスタムポリシーの作成」をご参照ください。``json { "Action": "arms:*", "Resource": "*", "Effect": "Allow" } ``

    2. カスタムポリシーをクラスターのワーカー RAM ロールにアタッチします。「ステップ 2: クラスターのワーカー RAM ロールに権限を付与する」をご参照ください。

ステップ 3: Java アプリケーションの ARMS アプリケーションモニタリングの有効化

モニタリングを有効化するには、Deployment の spec.template.metadata セクションにラベルを追加します。

  1. ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター] ページで、クラスター名をクリックします。 左側のナビゲーションウィンドウで、[ワークロード] > [デプロイメント] を選択します。

  3. [デプロイメント] ページで、[YAML から作成] をクリックします。

  4. 「サンプルテンプレート」からテンプレートを選択します。[テンプレート] フィールドに、spec.template.metadata に次のラベルを追加します。

    アプリケーションセキュリティを有効にすると、追加料金が発生します。「アプリケーションセキュリティとは」および「課金」をご参照ください。
    labels:
      armsPilotAutoEnable: "on"
      armsPilotCreateAppName: "<your-deployment-name>"  # 必須: ご利用のアプリケーション名に置き換えてください
      one-agent.jdk.version: "OpenJDK11"               # JDK 11 のみ必須
      armsSecAutoEnable: "on"                           # オプション: アプリケーションセキュリティを有効にします

    以下の完全な YAML は、ARMS モニタリングを有効にした arms-springboot-demo アプリケーションをデプロイします。完全な YAML サンプル (Java)

    apiVersion: v1
    kind: Namespace
    metadata:
      name: arms-demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: arms-springboot-demo
      namespace: arms-demo
      labels:
        app: arms-springboot-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: arms-springboot-demo
      template:
        metadata:
          labels:
            app: arms-springboot-demo
            armsPilotAutoEnable: "on"
            armsPilotCreateAppName: "arms-k8s-demo"
            one-agent.jdk.version: "OpenJDK11"
        spec:
          containers:
            - resources:
                limits:
                  cpu: 0.5
              image: registry.cn-hangzhou.aliyuncs.com/arms-docker-repo/arms-springboot-demo:v0.1
              imagePullPolicy: Always
              name: arms-springboot-demo
              env:
                - name: SELF_INVOKE_SWITCH
                  value: "true"
                - name: COMPONENT_HOST
                  value: "arms-demo-component"
                - name: COMPONENT_PORT
                  value: "6666"
                - name: MYSQL_SERVICE_HOST
                  value: "arms-demo-mysql"
                - name: MYSQL_SERVICE_PORT
                  value: "3306"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: arms-springboot-demo
      name: arms-springboot-demo
      namespace: arms-demo
    spec:
      ports:
        - name: arms-demo-svc
          port: 6666
          targetPort: 8888
      selector:
        app: arms-springboot-demo
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: arms-springboot-demo-subcomponent
      namespace: arms-demo
      labels:
        app: arms-springboot-demo-subcomponent
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: arms-springboot-demo-subcomponent
      template:
        metadata:
          labels:
            app: arms-springboot-demo-subcomponent
            armsPilotAutoEnable: "on"
            armsPilotCreateAppName: "arms-k8s-demo-subcomponent"
            one-agent.jdk.version: "OpenJDK11"
        spec:
          containers:
            - resources:
                limits:
                  cpu: 0.5
              image: registry.cn-hangzhou.aliyuncs.com/arms-docker-repo/arms-springboot-demo:v0.1
              imagePullPolicy: Always
              name: arms-springboot-demo-subcomponent
              env:
                - name: SELF_INVOKE_SWITCH
                  value: "false"
                - name: MYSQL_SERVICE_HOST
                  value: "arms-demo-mysql"
                - name: MYSQL_SERVICE_PORT
                  value: "3306"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: arms-demo-component
      name: arms-demo-component
      namespace: arms-demo
    spec:
      ports:
        - name: arms-demo-component-svc
          port: 6666
          targetPort: 8888
      selector:
        app: arms-springboot-demo-subcomponent
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: arms-demo-mysql
      namespace: arms-demo
      labels:
        app: mysql
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          containers:
            - resources:
                limits:
                  cpu: 0.5
              image: registry.cn-hangzhou.aliyuncs.com/arms-docker-repo/arms-demo-mysql:v0.1
              name: mysql
              ports:
                - containerPort: 3306
                  name: mysql
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: mysql
      name: arms-demo-mysql
      namespace: arms-demo
    spec:
      ports:
        - name: arms-mysql-svc
          port: 3306
          targetPort: 3306
      selector:
        app: mysql

    YAML Example

  5. デプロイメントを確認します。[Deployments] ページで、対象アプリケーションの [Actions] 列に [ARMS Console] ボタンが表示されます。[ARMS Console] をクリックしてモニタリングデータを表示します。左側のナビゲーションウィンドウで、[Interface Invocation] をクリックして、HTTP インターフェイスのアクセス詳細を確認します。デモアプリケーションは、継続的なインターフェイス呼び出しを自動的に生成します。

    ARMS Console Button

    4

  6. サービス arms-springboot-demo を作成し、負荷分散を有効にします。

    1. [クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[ネットワーク] > [サービス] を選択します。

    2. [作成] をクリックし、サービスを構成してから、[OK] をクリックします。構成の詳細については、「サービスの作成」をご参照ください。

    3. サービスが作成された後、arms-demo-svc外部 IP を記録します(例: 47.94.XX.XX:8080)。

    4. エンドポイントをテストします。``shell curl http://47.94.XX.XX:8080/demo/queryUser/10 ` 期待される出力: `json {"id":1,"name":"KeyOfSpectator","password":"12****"} ``

ステップ 4: メトリックアダプターの構成

重要

続行する前に、Alibaba Cloud Prometheus モニタリングと、ack-alibaba-cloud-metrics-adapter コンポーネント(kube-system にデプロイ済み)の両方とも実行中である必要があります。

このステップでは、ARMS APM のリクエスト数データを、HPA が使用できる名前付き外部メトリックにマッピングします。ステップ 5 の hpa.yaml で使用されるメトリック名は、ここで設定する name.as フィールドから生成されます。

4.1 Prometheus URL の取得

  1. ARMS コンソールにログインします。

  2. 左側のナビゲーションウィンドウで、[Managed Service For Prometheus] > [インスタンス] を選択します。

  3. ターゲットインスタンス名をクリックします(フォーマット:arms_metrics_{RegionId}_XXX)。左ナビゲーションウィンドウで、[設定項目] をクリックします。

  4. [設定項目] タブの下部で、HTTP API URL (Grafana Read URL) を記録します。これは、Prometheus URL です。

    5

4.2 アダプターでの Prometheus URL の設定

  1. ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。

  2. [クラスター]」ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、「[アプリケーション]」>「[Helm]」を選択します。

  3. Helm]ページで、ack-alibaba-cloud-metrics-adapter を見つけて、[操作]列の[更新]をクリックします。

  4. [リリースの更新]」パネルに、上記で記録した Prometheus URL を挿入します。

    8

4.3 adapter-config に ARMS メトリックルールを追加する

  1. [Helm] ページで、[ack-alibaba-cloud-metrics-adapter] をクリックします。

  2. [基本情報] タブで、[アダプター設定] をクリックします。

  3. 右上隅で、[YAML の編集] をクリックします。

  4. 次のルールを adapter-config に追加します。

    rules:
    - metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
    #                                                    ^^ ご利用の ARMS サービス名に置き換えてください
    #                                                                          ^^ ご利用のクラスター ID に置き換えてください
      name:
        as: "${1}_per_second"       # HPA メトリック名を生成します: arms_app_requests_per_second
        matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
      resources:
        namespaced: false
      seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7"}
    #                                                                     ^^ ご利用の ARMS サービス名とクラスター ID に置き換えてください
    

    arms-k8s-demo をお客様の ARMS サービス名に置き換え、cc13c8725****a9839190b7d1695d7` をお客様のクラスター ID に置き換えます。adapter-config` の例を完成させます**

    apiVersion: v1
    data:
      config.yaml: >
        rules:
    
        - metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
          name:
            as: ${1}_bytes_per_second
            matches: ^(.*)_bytes
          resources:
            overrides:
              namespace:
                resource: namespace
              pod:
                resource: pod
          seriesQuery: container_memory_working_set_bytes{namespace!="",pod!=""}
        - metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by
        (<<.GroupBy>>)
          name:
            as: ${1}_core_per_second
            matches: ^(.*)_seconds_total
          resources:
            overrides:
              namespace:
                resource: namespace
              pod:
                resource: pod
          seriesQuery: container_cpu_usage_seconds_total{namespace!="",pod!=""}
        - metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
          name:
            as: "${1}_per_second"
            matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
          resources:
            namespaced: false
          seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7"}
    kind: ConfigMap
    metadata:
      annotations:
        meta.helm.sh/release-name: ack-alibaba-cloud-metrics-adapter
        meta.helm.sh/release-namespace: kube-system
      creationTimestamp: '2024-04-02T02:29:32Z'
      labels:
        app.kubernetes.io/managed-by: Helm
      managedFields:
        - apiVersion: v1
          fieldsType: FieldsV1
          fieldsV1:
            'f:data':
              .: {}
              'f:config.yaml': {}
            'f:metadata':
              'f:annotations':
                .: {}
                'f:meta.helm.sh/release-name': {}
                'f:meta.helm.sh/release-namespace': {}
              'f:labels':
                .: {}
                'f:app.kubernetes.io/managed-by': {}
          manager: rc
          operation: Update
          time: '2024-04-02T02:40:52Z'
      name: adapter-config
      namespace: kube-system
      resourceVersion: '8223891'
      uid: 294634e6-aeae-4048-9e69-365a4ce4b2cd

4.4 メトリックが利用可能であることの確認

  1. arms_app_requests_per_second が External Metrics API に表示されていることを確認します。

    kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1"

    出力で "name":"arms_app_requests_per_second" を探します。

  2. メトリックがリアルタイムデータを返すことを確認します。

    kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/arms-demo/arms_app_requests_per_second" | jq .

    期待される出力:

    {
      "kind": "ExternalMetricValueList",
      "apiVersion": "external.metrics.k8s.io/v1beta1",
      "metadata": {},
      "items": [
        {
          "metricName": "arms_app_requests_per_second",
          "metricLabels": {},
          "timestamp": "2025-02-13T02:51:31Z",
          "value": "2"
        }
      ]
    }

ステップ 5: HPA の作成

以下の内容で hpa.yaml を作成します。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: test-hpa
  namespace: arms-demo
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: arms-springboot-demo
  minReplicas: 1
  maxReplicas: 10
  metrics:
    - type: External
      external:
        metric:
          name: arms_app_requests_per_second   # adapter-config によって生成された名前と一致する必要があります (ステップ 4.3 の name.as フィールド)
        target:
          type: AverageValue
          averageValue: 40                     # QPS が 40 を超えるとスケールアウトします。外部メトリックは Value と AverageValue のみをサポートします

HPA を適用します。

kubectl apply -f hpa.yaml

メトリックデータが取得されていることを確認します。

kubectl get hpa -n arms-demo

期待される出力:

NAME       REFERENCE                         TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
test-hpa   Deployment/arms-springboot-demo   12/40 (avg)   1         10        1          113s

空でない TARGETS 値は、HPA がメトリックデータを正常に読み取っていることを確認します。

ステップ 6: ストレステストによる弾力的スケーリングの検証

デモ アプリケーションに対してストレステストを実行します。 「47.94.XX.XX:8080」を「arms-demo-svc」の外部エンドポイントに置き換えます。

ab -c 50 -n 2000 http://47.94.XX.XX:8080/demo/queryUser/10

テストの実行中に、HPA を監視します。

kubectl get hpa -n arms-demo

スケーリング後の期待される出力:

NAME       REFERENCE                         TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
test-hpa   Deployment/arms-springboot-demo   47500m/40 (avg)   1         10        10         6m43s

3 つのビューからスケーリング効果を確認します。

  • ARMS コンソール: ストレステスト中に、インターフェイスのリクエストボリュームが急激にスパイクします。

    image

  • Prometheus ダッシュボード: QPS が構成されたしきい値を超えると、HPA がスケールアウトをトリガーします。

    image

  • ACK クラスター: Pod レプリカ数は、インターフェイス呼び出しの QPS に応じてスケールインおよびスケールアウトします。

完全なスケーリングイベント履歴を表示するには、次を実行します。

kubectl describe hpa test-hpa -n arms-demo

高度な例

次の例では、より具体的なスケーリングシナリオ向けにメトリックアダプターを設定する方法を示します。すべての例で、1 分間のウィンドウにおけるリクエスト数を集計するために sum_over_time_lorc を使用しています。

複数のサービスを個別にスケーリング

サービスごとに 1 つのルールを定義し、それぞれに一意のメトリック名を付けて、HPA がそれらを個別にターゲットにできるようにします。

rules:
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
  name:
    as: "${1}_per_second_arms_k8s_demo"
    matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
  resources:
    namespaced: false
  seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo-subcomponent",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
  name:
    as: "${1}_per_second_arms_k8s_demo_subcomponent"
    matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
  resources:
    namespaced: false
  seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo-subcomponent",clusterId="cc13c8725******a9839190b7d1695d7"}

特定の RPC エンドポイントに基づくスケーリング

クエリに rpc ラベルを追加して、サービスのすべてのトラフィックではなく、単一のエンドポイントを対象とします。

rules:
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryUser/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
  name:
    as: "${1}_per_second_arms_k8s_demo_queryUser"
    matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
  resources:
    namespaced: false
  seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryUser/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryException/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
  name:
    as: "${1}_per_second__arms_k8s_demo_queryException"
    matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
  resources:
    namespaced: false
  seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryException/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryNotExistDB/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
  name:
    as: "${1}_per_second__arms_k8s_demo_queryNotExistDB"
    matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
  resources:
    namespaced: false
  seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryNotExistDB/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}

参考資料