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

Container Service for Kubernetes:ASMメトリックを使用したワークロードの自動スケーリングの実装

最終更新日:Jan 07, 2025

Service Mesh (ASM) は、Container Service for Kubernetes (ACK) クラスターおよびContainer Compute Service (ACS) クラスターのテレメトリデータを非侵入的な方法で収集します。 このテレメトリ機能により、サービスの動作が観察可能になり、O&Mスタッフがメンテナンスコストを増加させることなく、アプリケーションのトラブルシューティング、保守、最適化に役立ちます。 遅延、トラフィック、エラー、および飽和を含む4つの主要なメトリックに基づいて、ASMは、管理するサービスの一連のメトリックを生成します。 このトピックでは、ASMメトリックを使用してワークロードの自動スケーリングを実装する方法について説明します。

前提条件

背景

ASMは、管理するサービスの一連のメトリックを生成します。 詳細については、「Istio Standard Metrics」をご参照ください。

自動スケーリングは、リソース使用量に基づいてワークロードを自動的にスケールアップまたはスケールダウンするために使用されるアプローチです。 Kubernetesでは、2つのオートスケーラーを使用してオートスケーリングを実装します。

  • クラスターオートスケーラー (CA): CAは、クラスター内のノード数を増減するために使用されます。

  • 水平ポッドオートスケーラー (HPA): HPAは、アプリケーションのデプロイに使用されるポッドの数を増減するために使用されます。

Kubernetesの集約レイヤーを使用すると、サードパーティのアプリケーションは、APIアドオンとして登録することでKubernetes APIを拡張できます。 これらのアドオンを使用して、カスタムメトリクスAPIを実装し、HPAが任意のメトリクスを照会できるようにすることができます。 HPAは、リソースメトリクスAPIを使用して、CPU使用率やメモリ使用量などのコアメトリクスを定期的にクエリします。 さらに、HPAはカスタムメトリクスAPIを使用して、ASMによって提供される可観測性メトリクスなどのアプリケーション固有のメトリクスを照会します。

image

手順1: ASMインスタンスのPrometheusモニタリングを有効にする

詳細については、「PrometheusのManaged Serviceへのメトリックの収集」をご参照ください。

手順2: カスタムメトリクスAPIのアダプターのデプロイ

  1. 次のコマンドを実行して、アダプタのインストールパッケージをダウンロードします。 次に、カスタムメトリクスAPIのアダプターをクラスターにインストールしてデプロイします。

    詳細については、kube-metrics-adapterをご参照ください。

    ## Use Helm 3. 
    helm -n kube-system install asm-custom-metrics ./kube-metrics-adapter  --set prometheus.url=http://prometheus.istio-system.svc:9090
  2. インストールが完了したら、次のコマンドを実行してkube-metrics-adapterが有効かどうかを確認します。

    • 次のコマンドを実行して、autoscaling/v2betaが存在することを確認します。

      kubectl api-versions |grep "autoscaling/v2beta"

      期待される出力:

      autoscaling/v2beta
    • 次のコマンドを実行して、kube-metrics-adapterのポッドのステータスを確認します。

      kubectl get po -n kube-system |grep metrics-adapter

      期待される出力:

      asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2****          1/1     Running   0          19s
    • 次のコマンドを実行して、kube-metrics-adapterによって提供されるカスタムメトリクスを照会します。

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

      期待される出力:

      {
        "kind": "APIResourceList",
        "apiVersion": "v1",
        "groupVersion": "external.metrics.k8s.io/v1beta1",
        "resources": []
      }

手順3: サンプルアプリケーションのデプロイ

  1. testという名前の名前空間を作成します。 詳細については、「名前空間とリソースクォータの管理」をご参照ください。

  2. 自動サイドカープロキシ注入を有効にします。 詳細については、「自動サイドカープロキシ注入の有効化」をご参照ください。

  3. サンプルアプリケーションを展開します。

    1. podinfo.yamlという名前のファイルを作成し、次のコンテンツをファイルにコピーします。

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: podinfo
        namespace: test
        labels:
          app: podinfo
      spec:
        minReadySeconds: 5
        strategy:
          rollingUpdate:
            maxUnavailable: 0
          type: RollingUpdate
        selector:
          matchLabels:
            app: podinfo
        template:
          metadata:
            annotations:
              prometheus.io/scrape: "true"
            labels:
              app: podinfo
          spec:
            containers:
            - name: podinfod
              image: stefanprodan/podinfo:latest
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 9898
                name: http
                protocol: TCP
              command:
              - ./podinfo
              - --port=9898
              - --level=info
              livenessProbe:
                exec:
                  command:
                  - podcli
                  - check
                  - http
                  - localhost:9898/healthz
                initialDelaySeconds: 5
                timeoutSeconds: 5
              readinessProbe:
                exec:
                  command:
                  - podcli
                  - check
                  - http
                  - localhost:9898/readyz
                initialDelaySeconds: 5
                timeoutSeconds: 5
              resources:
                limits:
                  cpu: 2000m
                  memory: 512Mi
                requests:
                  cpu: 100m
                  memory: 64Mi
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: podinfo
        namespace: test
        labels:
          app: podinfo
      spec:
        type: ClusterIP
        ports:
          - name: http
            port: 9898
            targetPort: 9898
            protocol: TCP
        selector:
          app: podinfo
    2. 次のコマンドを実行して、podinfoアプリケーションをデプロイします。

      kubectl apply -n test -f podinfo.yaml
  4. 自動スケーリングをトリガーするには、リクエストをトリガーするためにテスト名前空間にロードテストサービスをデプロイする必要があります。

    1. loadtester.yamlという名前のファイルを作成し、次の内容をファイルにコピーします。

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: loadtester
        namespace: test
        labels:
          app: loadtester
      spec:
        selector:
          matchLabels:
            app: loadtester
        template:
          metadata:
            labels:
              app: loadtester
            annotations:
              prometheus.io/scrape: "true"
          spec:
            containers:
              - name: loadtester
                image: weaveworks/flagger-loadtester:0.18.0
                imagePullPolicy: IfNotPresent
                ports:
                  - name: http
                    containerPort: 8080
                command:
                  - ./loadtester
                  - -port=8080
                  - -log-level=info
                  - -timeout=1h
                livenessProbe:
                  exec:
                    command:
                      - wget
                      - --quiet
                      - --tries=1
                      - --timeout=4
                      - --spider
                      - http://localhost:8080/healthz
                  timeoutSeconds: 5
                readinessProbe:
                  exec:
                    command:
                      - wget
                      - --quiet
                      - --tries=1
                      - --timeout=4
                      - --spider
                      - http://localhost:8080/healthz
                  timeoutSeconds: 5
                resources:
                  limits:
                    memory: "512Mi"
                    cpu: "1000m"
                  requests:
                    memory: "32Mi"
                    cpu: "10m"
                securityContext:
                  readOnlyRootFilesystem: true
                  runAsUser: 10001
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: loadtester
        namespace: test
        labels:
          app: loadtester
      spec:
        type: ClusterIP
        selector:
          app: loadtester
        ports:
          - name: http
            port: 80
            protocol: TCP
            targetPort: http
    2. 次のコマンドを実行して、ロードテストサービスをデプロイします。

      kubectl apply -n test -f loadtester.yaml
  5. サンプルアプリケーションとロードテストサービスがデプロイされているかどうかを確認します。

    1. 次のコマンドを実行して、ポッドのステータスを確認します。

      kubectl get pod -n test

      期待される出力:

      NAME                          READY   STATUS    RESTARTS   AGE
      loadtester-64df4846b9-nxhvv   2/2     Running   0          2m8s
      podinfo-6d845cc8fc-26xbq      2/2     Running   0          11m
    2. 次のコマンドを実行してロードテストのためにコンテナにログインし、heyコマンドを実行してロードを生成します。

      export loadtester=$(kubectl -n test get pod -l "app=loadtester" -o jsonpath='{.items[0].metadata.name}')
      kubectl -n test exec -it ${loadtester} -c loadtester -- hey -z 5s -c 10 -q 2 http://podinfo.test:9898

      サンプルアプリケーションとロードテストサービスがデプロイされていることを示すロードが生成されます。

ステップ4: ASMメトリックを使用してHPAを設定する

podinfoアプリケーションが1秒間に受信するリクエストの数に基づいて、podinfoアプリケーションのワークロードをスケーリングするHPAを定義します。 平均して1秒あたり10を超えるリクエストが受信されると、HPAはレプリカの数を増やします。

  1. hpa.yamlという名前のファイルを作成し、次のコードをファイルにコピーします。

    apiVersion: autoscaling/v2beta2
    kind: HorizontalPodAutoscaler
    metadata:
      name: podinfo
      namespace: test
      annotations:
        metric-config.external.prometheus-query.prometheus/processed-requests-per-second: |
          sum(
              rate(
                  istio_requests_total{
                    destination_workload="podinfo",
                    destination_workload_namespace="test",
                    reporter="destination"
                  }[1m]
              )
          ) 
    spec:
      maxReplicas: 10
      minReplicas: 1
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: podinfo
      metrics:
        - type: External
          external:
            metric:
              name: prometheus-query
              selector:
                matchLabels:
                  query-name: processed-requests-per-second
            target:
              type: AverageValue
              averageValue: "10"
  2. 次のコマンドを実行してHPAをデプロイします。

    kubectl apply -f hpa.yaml
  3. 次のコマンドを実行して、HPAがデプロイされているかどうかを確認します。

    次のコマンドを実行して、kube-metrics-adapterによって提供されるカスタムメトリクスを照会します。

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

    期待される出力:

    {
      "kind": "APIResourceList",
      "apiVersion": "v1",
      "groupVersion": "external.metrics.k8s.io/v1beta1",
      "resources": [
        {
          "name": "prometheus-query",
          "singularName": "",
          "namespaced": true,
          "kind": "ExternalMetricValueList",
          "verbs": [
            "get"
          ]
        }
      ]
    }

    出力には、HPAがデプロイされていることを示すカスタムASMメトリックのリストが含まれています。

自動スケーリングの確認

  1. 次のコマンドを実行してロードテストのためにコンテナにログインし、heyコマンドを実行してロードを生成します。

    kubectl -n test exec -it ${loadtester} -c loadtester -- sh
    ~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
  2. 次のコマンドを実行して、自動スケーリングの効果を確認します。

    説明

    メトリックは、デフォルトで30秒ごとに同期されます。 コンテナは3〜5分ごとに1回のみスケーリングできます。 このように、HPAは、競合戦略が実行される前に自動スケーリングのための時間を予約することができる。

    watch kubectl -n test get hpa/podinfo

    期待される出力:

    NAME      REFERENCE            TARGETS          MINPODS   MAXPODS   REPLICAS   AGE
    podinfo   Deployment/podinfo   8308m/10 (avg)   1         10        6          124m

    HPAは、1秒あたりのリクエスト数が指定されたしきい値を下回るまで、1分でワークロードのスケールアップを開始します。 ロードテストが完了すると、1秒あたりのリクエスト数はゼロになります。 その後、HPAはポッドの数を減らし始める。 数分後、レプリカの数は前の出力の値から1に減少します。