このドキュメントでは、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
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
始める前に
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.
-
Grant roles to your user account. Run the following command once for each of the following IAM roles:
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_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
ワークロード例
次の図は、リクエストがクライアントからアプリケーションに送信されるワークロード例を示しています。
このインタラクションをモデル化するために、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 の数を指定することもできます。
負荷テストのタスクをデプロイするには、次の操作を行います。
- 負荷テストのプライマリ(Locust ではマスター)をデプロイします。
- 負荷テストのワーカーのグループをデプロイします。この負荷テストのワーカーを使用して、テスト用の大量のトラフィックを作成できます。
次の図は、サンプル アプリケーションを使用して負荷テストを行うアーキテクチャを示しています。負荷テストの操作とモニタリングに使用されるウェブ インターフェースを提供するマスター Pod。ワーカー Pod は、テスト中のアプリケーションの REST リクエスト トラフィックを生成し、マスターに指標を送信します。
負荷テストのマスターについて
Locust マスターは、負荷テストのタスクを実行するためのエントリ ポイントです。Locust のマスター構成では、コンテナで使用される次のデフォルト ポートなど、いくつかの要素が指定されます。
8089
: ウェブ インターフェース用5557
と5558
: ワーカーとの通信用
この情報は、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 ワーカー間の関係を示しています。
共通変数を初期化する
インフラストラクチャの要素がデプロイされる場所を制御する変数をいくつか定義する必要があります。
Cloud Shell を開きます。
このドキュメントでは、すべてのターミナル コマンドを Cloud Shell から実行します。
カスタマイズが必要な環境変数を設定します。
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
次の追加の環境変数を設定します。
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
デフォルトのゾーンを設定することより、以降のコマンドでこれらの値を指定する必要がなくなります。
gcloud config set compute/zone ${ZONE}
GKE クラスタを作成する
クラスタに必要な最小限の権限を持つサービス アカウントを作成します。
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
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}"
GKE クラスタに接続します。
gcloud container clusters get-credentials ${GKE_CLUSTER} \ --region ${REGION} \ --project ${PROJECT}
環境を設定する
GitHub からサンプル リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
作業ディレクトリをクローニングしたリポジトリに変更します。
cd distributed-load-testing-using-kubernetes
コンテナ イメージをビルドする
Artifact Registry リポジトリを作成します。
gcloud artifacts repositories create ${AR_REPO} \ --repository-format=docker \ --location=${REGION} \ --description="Distributed load testing with GKE and Locust"
コンテナ イメージをビルドし、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 つのエンドポイントに送信されたリクエストのそれぞれの割合は1
対999
になります。Docker イメージが Artifact Registry リポジトリにあることを確認します。
gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \ grep ${LOCUST_IMAGE_NAME}
出力は次のようになります。
Listing items under project
PROJECT
, locationREGION
, repositoryAR_REPO
REGION
-docker.pkg.dev/PROJECT
/AR_REPO
/locust-tasks sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283 2022-04-13T01:55:02 2022-04-13T01:55:02
サンプル アプリケーションをデプロイする
sample-webapp を作成して App Engine としてデプロイします。
gcloud app create --region=${SAMPLE_APP_LOCATION} gcloud app deploy sample-webapp/app.yaml \ --project=${PROJECT}
プロンプトが表示されたら、「
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
エンドポイントを実装します。
Locust のマスター Pod とワーカー Pod のデプロイ
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 -
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
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
Locust マスター ウェブ アプリケーション Service に内部パススルー ネットワーク ロードバランサの内部 IP アドレス(GKE 外部 IP アドレス)がプロビジョニングされている間に watch ループを実行します。
kubectl get svc locust-master-web --watch
外部 IP アドレスがプロビジョニングされたら、
Ctrl+C
を押して watch ループを終了します。
Locust ウェブ フロントエンドに接続する
Locust マスターのウェブ インターフェースを使用して、テスト対象システムに対して負荷テストのタスクを実行します。
ウェブホスト サービスの内部ロードバランサの IP アドレスをメモします。
export INTERNAL_LB_IP=$(kubectl get svc locust-master-web \ -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \ echo $INTERNAL_LB_IP
ネットワーク構成に応じて、プロビジョニングされた IP アドレスを使用して Locust ウェブ アプリケーションに接続する方法が 2 つあります。
ネットワーク ルーティング。ワークステーションからプロジェクト VPC ネットワークへのルーティングを許可するようにネットワークが構成されている場合、ワークステーションから内部パススルー ネットワーク ロードバランサの IP アドレスに直接アクセスできます。
プロキシと SSH トンネル。ワークステーションと VPC ネットワークの間にネットワーク ルートがない場合、
nginx
プロキシ、およびワークステーションとインスタンス間の SSH トンネルを使用して Compute Engine インスタンスを作成することで、内部パススルー ネットワーク ロードバランサの IP アドレスにトラフィックをルーティングできます。
ネットワーク ルーティング
ワークステーションと Google Cloud プロジェクトの VPC ネットワークの間にネットワーク トラフィックのルートがある場合は、ブラウザを開き、Locust マスターのウェブ インターフェースを開きます。Locust インターフェースを開くには、次の URL に移動します。
http://INTERNAL_LB_IP:8089
INTERNAL_LB_IP は、前の手順でメモした URL と IP アドレスに置き換えます。
プロキシと SSH トンネル
環境変数にインスタンスの名前を設定します。
export PROXY_VM=locust-nginx-proxy
内部パススルー ネットワーク ロードバランサの 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"
Cloud Shell からプロキシ インスタンスへの SSH トンネルを開きます。
gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \ -- -N -L 8089:localhost:8089
[ウェブでプレビュー] アイコン()をクリックし、表示されたオプションから [ポートを変更] を選択します。
[プレビュー ポートの変更] ダイアログで、[ポート番号] フィールドに「8089」と入力し、[変更してプレビュー] を選択します。
しばらくすると Locust ウェブ インターフェースがブラウザタブで開きます。
サンプル アプリケーションで基本的な負荷テストを実行する
ブラウザで Locust フロントエンドを開くと、新しい負荷テストを開始するために使用できるダイアログが表示されます。
[Number of users (peak concurrency)] に合計ユーザー数として
10
を指定し、[Spawn rate (users started/second)] に 1 秒あたりに生成するユーザー数として5
を指定します。[Start swarming] をクリックしてシミュレーションを開始します。
リクエストによりスワーミングが開始されると、次の画像に示すように [Statistics] でリクエスト数や 1 秒あたりのリクエスト数などのシミュレーション指標の集計が始まります。
デプロイされたサービスやその他の指標を Google Cloud コンソール から表示します。
テスト対象のアプリケーションの動作を確認したら、[停止] をクリックしてテストを終了します。
ユーザー数をスケールアップする(省略可)
アプリケーションの負荷を増加してテストしたい場合は、シミュレーションするユーザー数を追加できます。シミュレーションするユーザー数を追加する前に、負荷の増加に対応できる十分なリソースがあることを確認してください。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 のドキュメントをご覧ください。
クリーンアップ
このドキュメントで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
プロジェクトを削除する
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
GKE クラスタを削除する
プロジェクト全体を削除したくない場合は、次のコマンドを実行して GKE クラスタを削除します。
gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
次のステップ
- スケーラブルで復元性の高いウェブ アプリケーションを構築する。
- GKE のドキュメントで詳細を確認する。
- GKE のチュートリアルを試す。
- Cloud アーキテクチャ センターで、リファレンス アーキテクチャ、図、ベスト プラクティスを確認する。