API のトラフィックが急増した場合、アプリケーションは迅速にスケールする必要があります。このガイドでは、Application Real-Time Monitoring Service (ARMS) からのリアルタイムの秒間クエリ数 (QPS) データを使用して HorizontalPodAutoscaler (HPA) を駆動する方法を説明します。これにより、Pod は CPU やメモリだけでなく、実際のリクエスト負荷に基づいてスケーリングします。
仕組み
Container Service for Kubernetes (ACK) クラスター内の Java アプリケーションを ARMS Application Monitoring に接続すると、各 API のアクセス詳細が ARMS で確認できるようになります。
ARMS Application Monitoring は Java アプリケーションを計測し、API ごとのリクエスト数を Prometheus メトリクスとして公開します。ack-alibaba-cloud-metrics-adapter アドオンは、Managed Service for Prometheus のメトリクスを HPA が使用できる外部メトリクスに変換し、外部メトリクス API を通じて提供します。HPA は、設定したしきい値に基づいて Deployment をスケールアップまたはスケールダウンします。
完全なデータパスは次のとおりです:
[ARMS Application Monitoring] が Java アプリケーションから API ごとのリクエスト数を収集 → [Managed Service for Prometheus] がメトリクスを保存 → [ack-alibaba-cloud-metrics-adapter] が Prometheus データを Kubernetes 外部メトリクス API 形式に変換 → [Kubernetes HPA] がメトリクスを読み取り、Deployment をスケールアップまたはスケールダウンします。
このガイドでは、全体を通して arms-springboot-demo アプリケーションとその /demo/queryUser/10 エンドポイントを例に説明します。
前提条件
開始する前に、次のものが揃っていることを確認してください:
-
クラスターに Managed Service for Prometheus がデプロイされていること。詳細については、「Alibaba Cloud Prometheus を使用したモニタリング」をご参照ください。
-
ack-alibaba-cloud-metrics-adapterアドオンがkube-system名前空間にデプロイされ、そのprometheus.urlフィールドが設定されていること。詳細については、「ack-alibaba-cloud-metrics-adapter のデプロイ」をご参照ください。 -
デモ用に名前空間が作成されていること。このガイドでは
arms-demoを使用します。詳細については、「名前空間とクォータの管理」をご参照ください。 -
Java Development Kit (JDK) がインストールされていること。サポートされている JDK のバージョンについては、「Application Monitoring のネットワーク設定」をご参照ください。
操作手順

ステップ 1:ARMS Application Monitoring アドオンのインストール
ack-onepilot アドオンをインストールして、アプリケーションを ARMS Application Monitoring に接続します。
-
ACK コンソールにログインします。左側のナビゲーションペインで、[クラスター] をクリックします。
-
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションペインで、[アドオン] をクリックします。
-
ack-onepilot を検索し、そのパラメーターを設定してインストールします。
ステップ 2:ARMS アクセス権限の付与
必要な承認は、クラスターの種類によって異なります。
ACK Serverless クラスターまたは Elastic Container Instance (ECI) に接続されたクラスター内のアプリケーションの場合:
RAM クイック承認ページで承認し、ack-onepilot アドオンのすべての Pod を再起動します。
標準の ACK クラスターの場合:
クラスターに ARMS Addon Token が存在するかどうかを確認します。
-
トークンが存在する場合:ARMS はパスワード不要の承認を自動的に実行します。
ACK マネージドクラスターには、デフォルトで ARMS Addon Token が含まれています。一部の古いマネージドクラスターにはない場合があります。その場合は、以下の手順を使用して手動で権限を付与してください。
-
トークンが存在しない場合:手動で権限を付与します。
-
次の内容でカスタムポリシーを作成します。詳細については、「ステップ 1:カスタムポリシーの作成」をご参照ください。
{ "Action": "arms:*", "Resource": "*", "Effect": "Allow" } -
カスタムポリシーをクラスターのワーカー RAM ロールにアタッチします。詳細については、「ステップ 2:カスタムポリシーをワーカー RAM ロールにアタッチする」をご参照ください。
-
ステップ 3:Java アプリケーションでの ARMS Application Monitoring の有効化
Deployment の spec.template.metadata セクションにラベルを追加して、モニタリングを有効にします。
-
ACK コンソールにログインします。左側のナビゲーションペインで、[クラスター] をクリックします。
-
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションペインで、[ワークロード] > [Deployment] を選択します。
-
デプロイメント ページで、YAML のリソースの作成 をクリックします。
-
サンプルテンプレート を選択し、テンプレート (YAML 形式) の
spec.template.metadataの下に次のlabelsを追加します:アプリケーションセキュリティを有効にすると、追加料金が発生します。詳細については、「アプリケーションセキュリティとは」および「課金」をご参照ください。
labels: armsPilotAutoEnable: "on" armsPilotCreateAppName: "<your-deployment-name>" # 必須: アプリケーション名に置き換えます one-agent.jdk.version: "OpenJDK11" # JDK 11 の場合にのみ必須 armsSecAutoEnable: "on" # オプション: アプリケーションセキュリティを有効にします次の YAML の例は、ARMS Application Monitoring を有効にしたステートレス (Deployment) アプリケーションを作成する方法を示します。
-
デプロイを検証します。デプロイメント ページで、対象アプリケーションの アクション 列に ARMS コントロール台 ボタンが表示されます。ARMS コントロール台 をクリックしてモニタリングデータを表示します。左側のナビゲーションペインで インターフェースの呼び出し をクリックすると、HTTP インターフェースのアクセス詳細が表示されます。デモアプリケーションは、インターフェース呼び出しを継続的に自動生成します。
[API 呼び出し] ページには、各 API の応答時間、リクエスト数、エラー数が一覧表示されます。例として、
/demo/randomRT/{id}(5.0 秒)、/demo/invokeConponent(1.2 秒)、/demo/queryUser/{id}(218.07 ms)、/demo/queryNotExistDB/{id}(2.5 ms)、/demo/queryException/{id}(1.4 ms) があります。また、このページには呼び出しトポロジー図と、リクエスト数と応答時間の傾向チャートも表示されます。 -
arms-springboot-demoの Service を作成し、Server Load Balancer (SLB) を介してアプリケーションの API を公開します。-
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションペインで、[ネットワーク] > [Service] を選択します。
-
作成する をクリックして関連アプリケーションの Service を作成し、作成する をクリックします。パラメーターの詳細については、「Service の作成」をご参照ください。
-
Service が作成された後、
arms-demo-svcの 外部 IP アドレス (External IP) (例:47.94.XX.XX:8080) を記録します。 -
外部ポートを介して Service の
/demo/queryUser/10エンドポイントにアクセスします:curl http://47.94.XX.XX:8080/demo/queryUser/10期待される出力:
{"id":1,"name":"KeyOfSpectator","password":"12****"}この出力は、エンドポイントにアクセスできることを示します。
-
ステップ 4:メトリクスアダプターの設定
Managed Service for Prometheus と ack-alibaba-cloud-metrics-adapter アドオン (kube-system にデプロイ) の両方が実行中であることを確認してから、次に進んでください。
このステップでは、ARMS Application Monitoring のリクエスト数データを、HPA が使用できる名前付きの外部メトリクスにマッピングします。hpa.yaml (ステップ 5) で使用されるメトリクス名は、ここで設定する name.as フィールドから生成されます。
4.1 Prometheus URL の取得
-
ARMS コンソールにログインします。
-
左側のナビゲーションペインで、[Managed Service for Prometheus] > インスタンス を選択します。
-
ターゲットインスタンス名 (形式:
arms_metrics_{RegionId}_XXX) をクリックします。左側のナビゲーションペインで、設定 をクリックします。 -
設定 タブの下部で、HTTP API アドレス (Grafana 読み取りアドレス) を表示して記録します。これが Prometheus の URL です。
ページには、[URL] 列と [ネットワーク] 列のある [HTTP API アドレス (Grafana 読み取りアドレス)] が表示されます:
-
パブリック:
https://{RegionId}.arms.aliyuncs.com:9443/api/v1/prometheus/{InstanceID}/{UserID}/{Secret}/cn-beijing -
イントラネット:
http://{RegionId}-intranet.arms.aliyuncs.com:9090/api/v1/prometheus/{InstanceID}/{UserID}/{Secret}/cn-beijing
後のステップのために、パブリックネットワークアドレスを Prometheus URL としてコピーします。
-
4.2 アダプターでの Prometheus URL の設定
-
ACK コンソールにログインします。左側のナビゲーションペインで、[クラスター] をクリックします。
-
[クラスター] ページで、クラスター名をクリックします。左側のナビゲーションペインで、[アプリケーション] > [Helm] を選択します。
-
Helm ページで ack-alibaba-cloud-metrics-adapter を見つけ、操作 列の 更新 をクリックします。
-
リリースのアップデート パネルで、ステップ 4.1 で記録した Prometheus URL を設定します。これは、Helm リリースの
values.yamlファイル内のalibabaCloudMetricsAdapter.prometheus.urlパラメーターに対応します。custom: - metricsQuery: sum(sum(container_memory_working_set_bytes)by(pod) * on(pod) group_right sum(<<.Series>>{<<.LabelMatchers>>}) by(pod)) / 1024 / 1024 / 1024 name: as: container_memory_working_total matches: ^(.*)_labels resources: overrides: namespace: resource: namespace pod: resource: pod seriesQuery: kube_pod_labels{namespace!="",pod!=""} default: false enabled: true logLevel: 4 metricsRelistInterval: 1m tls: ca: "" certificate: "" enable: false key: "" url: http://cn-beijing-intranet.arms.aliyuncs.com:9090/api/v1/prometheus/ 8cba801fff65546a3012e9a6843xxx/xxx0538168824xxx xxx a174ae4xxx2xxx xxx xxx xxx ramRoleType: restricted replicas: 1 service: type: ClusterIP serviceAccountName: admin tolerations: [] ConfigReloader: image: repository: registry.aliyuncs.com/acs/configmap-reload tag: v0.0.1
4.3 adapter-config に ARMS メトリックルールを追加
-
Helm ページで、[ack-alibaba-cloud-metrics-adapter] をクリックします。
-
基本情報 タブで、[adapter-config] をクリックします。
-
右上隅にある 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 に置き換えます。完全な例は次のとおりです:
4.4 メトリクスの可用性の確認
-
arms_app_requests_per_secondが外部メトリクス 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 6m43s
3 つのビューからスケーリング効果を確認します:
-
ARMS コンソール:ストレステスト中、インターフェースのリクエスト量が急増します。
ARMS Application Monitoring の [概要] タブでは、ストレステスト中 (約 10:58〜10:59) に次のメトリクスの変化が確認できます:
-
[1 分あたりのリクエスト数]:HTTP エントリのリクエスト数が 0 近くから約 1,800 に急増します。
-
[1 分あたりの応答時間]:HTTP エントリの応答時間は 800 ms から 1.6 秒の間で変動します。
-
[1 分あたりの低速呼び出し数]:テストの終わりに向かって、カウントは約 6 に上昇します。
-
[HTTP ステータスコード統計]:リクエスト数に合わせて 200 ステータスコードの数が約 2,400 に急増しますが、他のステータスコードは 0 近くのままです。
-
-
Prometheus ダッシュボード:QPS が設定されたしきい値を超えると、HPA がスケールアウトをトリガーします。
Grafana ダッシュボードでは、
arms_app_requests_countメトリクスの折れ線グラフがストレステスト中に顕著なスパイクを示します。リクエスト数は急増し、その後ベースラインレベルに戻ります。パネルの統計には、最小、最大、平均、現在のリクエスト数が表示され、負荷の変動を確認できます。 -
ACK クラスター:Pod のレプリカ数は、インターフェース呼び出しの QPS に応じてスケールインおよびスケールアウトします。
完全なスケーリングイベント履歴を表示するには、次を実行します:
kubectl describe hpa test-hpa -n arms-demo
高度な例
次の例では、より具体的なスケーリングシナリオのためにメトリクスアダプターを設定する方法を説明します。すべての例では、sum_over_time_lorc を使用して、1 分間のウィンドウでリクエスト数を集計します。
複数のサービスの個別スケーリング
サービスごとに 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 メトリクスの全リストです。