学習プログラム: スケーラブルなアプリケーション - スケーリング

このチュートリアルは、Google Kubernetes Engine(GKE)で実行される最新のアプリケーション環境をデプロイ、実行、管理することを目的とする IT 管理者とオペレーターを対象としています。このチュートリアルでは、Cymbal Bank サンプル マイクロサービス アプリケーションを使用して、モニタリングとアラートの構成、ワークロードのスケーリング、障害のシミュレーションの方法を学習します。

  1. クラスタを作成してサンプル アプリケーションをデプロイする
  2. Google Cloud Managed Service for Prometheus でモニタリングする
  3. ワークロードをスケーリングする(このチュートリアル)
  4. 障害をシミュレートする
  5. チェンジ マネジメントを一元化する

概要と目的

Cymbal Bank のような一般ユーザー向けアプリでは、時間帯によってユーザー数が変化することがよくあります。理想的には、ウェブサイトは、トラフィックの急増に対応でき、遅延や他の問題が生じたり、不要なクラウド リソースに対する課金が発生しないようなウェブサイトが必要になります。Google Cloud が提供するソリューションは自動スケーリングです。

このチュートリアルでは、組み込みの Kubernetes 指標と Cloud Monitoring と Cloud Trace のカスタム指標の両方を使用して、GKE クラスタのクラスタとワークロードをスケーリングする方法について説明します。次のタスクを完了する方法を学習します。

  • Cloud Monitoring for Trace でカスタム指標を有効にします。
    • カスタム指標を使用すると、Kubernetes クラスタの認識を超える追加のモニタリング データまたは外部入力(ネットワーク トラフィックや HTTP レスポンス コードなど)を使用してスケーリングできます。
  • HorizontalPodAutoscaler を構成します。これは、指定された指標に応じてワークロードの Pod 数を自動的に増減できる GKE 機能です。
  • アプリケーションの負荷をシミュレートし、クラスタ オートスケーラーと HorizontalPodAutoscaler のレスポンスを確認します。

カスタム指標の収集を設定する

基本的な組み込みの Kubernetes CPU とメモリの指標を使用するように HorizontalPodAutoscaler を構成できます。また、1 秒あたりの HTTP リクエスト数や SELECT ステートメントの数など、Cloud Monitoring のカスタム指標を使用することもできます。カスタム指標は、アプリケーションを変更せずに使用できます。また、アプリケーションの全体的なパフォーマンスとニーズに関する詳細な分析情報をクラスタに提供します。このチュートリアルでは、組み込み指標とカスタム指標の両方を使用する方法について説明します。

  1. HorizontalPodAutoscaler が Monitoring からカスタム指標を読み取るには、カスタム指標 - Stackdriver アダプタ アダプタをクラスタにインストールする必要があります。

    カスタム指標 Stackdriver アダプタをクラスタにデプロイします。

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter.yaml
    
  2. Stackdriver アダプタがクラスタからカスタム指標を取得できるようにするには、Workload Identity Federation for GKE を使用します。このアプローチでは、モニタリング指標の読み取り権限を持つ IAM サービス アカウントを使用します。

    IAM サービス アカウントに roles/monitoring.viewer ロールを付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:scalable-apps@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/monitoring.viewer
    
  3. Workload Identity Federation for GKE と、モニタリング指標を読み取る権限を持つ IAM サービス アカウントを使用するように Stackdriver アダプタを構成します。

    gcloud iam service-accounts add-iam-policy-binding scalable-apps@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[custom-metrics/custom-metrics-stackdriver-adapter]"
    
  4. Kubernetes には、クラスタ内へのアクセスに使用するサービス アカウント用の独自のシステムが含まれています。アプリケーションが Google Kubernetes Engine クラスタの外部のサービスやリソース(Monitoring など)に対して認証を行うには、Workload Identity Federation for GKE を使用します。このアプローチでは、GKE に IAM サービス アカウントを使用するように Kubernetes サービス アカウントを構成します。

    アダプタが使用する Kubernetes サービス アカウントにアノテーションを付けます。

    kubectl annotate serviceaccount custom-metrics-stackdriver-adapter \
        --namespace=custom-metrics \
        iam.gke.io/gcp-service-account=scalable-apps@PROJECT_ID.iam.gserviceaccount.com
    
  5. Stackdriver アダプタ Deployment を再起動して変更を適用します。

    kubectl rollout restart deployment custom-metrics-stackdriver-adapter \
        --namespace=custom-metrics
    

HorizontalPodAutoscaler を構成する

GKE Autopilot は、いくつかの方法でスケーリングできます。このチュートリアルでは、次の方法でクラスタをスケーリングする方法について説明します。

  • HorizontalPodAutoscaler: ワークロードの Pod の数をスケーリングします。
  • クラスタ オートスケーラー: クラスタで使用可能なノードリソースをスケーリングします。

これらの 2 つの方法を組み合わせて使用する場合、アプリケーションの Pod の数が変化すると、それらの Pod をサポートするノードリソースも変化します。

HorizontalPodAutoscaler を基に Pod をスケーリングする他の実装も利用できます。また、VerticalPodAutoscaler を使用して、Pod の数ではなく Pod の CPU リクエストとメモリ リクエストを調整することもできます。

このチュートリアルでは、組み込みの指標を使用して userservice Deployment の HorizontalPodAutoscaler を構成し、カスタム指標を使用して frontend Deployment の HorizontalPodAutoscaler を構成します。

独自のアプリケーションの場合は、アプリケーション デベロッパーとプラットフォーム エンジニアと協力してニーズを把握し、HorizontalPodAutoscaler ルールを構成します。

userservice Deployment をスケーリングする

Cymbal Bank サンプル アプリケーションのユーザー数が増加すると、userservice Service はより多くの CPU リソースを消費します。HorizontalPodAutoscaler オブジェクトを使用して、アプリケーションが読み込みにどのように応答するかを制御します。HorizontalPodAutoscaler の YAML マニフェストで、HorizontalPodAutoscaler のスケーリング対象の Deployment、モニタリングする指標、実行するレプリカの最小数と最大数を定義します。

  1. userservice Deployment の HorizontalPodAutoscaler サンプル マニフェストを確認します。

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    ---
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: userservice
    spec:
      behavior:
        scaleUp:
          stabilizationWindowSeconds: 0
          policies:
            - type: Percent
              value: 100
              periodSeconds: 5
          selectPolicy: Max
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: userservice
      minReplicas: 5
      maxReplicas: 50
      metrics:
        - type: Resource
          resource:
            name: cpu
            target:
              type: Utilization
              averageUtilization: 60
    

    このマニフェストの内容は次のとおりです。

    • 50 へのスケールアップ時のレプリカの最大数を設定します。
    • スケールダウン中の最小数を 5 に設定します。
    • 組み込みの Kubernetes 指標を使用してスケーリングに関する決定を行います。このサンプルでは、指標は CPU 使用率であり、目標使用率は 60% です。これにより、過剰な使用率と過小な使用率の両方が回避されます。
  2. マニフェストをクラスタに適用します。

    kubectl apply -f extras/postgres-hpa/hpa/userservice.yaml
    

frontend Deployment をスケーリングする

前のセクションでは、CPU 使用率の組み込み Kubernetes 指標に基づいて、userservice Deployment に HorizontalPodAutoscaler を構成しました。frontend Deployment の場合は、受信した HTTP リクエストの数に基づいてスケーリングすることをおすすめします。この方法では、Stackdriver アダプタを使用して、HTTP(S) ロードバランサ Ingress オブジェクトの Monitoring からカスタム指標を読み取ります。

  1. frontend Deployment の HorizontalPodAutoscaler マニフェストを確認します。

    # Copyright 2022 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    ---
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: frontend
    spec:
      behavior:
        scaleUp:
          stabilizationWindowSeconds: 0
          policies:
            - type: Percent
              value: 100
              periodSeconds: 5
          selectPolicy: Max
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: frontend
      minReplicas: 5
      maxReplicas: 25
      metrics:
        - type: External
          external:
            metric:
              name: loadbalancing.googleapis.com|https|request_count
              selector:
                matchLabels:
                  resource.labels.forwarding_rule_name: FORWARDING_RULE_NAME
            target:
              type: AverageValue
              averageValue: "5"
    

    このマニフェストでは、次のフィールドを使用します。

    • spec.scaleTargetRef: スケーリングする Kubernetes リソース。
    • spec.minReplicas: レプリカの最小数。このサンプルでは 5 です。
    • spec.maxReplicas: レプリカの最大数。このサンプルでは 25 です。
    • spec.metrics.*: 使用する指標。このサンプルでは、1 秒あたりの HTTP リクエストの数です。これは、デプロイしたアダプタによって指定される Monitoring のカスタム指標です。
    • spec.metrics.external.metric.selector.matchLabels: スケーリング時にフィルタリングする特定のリソースラベル。
  2. frontend Ingress ロードバランサから転送ルールの名前を確認します。

    export FW_RULE=$(kubectl get ingress frontend -o=jsonpath='{.metadata.annotations.ingress\.kubernetes\.io/forwarding-rule}')
    echo $FW_RULE
    

    出力は次のようになります。

    k8s2-fr-j76hrtv4-default-frontend-wvvf7381
    
  3. 転送ルールをマニフェストに追加します。

    sed -i "s/FORWARDING_RULE_NAME/$FW_RULE/g" "extras/postgres-hpa/hpa/frontend.yaml"
    

    このコマンドは FORWARDING_RULE_NAME を保存した転送ルールに置き換えます。

  4. マニフェストをクラスタに適用します。

    kubectl apply -f extras/postgres-hpa/hpa/frontend.yaml
    

読み込みをシミュレートする

このセクションでは、負荷生成ツールを使用してトラフィックの急増をシミュレートし、時間の経過に伴う負荷の増加に対応するためにレプリカ数とノード数がスケールアップすることを確認します。次に、トラフィックの生成を停止し、レスポンスでレプリカとノードの数がスケールダウンすることを確認します。

  1. 開始する前に、HorizontalPodAutoscaler のステータスを確認し、使用中のレプリカの数を確認します。

    HorizontalPodAutoscaler リソースの状態を取得します。

    kubectl get hpa
    

    出力は次のようになります。1 つの frontend レプリカと 5 つの userservice レプリカがあることがわかります。

    NAME                     REFERENCE                            TARGETS             MINPODS   MAXPODS   REPLICAS   AGE
    frontend                 Deployment/frontend                  <unknown>/5 (avg)   5         25        1          34s
    userservice              Deployment/userservice               0%/60%              5         50        5          4m56s
    
  2. Cymbal Bank サンプル アプリケーションには loadgenerator サービスが含まれています。このサービスは、ユーザーを模倣したリクエストをフロントエンドに継続的に送信し、定期的に新しいアカウントを作成して、それらのアカウント間のトランザクションをシミュレートします。

    loadgenerator ウェブ インターフェースをローカルで公開します。このインターフェースを使用して、Cymbal Bank サンプル アプリケーションの負荷をシミュレートします。

    kubectl port-forward svc/loadgenerator 8080
    

    エラー メッセージが表示された場合は、Pod の実行中にもう一度お試しください。

  3. お使いのコンピュータのブラウザで、負荷生成ツールのウェブ インターフェースを開きます。

    • ローカルシェルを使用している場合は、ブラウザを開いて http://127.0.0.1:8080 に移動します。
    • Cloud Shell を使用している場合は、[ ウェブでプレビュー] をクリックし、[ポート 8080 でプレビュー] をクリックします。
  4. 負荷生成ツールのウェブ インターフェースで、[失敗] の値が 100% と表示されている場合は、次の手順を行ってテスト設定を更新します。

    1. 失敗率カウンタの横にある [停止] ボタンをクリックします。
    2. [ステータス] で、[新しいテスト] のオプションをクリックします。
    3. [ホスト] の値を Cymbal Bank の Ingress の IP アドレスに更新します。
    4. [Start swarming] をクリックします。
  5. 負荷生成ツールのウェブ インターフェースで [グラフ] タブをクリックして、パフォーマンスの推移を確認します。リクエスト数とリソース使用率を確認します。

  6. 新しいターミナル ウィンドウを開き、frontend Pod と userservice Pod のレプリカ数を確認します。

    kubectl get hpa -w
    

    レプリカの数は、負荷が増加すると増加します。クラスタが構成された指標が定義されたしきい値に達したことを認識し、HorizontalPodAutoscaler を使用して Pod の数をスケールアップするため、スケールアップ アクションには約 10 分かかります。

    次の出力例は、負荷生成ツールの実行に伴いレプリカの数が増加したことを示しています。

    NAME                     REFERENCE                            TARGETS          MINPODS   MAXPODS   REPLICAS
    frontend                 Deployment/frontend                  5200m/5 (avg)    5         25        13
    userservice              Deployment/userservice               71%/60%          5         50        17
    
  7. 別のターミナル ウィンドウを開き、クラスタ内のノード数を確認します。

    gcloud container clusters list \
        --filter='name=scalable-apps' \
        --format='table(name, currentMasterVersion, currentNodeVersion, currentNodeCount)' \
        --location="CONTROL_PLANE_LOCATION"
    

    CONTROL_PLANE_LOCATION は、クラスタのコントロール プレーンの Compute Engine のロケーションに置き換えます。リージョン クラスタの場合はリージョン、ゾーンクラスタの場合はゾーンを指定します。

    ノードの数も、新しいレプリカに対応するために、最初の数から増えました。このノード数の増加は、GKE Autopilot によって実現されます。このノードスケールでは構成するために何も行う必要はありません。

  8. 負荷生成ツールのインターフェースを開き、[停止] をクリックしてテストを終了します。

  9. レプリカ数とノード数を再度チェックし、負荷が軽減されて数が減少するのを確認します。Kubernetes HorizontalPodAutoscaler リソースのレプリカの安定化に要する時間はデフォルトで 5 分であるため、スケールダウンには時間がかかることがあります。

実際の環境では、このシミュレートされた負荷と同じように、環境内のノード数と Pod 数が自動的にスケールアップまたはスケールダウンされます。Cymbal Bank サンプル アプリケーションは、この種のスケーリングに対応するように設計されています。ワークロードがこれらのスケーリング機能の恩恵を受けられるかどうかは、アプリ オペレーターとサイト信頼性エンジニアリング(SRE)またはアプリケーションのデベロッパーに確認してください。