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

負荷テストは、実際のニーズに直面したときにシステムがどの程度適切に機能するかを示すため、任意のバックエンド インフラストラクチャの開発の鍵となります。負荷テストで重要な要素となるのは、アプリケーションを実稼働用にデプロイする前に、ユーザーの行動とデバイスの動作を適切にシミュレートして懸念されるシステムのボトルネックを特定して把握することです。

しかし、専用のテスト インフラストラクチャは、継続的に必要とするものではないため、コストがかかり、メンテナンスが困難な場合があります。さらに、専用のテスト インフラストラクチャは、容量が固定された 1 回限りの設備投資となることが多いため、初期投資を超えた負荷テストの拡張が困難になり、テストが限られてしまうことがあります。その結果、開発チームの生産性が低下し、実稼働用にデプロイする前にアプリケーションが適切にテストされない可能性があります。

ソリューションの概要

クラウド コンピューティングを使用した負荷分散テストは、さまざまなテストシナリオにとって魅力的なオプションです。クラウド プラットフォームにより、高度な弾力性を備えたインフラストラクチャが提供されるため、シミュレートされた多数のクライアントでのアプリケーションとサービスのテストが容易になり、アプリケーションやサービスそれぞれに対してユーザーやデバイスの後にパターン化されたトラフィックが生成されます。さらに、クラウド コンピューティングの料金モデルは、負荷テストの非常に弾力性のある性質に合わせたモデルになっています。

アプリケーションの仮想マシン インスタンス全体を実行する代わりに軽量化を実現するコンテナは、シミュレートされたクライアントの迅速なスケーリングに最適です。コンテナは、軽量でデプロイしやすく、すぐに使えて特異なタスクに最適であるため、テスト用クライアントの実行に最適な抽象化を実現します。

Google Cloud Platform は、コンテナを使用した負荷分散テストに最適な環境です。このプラットフォームは、オープンソースのコンテナクラスタ マネージャ Kubernetes を利用している Google Kubernetes Engine 経由で主要機能としてコンテナをサポートします。Kubernetes Engine には、すばやくコンテナ インフラストラクチャとツールのプロビジョニングを行い、デプロイされたアプリケーションとリソースを管理する機能があります。

このソリューションでは、Kubernetes Engine を使用して負荷分散テスト フレームワークをデプロイする方法を示します。このフレームワークでは、複数のコンテナを使用して、REST ベースのシンプルな API の負荷テスト トラフィックを作成します。このソリューションでは、シンプルなウェブ アプリケーションをテストしますが、同じパターンを使用して、ゲーム アプリケーションやモノのインターネット(IoT)アプリケーションなどのより複雑な負荷テストシナリオを作成することができます。このソリューションでは、コンテナベースの負荷テスト フレームワークの一般的なアーキテクチャについて説明します。サンプル フレームワークの設定についてステップごとに説明されているチュートリアルについては、このドキュメントの最後にあるチュートリアル セクションをご覧ください。

このソリューションでは、負荷テスト トラフィックを作成するための Kubernetes Engine の使用に重点を置いて説明します。テスト対象システムは、REST API を使用するシンプルなウェブ アプリケーションです。このソリューションでは、既存のテスト フレームワークを活用して、以下のセクションで詳しく説明されている API インタラクションをモデル化します。テスト対象システムをデプロイした後、このソリューションでは、Kubernetes Engine を使用して、負荷分散テストのタスクをデプロイします。

テスト対象システム

ソフトウェア テストの用語では、テスト対象システムは、テストが評価されるよう設計されているシステムのことです。このソリューションでのテスト対象システムは、Google App Engine にデプロイされているシンプルなウェブ アプリケーションです。このアプリケーションは、REST スタイルの基本的なエンドポイントを公開して、受信 HTTP POST リクエストをキャプチャします(受信データは永続化されません)。実際のシナリオでは、ウェブ アプリケーションは複雑で、キャッシュ、メッセージング、永続化などの多くの追加コンポーネントやサービスが含まれています。こうした複雑なアプリケーションは、このソリューションでは取り扱いません。Google Cloud Platform でのスケーラビリティの高いウェブ アプリケーションの構築に関する詳細については、スケーラビリティと復元性の高いウェブ アプリケーションの構築のソリューションをご覧ください。

サンプル アプリケーションのソースコードは、このドキュメントの最後にあるチュートリアルの一部として提供されています。

サンプルのワークロード

サンプル アプリケーションは、モノのインターネット(IoT)の多くのデプロイ(まずデバイスがサービスに登録し、次に指標とセンサー測定値の報告を開始しながら定期的にサービスに再登録する)でバックエンド サービス コンポーネントが見つかった後にモデル化されます。

次の図は、一般的なバックエンド サービス コンポーネントのインタラクションを示しています。

バックエンド サービス コンポーネントのインタラクションを示す図。

このインタラクションをモデル化するには、Locust を使用します。これは、複数のターゲットパスにまたがってリクエストを分散できる Python ベースの負荷テストツールです。たとえば Locust は、リクエストを /login/metrics のターゲットパスに分散できます。他にも JMeterGatlingTsung など、多くの負荷生成ソフトウェア パッケージがあり、プロジェクトのニーズに合わせて適切なものを選択します。

ワークロードは、上記に説明したインタラクションに基づいており、Locust で一連のタスクとしてモデル化されます。実際のクライアントに近づけるために、各 Locust タスクが重み付けされます。たとえば、クライアントの合計リクエスト 1,000 個ごとに登録が 1 回発生します。

コンテナベースのコンピューティング

アーキテクチャの観点からすると、この負荷分散テスト ソリューションのデプロイに関係するのは、Locust コンテナ イメージとコンテナ オーケストレーションおよび管理メカニズムの 2 つのメイン コンポーネントです。

Locust コンテナ イメージとは、Locust ソフトウェアに含まれている Docker イメージです。Dockerfile は、関連付けられている Github レポジトリにあります(下記のチュートリアルをご覧ください)。Dockerfile では、ベースの Python イメージを使用します。Dockerfile には、Locust サービスを起動してタスクを実行するスクリプトが含まれています。

このソリューションでは、コンテナ オーケストレーションおよび管理メカニズムとして Google Kubernetes Engine を使用します。オープンソースのフレームワーク Kubernetes をベースにした Kubernetes Engine は、Google のあらゆるサービスで何年にもわたってコンテナのデプロイを実行、オーケストレーション、管理してきたサービスです。コンテナベースのコンピューティングにより、デベロッパーは、ホスティング環境へのデプロイや統合ではなく、各自のアプリケーションに集中することができます。また、コンテナにより、負荷テストの移植が容易になるため、複数のクラウド環境でコンテナ化アプリケーションを実行できるようになります。Kubernetes Engine と Kubernetes では、コンテナのオーケストレーションと管理に固有のいくつかの概念を導入しています。

コンテナ クラスタ

コンテナ クラスタとは、アプリケーション全体の基盤となる Compute Engine インスタンスのグループです。Kubernetes Engine と Kubernetes のドキュメントでは、これらのインスタンスはノードと呼ばれています。クラスタは、1 つのマスターノードと 1 つ以上のワーカーノードで構成されます。マスターとワーカーはすべて、Kubernetes で実行されるため、コンテナ クラスタは Kubernetes クラスタと呼ばれることもあります。クラスタの詳細については、Kubernetes Engine のドキュメントをご覧ください。

ポッド

ポッドとは、同時にデプロイされる密結合したコンテナのグループです。一部のポッドには、コンテナが 1 つしか含まれていません。たとえば、このソリューションでは、各 Locust コンテナがそれ自身のポッドで実行されます。しかし、多くの場合、ポッドにはなんらかの方法で連携する複数のコンテナが含まれています。たとえば、このソリューションでは、Kubernetes は 3 つのコンテナが含まれているポッドを使用して、DNS サービスを提供します。1 つのコンテナでは、SkyDNS によって DNS サーバー機能が提供されます。SkyDNS は、別のコンテナにある etcd という名前の key-value ストアに依存しています。ポッドの 3 番目のコンテナでは、kube2sky が Kubernetes と SkyDNS 間の橋渡しとして機能します。

レプリケーション コントローラ

レプリケーション コントローラによって、指定した数のポッド「レプリカ」がどの時点でも確実に実行されます。ポッドレプリカが多すぎる場合は、レプリケーション コントローラによって一部のポッドが削除されます。ポッドレプリカが少なすぎる場合は、レプリケーション コントローラによってさらにポッドが起動されます。このソリューションには、3 つのレプリケーション コントローラがあります。1 つ目のレプリケーション コントローラは 1 つの DNS サーバーポッドの存在を確認し、2 つ目のレプリケーション コントローラは 1 つの Locust マスターポッドを保持し、3 つ目のレプリケーション コントローラは実行されているちょうど 10 個の Locust ワーカーポッドを保持しています。

サービス

更新やメンテナンスのノードの障害や意図的なノードの中断などのさまざまな理由で、特定のポッドが表示されないことがあります。これは、ポッドの IP アドレスによってそのポッドに信頼できるインターフェースが提供されないことを意味します。より信頼性の高いアプローチでは、基になるポッドが表示されず、IP アドレスが異なる新しいポッドに置き換えられる場合でも、そのインターフェースの変更されない抽象表現を使用します。Kubernetes Engine サービスでは、ポッドの論理セットとポッドへのアクセスに使われるポリシーを定義することで、このタイプの抽象インターフェースを提供します。このソリューションでは、ポッドやポッドのセットを表すいくつかのサービスがあります。たとえば、DNS サーバーポッドのサービス、Locust マスターポッドのサービス、10 個すべての Locust ワーカーポッドを表すサービスがあります。

次の図は、マスターノードとワーカーノードの内容を示してします。

マスターノードとワーカーノードの内容を示す図。

テスト対象システムのデプロイ

このソリューションでは、Google App Engine を使用してテスト対象システムを実行します。テスト対象システムをデプロイするには、Google Cloud Platform SDK をインストールして実行できるように有効な Google Cloud Platform アカウントが必要です。SDK をインストールして実行すると、1 つのコマンドでサンブルのウェブ アプリケーションをデプロイできます。このウェブ アプリケーションのソースコードは、このドキュメントの最後にあるチュートリアルの一部として提供されています。

負荷テストのタスクのデプロイ

負荷テストのタスクをデプロイするには、最初に負荷テストのマスターをデプロイし、10 個の負荷テストワーカーからなるグループをデプロイします。この多数の負荷テストワーカーを使用し、かなりの量のテスト用トラフィックを作成できます。ただし、外部システムへのトラフィックを多く生成しすぎると、DoS 攻撃と見なされる可能性があるので注意してください。Google Cloud Platform 利用規約Google Cloud Platform 利用規定ポリシーをご確認ください。

負荷テストのマスター

デプロイの最初のコンポーネントは、Locust のマスターです。このマスターは、前述の負荷テストのタスクを実行するためのエントリ ポイントです。必要となるマスターは 1 つだけであるため、Locust のマスターは、レプリカが 1 つのレプリケーション コントローラとしてデプロイされます。レプリケーション コントローラは、高可用性を確保する理由で 1 つのポッドをデプロイする場合にも役立ちます。

レプリケーション コントローラの構成により、コントローラの名前(locust-master)、組織のラベル(name: locust, role: master)、コンテナによって公開される必要があるポート(ウェブ インターフェースの場合は 8089、ワーカーとの通信の場合は 55575558)などのいくつかの要素が指定されます。この情報は、Locust ワーカー コントローラを構成するために後で使用されます。次のスニペットには、ポートの構成が含まれています。

...
ports:
  - name: locust-master-web
    containerPort: 8089
    protocol: TCP
  - name: locust-master-port-1
    containerPort: 5557
    protocol: TCP
  - name: locust-master-port-2
    containerPort: 5558
    protocol: TCP

次に、サービスをデプロイして、公開されたポートがクラスタ内の hostname:port で他のポッドにアクセスでき、わかりやすいポート名で参照できるようにします。サービスを使用すると、マスターが失敗してレプリケーション コントローラで新しいポッドに置き換えられる場合でも、Locust のワーカーが簡単にマスターを検出し、確実にマスターと通信できるようになります。また、Locust マスター サービスには、クラスタレベルで外部転送ルールを作成するディレクティブも含まれています。これにより、外部トラフィックがクラスタ リソースにアクセスできる機能が提供されます。ターゲット インスタンスへの完全なアクセス権を提供するには、ファイアウォール ルールを作成する必要があります。

Locust マスターをデプロイした後、外部転送ルールのパブリック IP アドレスを使用してウェブ インターフェースにアクセスできます。Locust ワーカーをデプロイした後、シミュレーションを開始して Locust ウェブ インターフェース経由で集計した統計情報を確認できます。

負荷テストのワーカー

デプロイの次のコンポーネントには、前述の負荷テストのタスクを実行する Locust ワーカーが含まれています。Locust ワーカーは、10 個のポッドを作成する 1 つのレプリケーション コントローラによってデプロイされます。ポッドは、Kubernetes クラスタ全体に分散されます。各ポッドでは、環境変数を使用して、テスト対象システムのホスト名、Locust マスターのホスト名などの重要な設定情報を制御します。ワーカーのレプリケーション コントローラの設定は、下記のチュートリアルにあります。その設定には、そのコントローラの名前(locust-worker)、組織のラベル(name: locust, role: worker)、前述の環境変数が含まれています。次のスニペットには、名前、ラベル、レプリカ数の設定があります。

kind: ReplicationController
  apiVersion: v1
  metadata:
    name: locust-worker
    labels:
      name: locust
      role: worker
  spec:
    replicas: 10
    selector:
      name: locust
      role: worker
...

Locust ワーカーでは、ワーカーポッド自体で通信の受信をサポートする(つまり、Locust マスターポッドに直接接続する)必要がないため、追加サービスをデプロイする必要はありません。

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

Kubernetes のポッドと Locust のマスターノードおよびワーカーノードを示す図。

レプリケーション コントローラによる Locust ワーカーのデプロイの後、Locust マスターのウェブ インターフェースに戻ってデプロイされたワーカー数に対応するスレーブ数を確認できます。

負荷テストのタスクの実行

負荷テストの開始

Locust マスターのウェブ インターフェースでは、次の画像に示すようにテスト対象システムに対して負荷テストのタスクを実行できます。

Locust の最初のウェブ インターフェースのスクリーンショット。

開始するには、シミュレートするユーザーの合計数と各ユーザーを生成する速度を指定します。次に、[スワーミングの開始] をクリックしてシミュレーションを開始します。時間の経過とともにユーザーが生成されるにつれ、次の画像に示すように統計情報でリクエスト数、1 秒あたりのリクエスト数などのシミュレーション指標の集計が開始されるのがわかります。

スワーミングが進行しているときの Locust ウェブ インターフェースのスクリーンショット。

シミュレーションを停止するには、[停止] をクリックすると、テストが終了します。全体の結果は、スプレッドシートにダウンロードできます。

クライアントのスケーリング

シミュレート対象のユーザー数をスケールアップするには、Locust ワーカーポッド数を増やす必要があります。Locust ワーカー コントローラで指定されているように、レプリケーション コントローラによって 10 個の Locust ワーカーポッドがデプロイされています。レプリケーション コントローラによってデプロイされるポッド数を増やすために、ポッドを再デプロイすることなくコントローラのサイズを変更できる機能が Kubernetes に用意されています。たとえば、kubectl コマンドライン ツールを使用してワーカーポッド数を変更できます。次のコマンドにより、ワーカーポッドのプールが 20 にスケーリングされます。

$ kubectl scale --replicas=20 replicationcontrollers locust-worker

scale コマンドの発行後、すべてのポッドがデプロイされ、起動するまで数分かかります。すべてのポッドが起動したら、Locust マスターのウェブ インターフェースに戻って負荷テストを再開します。

リソースと費用

このソリューションでは、4 つの Kubernetes Engine ノードを使用します。これらのノードはそれぞれ、n1-standard-1 タイプの Compute Engine VM 標準インスタンスを基盤としています。Google Cloud Platform 料金計算ツールを使用して、このコンテナ クラスタ実行の 1 か月の費用を見積もることができます。前述のように、コンテナ クラスタのサイズのスケーリングをお客様のニーズに合わせてカスタマイズできます。料金計算ツールで、クラスタの特性をカスタマイズして、スケールアップやスケールダウンした場合の費用を見積もることができます。

次のステップ

Kubernetes Engine を使用して単純なウェブ アプリケーション向けの負荷テスト フレームワークを作成する方法を説明しました。Kubernetes Engine により、負荷テスト フレームワークの基盤となるコンテナノードの数を指定できます。また、Kubernetes Engine では負荷テストワーカーをポッドにまとめ、Kubernetes Engine で実行し続けるポッドの数を宣言することもできます。

これと同じパターンで、さまざまなシナリオやアプリケーションの負荷テスト フレームワークを作成できます。たとえば、これと同じパターンで、メッセージング システム、データ ストリーム管理システムや、データベース システムの負荷テスト フレームワークを作成できます。また、新しい Locust タスクを作成したり、別の負荷テスト フレームワークを作成したりすることも可能です。

このソリューションで示したフレームワークを拡張するもう 1 つの方法は、収集される指標をカスタマイズすることです。たとえば、1 秒あたりのリクエスト数の測定、負荷の増加に伴うレスポンスのレイテンシの監視や、レスポンスの失敗率とエラーのタイプの確認を行うことができます。また、Google Cloud Monitoring など、利用可能なモニタリング オプションもいくつかあります。

チュートリアル

手順、ソースコードなど、チュートリアルのすべての内容は、GitHub の https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes で入手できます。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...