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

Container Service for Kubernetes:HPA ベースの弾性スケーリングに ARMS アプリケーション監視を使用する

最終更新日:Nov 09, 2025

アプリケーションの API へのリクエストトラフィックが急増した場合、API の秒間クエリ数 (QPS) に基づいて Horizontal Pod Autoscaler (HPA) ポリシーを設定し、アプリケーションを自動的にスケーリングできます。このトピックでは、ARMS アプリケーション監視を使用して、アプリケーションの HPA ベースの弾性スケーリングを実装する方法について説明します。

仕組み

ACK クラスター内の Java アプリケーションを ARMS アプリケーション監視に接続すると、アプリケーションの API の詳細なアクセス情報を取得できます。Java アプリケーションを ARMS アプリケーション監視に接続する方法の詳細については、「Java アプリケーション監視」をご参照ください。ARMS アプリケーション監視は、ARMS データを Alibaba Cloud Prometheus データ形式に変換します。その後、alibaba-cloud-metrics-adapter コンポーネントが Alibaba Cloud Prometheus メトリックを HPA が使用できるメトリックに変換します。このプロセスにより、アプリケーションの HPA ベースの弾性スケーリングが可能になります。

このトピックでは、arms-springboot-demo アプリケーションのデプロイメントと、その /demo/queryUser/10 インターフェイスのストレステストを例として使用します。

前提条件

手順

hpa

ステップ 1: ARMS アプリケーション監視コンポーネントをインストールする

アプリケーションを ARMS アプリケーション監視に接続するには、クラスターに one-pilot コンポーネントをインストールします。

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

  2. クラスター ページで、管理したいクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、[アドオン] をクリックします。

  3. ack-onepilot コンポーネントを検索します。画面の指示に従ってパラメーターを設定し、インストールを完了します。

ステップ 2: ARMS アクセス権限を付与する

  • Serverless Kubernetes クラスター内のアプリケーション、または ECI に接続されているアプリケーションを監視するには、RAM クイック承認ページで権限付与を完了します。その後、ack-onepilot コンポーネントのすべての Pod を再起動します。

  • ACK クラスターアプリケーションを監視するには、まず ARMS Addon Token が存在するかどうかを確認します。

    クラスター内の ARMS Addon Token を確認する方法を表示するにはクリックします

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

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

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

    • ACK クラスターに ARMS Addon Token が存在する場合、ARMS はパスワードなしの権限付与を実行します。

      説明

      デフォルトでは、ARMS Addon Token は ACK マネージドクラスターに存在します。ただし、かなり前に作成された一部の ACK マネージドクラスターには ARMS Addon Token が存在しない場合があります。このような場合は、クラスターへの ARMS アクセス権限を手動で付与する必要があります。

    • ACK クラスターに ARMS Addon Token が存在しない場合は、次の操作を実行して、クラスターへの ARMS アクセス権限を手動で付与します。

      1. 次の内容でカスタムポリシーを作成できます。詳細については、「ステップ 1: カスタムポリシーを作成する」をご参照ください。

            {
              "Action": "arms:*",
              "Resource": "*",
              "Effect": "Allow"
            }
      2. 前のステップで作成したカスタムポリシーをクラスターの WorkerRole にアタッチできます。詳細については、「ステップ 2: クラスターのワーカー RAM ロールに権限を付与する」をご参照ください。

ステップ 3: Java アプリケーションの ARMS アプリケーション監視を有効にする

クラスターに Java アプリケーションをデプロイするときに、アプリケーションにラベルを追加することで ARMS アプリケーション監視を有効にできます。

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

  2. クラスター ページで、管理したいクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、ワークロード > 展開 を選択します。

  3. [デプロイメント] ページの右上隅にある [YAML から作成] をクリックします。

  4. [サンプルテンプレート] を選択します。[テンプレート] (YAML 形式) で、spec.template.metadata パスに次の labels を追加します。

    labels:
      armsPilotAutoEnable: "on"
      armsPilotCreateAppName: "<your-deployment-name>" # <your-deployment-name> をアプリケーション名に置き換えます。
      one-agent.jdk.version: "OpenJDK11"    # アプリケーションが JDK 11 を使用する場合にこのパラメーターを設定します。
      armsSecAutoEnable: "on"    # このパラメーターを設定してアプリケーションセキュリティを有効にします。
    説明
    • アプリケーションセキュリティの詳細については、「アプリケーションセキュリティとは」をご参照ください。

    • アプリケーションセキュリティを有効にすると、その使用量に対して課金されます。課金の詳細については、「課金」をご参照ください。

    YAML Example

    次の YAML テンプレートは、ステートレス (Deployment) アプリケーションを作成し、ARMS アプリケーション監視を有効にする方法を示しています。

    完全な 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:
        # the port that this service should serve on
        - name: arms-demo-svc
          port: 6666
          targetPort: 8888
      # label keys and values that must match to receive traffic for this service
      selector:
        app: arms-springboot-demo
    ---
    apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
    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:
        # the port that this service should serve on
        - name: arms-demo-component-svc
          port: 6666
          targetPort: 8888
      # label keys and values that must match to receive traffic for this service
      selector:
        app: arms-springboot-demo-subcomponent
    ---
    apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
    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:
        # the port that this service should serve on
        - name: arms-mysql-svc
          port: 3306
          targetPort: 3306
      # label keys and values that must match to receive traffic for this service
      selector:
        app: mysql
    ---
  5. アプリケーションのデプロイメントを検証します。

    [デプロイメント] ページでは、ターゲットアプリケーションの [アクション] 列に [ARMS コンソール] ボタンが表示されます。ARMS Console Button

    [ARMS コンソール] をクリックしてモニタリングデータを表示できます。左側のナビゲーションウィンドウで [インターフェイス呼び出し] をクリックすると、HTTP インターフェイスなどのアプリケーションインターフェイスのアクセス詳細を表示できます。提供されているデモアプリケーション arms-springboot-demo は、継続的なインターフェイス呼び出しを自動的に生成します。4

  6. arms-springboot-demo アプリケーション用のサービスを手動で作成し、ロードバランシングを有効にしてアプリケーションの API にアクセスします。

    1. クラスター ページで、目的のクラスターを見つけてその名前をクリックします。左側のペインで、[ネットワーク] > [サービス] を選択します。

    2. ページの右上隅にある [作成] をクリックします。アプリケーションのサービスを設定し、[作成] をクリックします。設定項目の詳細については、「サービスを作成する」をご参照ください。

    3. サービスが作成されるのを待ちます。[サービス] ページで、arms-demo-svc の [外部エンドポイント] (例: 47.94.XX.XX:8080) を記録します。

    4. 次のコマンドを実行して、外部エンドポイント経由でこのサービスの /demo/queryUser/10 インターフェイスにアクセスします。

      curl http://47.94.XX.XX:8080/demo/queryUser/10

      期待される出力:

      {"id":1,"name":"KeyOfSpectator","password":"12****"}

      期待される出力は、インターフェイスへのアクセスが成功したことを示します。

ステップ 4: alibaba-cloud-metrics-adapter コンポーネントと統合する

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

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

  3. [インスタンス] ページで、ターゲットインスタンスの名前 (arms_metrics_{RegionId}_XXX の形式) をクリックします。左側のナビゲーションウィンドウで、[設定] をクリックします。[設定] タブの下部で、Prometheus URL である [HTTP API アドレス (Grafana 読み取りアドレス)] を表示して記録します。

    5

  4. 前のステップで記録した [HTTP API アドレス (Grafana 読み取りアドレス)] (Prometheus URL) を使用して ack-alibaba-cloud-metrics-adapter を設定します。

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

    2. クラスター ページで、目的のクラスターを見つけてその名前をクリックします。左側のペインで、[アプリケーション] > [Helm] を選択します。

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

    4. [リリースを更新] パネルに、ステップ 2 で記録した Prometheus URL を挿入します。

      8

  5. ack-alibaba-cloud-metrics-adapter の adapter-config 設定を変更します。

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

    2. [基本情報] タブで、adapter-config をクリックします。

    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)
        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"}

      以下は完全な例です:

      コードの詳細を表示するにはクリックします

      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
      
  6. 次のコマンドを実行して、クラスター内のメトリックデータを表示します。

    1. 次のコマンドを実行して、arms_app_requests_per_second メトリックが存在するかどうかを確認します。

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

      期待される出力:

      {"kind":"APIResourceList","apiVersion":"v1","groupVersion":"external.metrics.k8s.io/v1beta1","resources":[{"name":"slb_l4_packet_rx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_cpu_util","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_custom_week","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_custom_month","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"billing_pretax_gross_amount_total","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_usage","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_network_rx_rate","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_network_rx_errors","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_latency_p95","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_cpu_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_week","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"metrics_kube_pod_labels","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_latency_p9999","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_status_3xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"ahas_sentinel_block_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_month","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_custom_hour","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_pod_cpu_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_traffic_rx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_traffic_tx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_packet_tx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_connection_utilization","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_rt","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_cpu_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_cpu_utilization","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_memory_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total_hour","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"memory_usage_average","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_pod_memory_request","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_cpu_limit","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"ahas_sentinel_pass_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_day","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_min","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_ratio","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_custom","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_status_2xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_upstream_5xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_upstream_rt","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_hour","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total_month","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"metrics_kube_pod_info","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"metrics_kube_node_info","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"memory_request_average","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_latency_avg","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_status_5xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_limit","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_working_set","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_memory_utilization","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_active_connection","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l4_max_connection","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"billing_pretax_amount_node","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_status_4xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_upstream_4xx","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_cache","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_custom_day","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"ahas_sentinel_total_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_alb_ingress_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_memory_rss","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_network_tx_rate","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_cpu_usage","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total_min","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total_week","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"billing_pretax_amount_total","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_latency_p99","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_percorepricing","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_total_day","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cpu_core_request_average","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"slb_l7_qps","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"ahas_sentinel_avg_rt","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_memory_limit","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cpu_core_usage_average","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_latency_p50","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"sls_ingress_inflow","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"k8s_workload_network_tx_errors","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_cpu_limit","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_memory_usage","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"cost_node","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]},{"name":"arms_app_requests_per_second","singularName":"","namespaced":true,"kind":"ExternalMetricValueList","verbs":["get"]}]}

      期待される出力は、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: APM メトリックに基づいて HPA スケーリングを設定する

  1. 次の内容で hpa.yaml という名前のファイルを作成します。

    説明
    • hpa.yaml で設定されたメトリック名は、前のステップで ack-alibaba-cloud-metrics-adapter で定義されたメトリック名と一致する必要があります。

    • hpa.yamltarget はスケーリングのしきい値です。QPS > 40 の場合にアプリケーションはスケールアウトします。

    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
    # External メトリックタイプでは、Value および AverageValue タイプのターゲット値のみがサポートされます。
            target:
              type: AverageValue
              averageValue: 40
  2. 次のコマンドを実行して、arms-springboot-demo アプリケーションに HPA をデプロイします。

    kubectl apply -f hpa.yaml
  3. 次のコマンドを実行して HPA の詳細を表示します。

    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: ストレステストを通じて弾性スケーリング効果を検証する

  1. 次のコマンドを実行して、デモアプリケーションでストレステストを実行します。

    arms-demo-svc サービスの外部エンドポイントで 47.94.XX.XX:8080 を置き換えます。

    ab -c 50 -n 2000 http://47.94.XX.XX:8080/demo/queryUser/10
  2. 次のコマンドを実行して 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

    期待される出力は Targets にデータが存在することを示しており、これは HPA が正常に設定されたことを意味します。

  3. 弾性スケーリング効果を確認します。

    • ARMS コンソールでは、ストレステストによりこのインターフェイスのリクエスト量が急増していることがわかります。image

    • Prometheus ダッシュボードでは、インターフェイスの QPS が設定されたしきい値を超えると HPA がアプリケーションをスケーリングすることがわかります。image

    • ACK クラスターでは、このサンプルアプリケーションの Pod レプリカ数がインターフェイス呼び出しの QPS に基づいてスケールインまたはスケールアウトすることがわかります。

      kubectl describe hpa test-hpa -n arms-demo を実行して、発生したスケーリングイベントを表示できます。

高度な例

次のセクションでは、さまざまなシナリオにおける metrics-adapter の設定例を示します。

複数のサービスに対するメトリック変換

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 に対するメトリック変換

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 メトリックの詳細については、「アプリケーション監視メトリックの説明」をご参照ください。