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` を設定するACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[アプリケーション] > [Helm] を選択します。
[Helm] ページで、ack-alibaba-cloud-metrics-adapter を見つけ、[アクション] 列の [更新] をクリックします。
「[リリースの更新]」パネルで、
alibabaCloudMetricsAdapter.prometheus.urlをお使いの Prometheus データ要求 URL に設定し、「[OK]」をクリックします。> Prometheus データ要求 URL の取得方法については、「Prometheus データ要求 URL の取得方法」をご参照ください。完全な構成ファイルの説明については、「ack-alibaba-cloud-metrics-adapter 構成リファレンス」をご参照ください。
デモ用に作成された名前空間。このガイドでは、
arms-demoを使用します。詳細については、「名前空間とクォータの管理」をご参照ください。Java 開発キット (JDK) がインストールされていること。サポートされている JDK バージョンについては、「ARMS がサポートする Java コンポーネントとフレームワーク」をご参照ください。

ステップ 1: ARMS アプリケーションモニタリングコンポーネントのインストール
ack-onepilot コンポーネントをインストールして、アプリケーションを ARMS アプリケーションモニタリングに接続します。
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[アドオン] をクリックします。
ack-onepilot を検索し、そのパラメーターを構成して、インストールを完了します。
ステップ 2: ARMS アクセス権限の付与
必要な権限付与は、ご利用のクラスタータイプによって異なります。
サーバーレス Kubernetes クラスターまたは ECI に接続されたアプリケーションの場合:
「RAM クイック権限付与」ページで権限付与を完了し、その後、ack-onepilot コンポーネントのすべての Pod を再起動します。
標準 ACK クラスターの場合:
クラスターに ARMS アドオントークンが存在するかどうかを確認します。
「ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスタ] をクリックします。
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[設定] > [シークレット] を選択します。
ページの上部で、[名前空間] を kube-system に設定し、
addon.arms.tokenが存在するかどうかを確認します。
トークンが存在する場合: ARMS はパスワードなしの権限付与を自動的に実行します。
ACK マネージドクラスターには、デフォルトで ARMS アドオントークンが含まれています。一部の古いマネージドクラスターにはトークンがない場合があります。その場合は、以下の手順を使用して手動で権限を付与してください。
トークンが存在しない場合: 手動で権限を付与します。
次の内容でカスタムポリシーを作成します。「ステップ 1: カスタムポリシーの作成」をご参照ください。``
json { "Action": "arms:*", "Resource": "*", "Effect": "Allow" }``カスタムポリシーをクラスターのワーカー RAM ロールにアタッチします。「ステップ 2: クラスターのワーカー RAM ロールに権限を付与する」をご参照ください。
ステップ 3: Java アプリケーションの ARMS アプリケーションモニタリングの有効化
モニタリングを有効化するには、Deployment の spec.template.metadata セクションにラベルを追加します。
「ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、クラスター名をクリックします。 左側のナビゲーションウィンドウで、[ワークロード] > [デプロイメント] を選択します。
[デプロイメント] ページで、[YAML から作成] をクリックします。
「サンプルテンプレート」からテンプレートを選択します。[テンプレート] フィールドに、
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
デプロイメントを確認します。[Deployments] ページで、対象アプリケーションの [Actions] 列に [ARMS Console] ボタンが表示されます。[ARMS Console] をクリックしてモニタリングデータを表示します。左側のナビゲーションウィンドウで、[Interface Invocation] をクリックして、HTTP インターフェイスのアクセス詳細を確認します。デモアプリケーションは、継続的なインターフェイス呼び出しを自動的に生成します。


サービス
arms-springboot-demoを作成し、負荷分散を有効にします。[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、[ネットワーク] > [サービス] を選択します。
[作成] をクリックし、サービスを構成してから、[OK] をクリックします。構成の詳細については、「サービスの作成」をご参照ください。
サービスが作成された後、
arms-demo-svcの 外部 IP を記録します(例:47.94.XX.XX:8080)。エンドポイントをテストします。``
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 の取得
ARMS コンソールにログインします。
左側のナビゲーションウィンドウで、[Managed Service For Prometheus] > [インスタンス] を選択します。
ターゲットインスタンス名をクリックします(フォーマット:
arms_metrics_{RegionId}_XXX)。左ナビゲーションウィンドウで、[設定項目] をクリックします。[設定項目] タブの下部で、HTTP API URL (Grafana Read URL) を記録します。これは、Prometheus URL です。

4.2 アダプターでの Prometheus URL の設定
「ACK コンソール」にログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
「[クラスター]」ページで、クラスター名をクリックします。左側のナビゲーションウィンドウで、「[アプリケーション]」>「[Helm]」を選択します。
[Helm]ページで、ack-alibaba-cloud-metrics-adapter を見つけて、[操作]列の[更新]をクリックします。
「[リリースの更新]」パネルに、上記で記録した Prometheus URL を挿入します。

4.3 adapter-config に ARMS メトリックルールを追加する
[Helm] ページで、[ack-alibaba-cloud-metrics-adapter] をクリックします。
[基本情報] タブで、[アダプター設定] をクリックします。
右上隅で、[YAML の編集] をクリックします。
次のルールを
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 メトリックが利用可能であることの確認
arms_app_requests_per_secondが External Metrics API に表示されていることを確認します。kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1"出力で
"name":"arms_app_requests_per_second"を探します。メトリックがリアルタイムデータを返すことを確認します。
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 6m43s3 つのビューからスケーリング効果を確認します。
ARMS コンソール: ストレステスト中に、インターフェイスのリクエストボリュームが急激にスパイクします。

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

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"}参考資料
「アプリケーションモニタリングメトリックの説明」— アダプタールールで使用できる ARMS メトリックの完全なリスト