Google Kubernetes Engine を使用した負荷分散テスト

Last reviewed 2022-04-22 UTC

このチュートリアルでは、Google Kubernetes Engine(GKE)を使用して、複数のコンテナを使ってシンプルな REST ベースの API のトラフィックを作成する負荷分散テスト フレームワークをデプロイする方法について説明します。ここでは、App Engine にデプロイされた、受信 HTTP POST リクエストに応答する REST スタイルのエンドポイントを公開するウェブ アプリケーションの負荷テストを行います。

同じパターンを使用して、メッセージング システム、データ ストリーム管理システム、データベース システムなど、さまざまなシナリオやアプリケーション用の負荷テスト フレームワークを作成できます。

目標

  • Deployment 構成を設定するための環境変数を定義する。
  • GKE クラスタを作成する。
  • 負荷テストを実行する。
  • 必要に応じて、ユーザー数をスケールアップするか、パターンを他のユースケースにも適用する。

料金

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

  • App Engine
  • Artifact Registry
  • Cloud Build
  • Cloud Storage
  • Google Kubernetes Engine

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management API を有効にします。

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management API を有効にします。

    API を有効にする

  8. このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

  9. Google アカウントにロールを付与します。次の IAM ロールごとに次のコマンドを 1 回実行します。 roles/serviceusage.serviceUsageAdmin, roles/container.admin, roles/appengine.appAdmin, roles/appengine.appCreator, roles/artifactregistry.admin, roles/resourcemanager.projectIamAdmin, roles/compute.instanceAdmin.v1, roles/iam.serviceAccountUser, roles/cloudbuild.builds.builder, roles/iam.serviceAccountAdmin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
    • PROJECT_ID は、実際のプロジェクト ID に置き換えます。
    • EMAIL_ADDRESS は実際のメールアドレスに置き換えます。
    • ROLE は、個々のロールに置き換えます。

ワークロード例

次の図は、リクエストがクライアントからアプリケーションに送信されるワークロード例を示しています。

クライアントからアプリケーションへのリクエスト。

このインタラクションをモデル化するために、Python ベースの分散型負荷テストツールである Locust を使用します。このツールでは複数のターゲットパスにリクエストを分散できます。たとえば、Locust は /login/metrics のターゲットパスにリクエストを分散できます。ワークロードは、Locust の一連のタスクとしてモデル化されます。

アーキテクチャ

このアーキテクチャには、次の 2 つの主要コンポーネントが含まれます。

  • Locust Docker コンテナ イメージ。
  • コンテナ オーケストレーションと管理メカニズム。

Locust Docker コンテナ イメージには Locust ソフトウェアが含まれています。Dockerfile はこのチュートリアルに付属する GitHub リポジトリのクローンを作成すると入手できます。Dockerfile はベースの Python イメージを使用し、Locust サービスを開始してタスクを実行するスクリプトを含んでいます。実際のクライアントに近づけるために、各 Locust タスクが重み付けされます。たとえば、クライアントの合計リクエスト 1,000 個ごとに登録が 1 回発生します。

GKE はコンテナのオーケストレーションと管理を提供します。GKE を使用すると、負荷テスト フレームワークの基盤となるコンテナノードの数を指定できます。負荷テストのワーカーを Pod に整理し、GKE が実行され続ける Pod の数を指定することもできます。

負荷テストのタスクをデプロイする手順は、次のとおりです。

  1. 負荷テストのマスターをデプロイします。
  2. 負荷テストのワーカーのグループをデプロイします。この負荷テストのワーカーを使用して、テスト用の大量のトラフィックを作成できます。

次の図は、サンプル アプリケーションを使用して負荷テストを行うアーキテクチャを示しています。負荷テストの操作とモニタリングに使用されるウェブ インターフェースを提供するマスター Pod。ワーカー Pod は、テスト中のアプリケーションの REST リクエスト トラフィックを生成し、マスターに指標を送信します。

負荷テストの操作とモニタリングに使用されるウェブ インターフェースを提供するマスター Pod。テスト中のアプリケーションの REST リクエスト トラフィックを生成するワーカー Pod。

負荷テストのマスターについて

Locust マスターは、負荷テストのタスクを実行するためのエントリ ポイントです。Locust のマスター構成では、コンテナで使用される次のデフォルト ポートなど、いくつかの要素が指定されます。

  • 8089: ウェブ インターフェース用
  • 55575558: ワーカーとの通信用

この情報は、Locust ワーカーを構成するために後で使用されます。

Service をデプロイして、クラスタ内の他の Pod が hostname:port を介して公開されたポートにアクセスできるようにします。これらのポートは、わかりやすいポート名でも参照できます。

この Service を使用すると、マスターが失敗して Deployment によって新しい Pod に置き換えられる場合でも、Locust ワーカーはマスターを簡単に検出して確実に通信できるようになります。

同じ VPC ネットワークを使用し、クラスタと同じ Google Cloud リージョンにあるクラスタ外のクライアントが Locust ウェブ アプリケーション サービスにアクセスできるようにする内部パススルー ネットワーク ロードバランサを作成するために、必要なアノテーションを含む 2 番目の Service がデプロイされます。

Locust マスターをデプロイした後、内部パススルー ネットワーク ロードバランサによってプロビジョニングされたプライベート IP アドレスを使用してウェブ インターフェースを開くことができます。Locust ワーカーをデプロイした後、シミュレーションを開始して Locust ウェブ インターフェース経由で集計した統計情報を確認できます。

負荷テストのワーカーについて

Locust ワーカーは負荷テストのタスクを実行します。単一の Deployment を使って複数の Pod を作成します。Pod は、Kubernetes クラスタ全体に分散されます。各 Pod は、環境変数を使用して、テスト対象システムのホスト名や Locust マスターのホスト名などの構成情報を制御します。

次の図は、Locust マスターと Locust ワーカー間の関係を示しています。

Locust マスターは階層の最上位に位置し、その下に複数のワーカーがある。

共通変数を初期化する

インフラストラクチャの要素がデプロイされる場所を制御する変数をいくつか定義する必要があります。

  1. Cloud Shell を開きます。

    Cloud Shell を開く

    このチュートリアルでは、Cloud Shell からすべてのターミナル コマンドを実行します。

  2. カスタマイズが必要な環境変数を設定します。

    export GKE_CLUSTER=GKE_CLUSTER
    export AR_REPO=AR_REPO
    export REGION=REGION
    export ZONE=ZONE
    export SAMPLE_APP_LOCATION=SAMPLE_APP_LOCATION
    

    次のように置き換えます。

    • GKE_CLUSTER: GKE クラスタの名前。
    • AR_REPO: Artifact Registry リポジトリの名前
    • REGION: GKE クラスタと Artifact Registry リポジトリが作成されるリージョン
    • ZONE: Compute Engine インスタンスを作成するリージョン内のゾーン
    • SAMPLE_APP_LOCATION: サンプル App Engine アプリケーションがデプロイされる(リージョン)ロケーション

    コマンドは次の例のようになります。

    export GKE_CLUSTER=gke-lt-cluster
    export AR_REPO=dist-lt-repo
    export REGION=us-central1
    export ZONE=us-central1-b
    export SAMPLE_APP_LOCATION=us-central
    
  3. 次の追加の環境変数を設定します。

    export GKE_NODE_TYPE=e2-standard-4
    export GKE_SCOPE="https://www.googleapis.com/auth/cloud-platform"
    export PROJECT=$(gcloud config get-value project)
    export SAMPLE_APP_TARGET=${PROJECT}.appspot.com
    
  4. デフォルトのゾーンを設定することより、以降のコマンドでこれらの値を指定する必要がなくなります。

    gcloud config set compute/zone ${ZONE}
    

GKE クラスタを作成する

  1. クラスタに必要な最小限の権限を持つサービス アカウントを作成します。

    gcloud iam service-accounts create dist-lt-svc-acc
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/artifactregistry.reader
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/container.nodeServiceAccount
    
  2. GKE クラスタを作成します。

    gcloud container clusters create ${GKE_CLUSTER} \
    --service-account=dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com \
    --region ${REGION} \
    --machine-type ${GKE_NODE_TYPE} \
    --enable-autoscaling \
    --num-nodes 3 \
    --min-nodes 3 \
    --max-nodes 10 \
    --scopes "${GKE_SCOPE}"
    
  3. GKE クラスタに接続します。

    gcloud container clusters get-credentials ${GKE_CLUSTER} \
       --region ${REGION} \
       --project ${PROJECT}
    

環境を設定する

  1. GitHub からサンプル リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
    
  2. 作業ディレクトリをクローニングしたリポジトリに変更します。

    cd distributed-load-testing-using-kubernetes
    

コンテナ イメージをビルドする

  1. Artifact Registry リポジトリを作成します。

    gcloud artifacts repositories create ${AR_REPO} \
        --repository-format=docker  \
        --location=${REGION} \
        --description="Distributed load testing with GKE and Locust"
    
  2. コンテナ イメージをビルドし、Artifact Registry リポジトリに保存します。

    export LOCUST_IMAGE_NAME=locust-tasks
    export LOCUST_IMAGE_TAG=latest
    gcloud builds submit \
        --tag ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO}/${LOCUST_IMAGE_NAME}:${LOCUST_IMAGE_TAG} \
        docker-image
    

    付属の Locust Docker イメージには、サンプル アプリケーションの /login エンドポイントと /metrics エンドポイントを呼び出すテストタスクが埋め込まれています。このサンプル タスクセットでは、これら 2 つのエンドポイントに送信されたリクエストのそれぞれの割合は 1999 になります。

    
    class MetricsTaskSet(TaskSet):
        _deviceid = None
    
        def on_start(self):
            self._deviceid = str(uuid.uuid4())
    
        @task(1)
        def login(self):
            self.client.post(
                '/login', {"deviceid": self._deviceid})
    
        @task(999)
        def post_metrics(self):
            self.client.post(
                "/metrics", {"deviceid": self._deviceid, "timestamp": datetime.now()})
    
    class MetricsLocust(FastHttpUser):
        tasks = {MetricsTaskSet}
    

  3. Docker イメージが Artifact Registry リポジトリにあることを確認します。

    gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \
        grep ${LOCUST_IMAGE_NAME}
    

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

    Listing items under project PROJECT, location REGION, repository AR_REPO
    
    REGION-docker.pkg.dev/PROJECT/AR_REPO/locust-tasks  sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283  2022-04-13T01:55:02  2022-04-13T01:55:02
    

サンプル アプリケーションをデプロイする

  1. sample-webapp を作成して App Engine としてデプロイします。

    gcloud app create --region=${SAMPLE_APP_LOCATION}
    gcloud app deploy sample-webapp/app.yaml \
    --project=${PROJECT}
    
  2. プロンプトが表示されたら、「y」と入力してデプロイに進みます。

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

    File upload done.
    Updating service [default]...done.
    Setting traffic split for service [default]...done.
    Deployed service [default] to [https://PROJECT.appspot.com]
    

    サンプル App Engine アプリケーションは、/login エンドポイントと /metrics エンドポイントを実装します。

    @app.route('/login',  methods=['GET', 'POST'])
    def login():
        deviceid = request.values.get('deviceid')
        return '/login - device: {}\n'.format(deviceid)
    
    @app.route('/metrics',  methods=['GET', 'POST'])
    def metrics():
        deviceid = request.values.get('deviceid')
        timestamp = request.values.get('timestamp')
    
        return '/metrics - device: {}, timestamp: {}\n'.format(deviceid, timestamp)

Locust のマスター Pod とワーカー Pod のデプロイ

  1. locust-master-controller.yaml ファイルと locust-worker-controller.yaml ファイルにあるターゲット ホスト、プロジェクト、イメージのパラメータの環境変数値を置き換え、Locust のマスター Deployment とワーカー Deployment を作成します。

    envsubst < kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -
    
  2. Locust の Deployment を確認します。

    kubectl get pods -o wide
    

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

    NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE
    locust-master-87f8ffd56-pxmsk    1/1     Running   0          1m    10.32.2.6    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-279q9   1/1     Running   0          1m    10.32.1.5    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-9frbw   1/1     Running   0          1m    10.32.2.8    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-dppmz   1/1     Running   0          1m    10.32.2.7    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-g8tzf   1/1     Running   0          1m    10.32.0.11   gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-qcscq   1/1     Running   0          1m    10.32.1.4    gke-gke-load-test-default-pool-96a3f394
    
  3. Service を確認します。

    kubectl get services
    

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

    NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    kubernetes          ClusterIP      10.87.240.1     <none>        443/TCP             12m
    locust-master       ClusterIP      10.87.245.22    <none>        5557/TCP,5558/TCP    1m
    locust-master-web   LoadBalancer   10.87.246.225   <pending>     8089:31454/TCP       1m
    
  4. Locust マスター ウェブ アプリケーション Service に内部パススルー ネットワーク ロードバランサのプライベート IP アドレス(GKE 外部 IP アドレス)がプロビジョニングされている間に watch ループを実行します。

    kubectl get svc locust-master-web --watch
    
  5. 外部 IP アドレスがプロビジョニングされたら、Ctrl+C を押して watch ループを終了します。

Locust ウェブ フロントエンドに接続する

Locust マスターのウェブ インターフェースを使用して、テスト対象システムに対して負荷テストのタスクを実行します。

  1. ウェブホスト サービスの内部ロードバランサの IP アドレスを取得します。

    export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                   -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                   echo $INTERNAL_LB_IP
    
  2. ネットワーク構成に応じて、プロビジョニングされた IP アドレスを使用して Locust ウェブ アプリケーションに接続する方法が 2 つあります。

    • ネットワーク ルーティング。ワークステーションからプロジェクト VPC ネットワークへのルーティングを許可するようにネットワークが構成されている場合、ワークステーションから内部パススルー ネットワーク ロードバランサの IP アドレスに直接アクセスできます。

    • プロキシと SSH トンネル。ワークステーションと VPC ネットワークの間にネットワーク ルートがない場合、nginx プロキシ、およびワークステーションとインスタンス間の SSH トンネルを使用して Compute Engine インスタンスを作成することで、内部パススルー ネットワーク ロードバランサの IP アドレスにトラフィックをルーティングできます。

ネットワーク ルーティング

ワークステーションと Google Cloud プロジェクトの VPC ネットワークの間にネットワーク トラフィックのルートがある場合は、ブラウザを開き、Locust マスターのウェブ インターフェースを開きます。URL http://[INTERNAL_LB_IP]:8089 の [INTERNAL_LB_IP] は、前の手順で確認した IP アドレスに置き換えます。

プロキシと SSH トンネル

  1. 環境変数にインスタンスの名前を設定します。

    export PROXY_VM=locust-nginx-proxy
    
  2. 内部パススルー ネットワーク ロードバランサの Locust ウェブ アプリケーション ポート 8089 に対してプロキシ設定するように構成された ngnix Docker コンテナを含むインスタンスを起動します。

    gcloud compute instances create-with-container ${PROXY_VM} \
       --zone ${ZONE} \
       --container-image gcr.io/cloud-marketplace/google/nginx1:latest \
       --container-mount-host-path=host-path=/tmp/server.conf,mount-path=/etc/nginx/conf.d/default.conf \
       --metadata=startup-script="#! /bin/bash
         cat <<EOF  > /tmp/server.conf
         server {
             listen 8089;
             location / {
                 proxy_pass http://${INTERNAL_LB_IP}:8089;
             }
         }
    EOF"
    
  3. Cloud Shell からプロキシ インスタンスへの SSH トンネルを開きます。

    gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                     -- -N -L 8089:localhost:8089
    
  4. [ウェブでプレビュー] アイコン(Cloud Shell のウェブでプレビュー アイコン)をクリックし、表示されたオプションから [ポートを変更] を選択します。

  5. [プレビュー ポートの変更] ダイアログで、[ポート番号] フィールドに「8089」と入力し、[変更してプレビュー] を選択します。

    しばらくすると Locust ウェブ インターフェースがブラウザタブで開きます。

サンプル アプリケーションで基本的な負荷テストを実行する

  1. ブラウザで Locust フロントエンドを開くと、新しい負荷テストを開始するために使用できるダイアログが表示されます。

    Locust マスターのウェブ インターフェースには、新しく swarm を開始し、ユーザーの数と生成速度を指定するためのダイアログがある。

  2. [Number of users (peak concurrency)] に合計ユーザー数として 10 を指定し、[Spawn rate (users started/second)] に 1 秒あたりに生成するユーザー数として 5 を指定します。

  3. [Start swarming] をクリックしてシミュレーションを開始します。

    リクエストによりスワーミングが開始されると、次の画像に示すように [Statistics] でリクエスト数や 1 秒あたりのリクエスト数などのシミュレーション指標の集計が始まります。

    Locust ウェブ インターフェースに統計情報の集計が開始されたことが示される。
  4. デプロイされたサービスやその他の指標を Google Cloud コンソール から表示します。

    App Engine ダッシュボードに、1 時間あたりのリクエスト数が種類別にグラフで表示される。
  5. テスト対象のアプリケーションの動作を確認したら、[停止] をクリックしてテストを終了します。

ユーザー数をスケールアップする(省略可)

アプリケーションの負荷を増加してテストしたい場合は、シミュレーションするユーザー数を追加できます。シミュレーションするユーザー数を追加する前に、負荷の増加に対応できる十分なリソースがあることを確認してください。Google Cloud では、Pod の数を増やすための基盤となる VM リソースがあれば、既存の Pod を再デプロイすることなく、Locust ワーカー Pod を Deployment に追加できます。最初の GKE クラスタは 3 ノードから始まり、最大 10 ノードまで自動スケーリングできます。

  • Locust ワーカー Pod のプールを 20 にスケールします。

    kubectl scale deployment/locust-worker --replicas=20
    

    新しい Pod のデプロイと起動には数分かかります。

Pod Unschedulable エラーが表示された場合は、クラスタにさらにロールを追加する必要があります。詳しくは、GKE クラスタのサイズ変更を参照してください。

Pod が起動したら、Locust マスターのウェブ インターフェースに戻り、負荷テストを再開します。

パターンを拡張する

このパターンを拡張するために、新しい Locust タスクを作成することや、別の負荷テスト フレームワークに切り替えることができます。

収集する指標はカスタマイズできます。たとえば、1 秒あたりのリクエスト数の測定、負荷の増加に伴うレスポンスのレイテンシのモニタリング、レスポンスの失敗率とエラーのタイプの確認などが可能です。

詳細については、Cloud Monitoring のドキュメントをご覧ください。

クリーンアップ

チュートリアルが終了したら、作成したリソースについて料金が発生しないようにクリーンアップできます。

プロジェクトを削除する

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

GKE クラスタの削除

プロジェクト全体を削除したくない場合は、次のコマンドを実行して GKE クラスタを削除します。

   gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
   

次のステップ