14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Locustの分散負荷テスト環境をAWS Fargateを使って簡単に用意してやる

Posted at

概要

この記事では、負荷テストツールLocustで分散負荷テスト環境を構築するに当たって私が使っている方法をまとめます。
構築はAWS Fargateを使って、設定をできるだけ少なくしました。
AWSの操作にはTerraformを使って、構築・破棄を繰り返しできるようにしています。

背景

これまでやっていた負荷テスト

負荷テストはどのようにして実行しているでしょうか?
私はこれまで簡単なものはApacheBenchで行い、
ログインを含むシナリオが必要なものはシェルスクリプトでコードを書いて実行していました。

しかし、ApacheBenchは静的なWebサイトなどで使うには良いのですが、Webアプリのテストとなると機能が足りないと感じていました。
シェルスクリプトを使えば何でもできる反面、テストの作成に時間がかかりがちで、メンテナンスもしずらくなっていました。

Locustを使った負荷テスト

そんなときに、Locustというツールを知りました。
まだ使い始めて一ヶ月ほどですが、満足できそうな予感がしています。
(ツールの特徴については公式をはじめ多数情報があるので、割愛します)

今回紹介する方法の良い点

Locustは気に入ったので、これから何度も使うつもりなのですが、毎回Locustサーバーを立てるのは面倒です。
使わないサーバーを停止状態で放置するのもリソースが無駄になって良くないと思います。
そこでFargateとTerraformも使い、使いたいときに立ち上げてすぐに破棄できるようにコード化しました。

  • Locustを使うことで

    • テストスクリプトが見やすくなる(と思う)
    • イベントやタスクの重み付けで、リアルなユーザーを想定したシナリオでテストできる
    • 分散クラスターの構築に対応していて、テストのスケールアウトに対応できる
  • Fargateを使うことで

    • 多数のコンテナをサーバーの台数やスペックを気にせずに立ち上げられる
  • Terraformを使うことで

    • 使いたくなったときにコマンド一発で環境が立ち上がり、コマンド一発でネットワーク設定もろとも破棄できる

構築手順

実際に環境を構築する方法です。

攻撃スクリプトコンテナを用意する

攻撃スクリプトは事前に用意して、コンテナに入れてイメージリポジトリにpushしておきます。
コンテナ内には複数種類のスクリプトを入れておいて、Terraformの変数でどのスクリプトを実行するか切り替えられるようにしています。

実業務では、攻撃スクリプトコンテナはプライベートなECRリポジトリに置いていますが、今回はgithubとDockerHubでサンプルを作っています。

github: https://github.com/neilli-sable/locust_scripts
dokcerhub: https://hub.docker.com/repository/docker/neilli/locust_scripts

Terraformから環境を構築する

このリポジトリに置いたコードから、攻撃スクリプトコンテナを起動して構築します。
https://github.com/neilli-sable/locust_fargate

設定内容について

「ネットワーク設定する -> ECSのクラスタを作る -> クラスタの上でLocustコンテナを動かす」というような内容になっています。
細かい部分はコードをご確認いただきたいですが、いくつか設定のポイントになった箇所を書いておきます。

接続情報と変数

variable.tf.defaultにプロバイダーと変数設定のサンプルがあります。
variable.tfとリネームして、設定値を変更することで構築するLocustクラスタのスペック変更などができます。

接続情報として、providerに名前付きプロファイル名と、regionを指定しておきます。

provider "aws" {
  profile = "my-profile"
  region  = "ap-northeast-1"
}

変数は以下の種類を用意しました。

  • general_name
    • AWSのリソース名やタグ付けに使うための文字列を指定します
  • slave_count
    • LocustのSlaveサーバーの数を指定します
  • fargate_cpu
    • LocustコンテナのCPUスペックを指定します
  • fargate_memory
    • Locustコンテナのメモリ量を指定します
  • locust_container
    • Locustの攻撃スクリプトを入れたコンテナのURLを指定します
  • locust_script_path
    • 使用する攻撃スクリプトのファイルパスを指定します

開放するポート

Masterサーバーは3つのポートを開放します。

  • 8089
    • WebブラウザからUIにアクセスするためのポート
  • 5557/5558
    • Slaveサーバーからの通信を受けるためのポート

5557と5558はSlaveサーバー向けのセキュリティグループからのみアクセス可にしておきます。
8089は今回アクセス制限していませんが、必要に応じてIP制限などを設定すると良いと思います。

一方、Slaveサーバーはポート開放は必要ありません。
セキュリティグループからingressは削除し、egressだけ設定して、外部からの接続はできないようにしておきます。

MasterサーバーのプライベートDNS

SlaveはMasterに通信しないといけないですが、コンテナは起動するまでIPアドレスが割り当たっていないため、単純なIPアドレスの指定は使えません。
なのでECSのサービスディスカバリ機能を使って、プライベートDNSを設定します。

vpc.tfにある、この以下の部分です。

# Service Discovery
resource "aws_service_discovery_private_dns_namespace" "locust_internal" {
  name        = "locust.internal"
  description = var.general_name
  vpc         = aws_vpc.vpc.id
}

resource "aws_service_discovery_service" "master" {
  name = "master"

  dns_config {
    namespace_id = aws_service_discovery_private_dns_namespace.locust_internal.id

    dns_records {
      ttl  = 10
      type = "A"
    }

    routing_policy = "MULTIVALUE"
  }

  health_check_custom_config {
    failure_threshold = 1
  }
}

そうすることで、タスク定義でmaster.locust.internalというプライベートDNSアドレスを解決できます。

  container_definitions = <<DEFINITION
[
  {
    "cpu": ${var.fargate_cpu},
    "essential": true,
    "image": "${var.locust_container}",
    "memoryReservation": ${var.fargate_memory},
    "name": "locust",
    "command": ["locust", "-f", "${var.locust_script}", "--slave", "--master-host=master.locust.internal"]
  }
]
DEFINITION

Terraformの実行

terraform ディレクトリが実行用のディレクトリなので、移動します。

cd ./locust_fargate/terraform

接続情報と変数」の項目でも書きましたが、variable.tfを作成して、接続情報などを設定します。

初回のみ、initコマンドを使います。

terraform init

一度 init すれば、以後はapplyコマンドで環境構築できます。

terraform apply

負荷テストを実行する

UIへのアクセス

terraform apply の結果、成功すればURLを出力するようにしています。
こんな感じに。

Outputs:

endpoint = access to here (wait a minute): http://locust-fargate-application-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com

terraform applyが終わってしばらくしてからURLにアクセスすると、LocustのUIが表示されます。
変数で設定した数のSlave数になっていることが確認できるはずです。

しばらくしてからと書きましたが、terraform applyの完了からサーバーが実際に起動完了するまでにタイムラグがあります。起動する前にURLにアクセスすると503エラーとなるので数分程度待たないといけません。
いつまでも503が続く場合は、エラーなどが原因でタスク自体が停止している可能性があります。

Locustを使う

UIに接続できれば、普通にLocustを使うことができます。
「Number of users to simulate」「Hatch rate」「Host」を入力して、テストを開始してください。
Hostに「http://」から入力しないといけないのをいつも間違えるのは私だけでしょうか。

お片付け

テストを実行してデータの回収などを完了したら、AWS上に作成したリソースを破棄します。

terraform destroy

これでキレイサッパリなはずなので、気軽に破棄してお金が掛からない状態にしておきます。
またテストしたくなったら、terraform applyからやり直すだけです。

感想

これまでの負荷テストだと、始めるまでがちょっとした仕事量になってしまい、実行がおろそかになっていたように思います。
もっと気軽にテストをしていきたいものです。

参考文献など

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?