🎅

AWSソリューションを利用して負荷テストを行う

2020/12/23に公開

こんにちは。クリスマスイヴイヴですね!みなさんいかがお過ごしでしょうか。

マクアケという会社でSREしてます。Naganeです。
という事でこの記事はMakuake Advent Calendar 2020 23日目の記事になります。

突然ですが皆さん。負荷テストしてますか!

苦労した末に作り上げたサービスを世の中に出し、これからさぁやっていくぞ!となっている中
アクセス集中でサイトダウン。悲しいですよね。
そうならないためにも、公開前に実際にある程度アクセス集中状態を擬似的に作り出し
実際に提供したい体験が得られるか確認するというのはとても大切な事です。

実際に負荷テストをしようとすると大変な所

しっかりとした負荷テストを実施しようとした時に意外と大変なのが環境の準備です。

  • 負荷をかける先が接続制限されていたり
  • 作成した実行環境が思ったより負荷が出ずカーネルパラメータのチューニングを強いられたり
  • そもそも作成した環境に負荷テストツールのインストールが大変だったり

一つ一つの問題解決は難しくはありませんが、じわじわと負荷テスト実施前に時間が奪われていき
最終的には割と無視できない量の時間が奪われていってしまいます。
SaaSの利用を検討しても良いと思いますが、今回はAWSソリューションから提供されている
Serverlessな分散負荷テスト環境を利用してみようと思います。

AWSソリューション

AWSソリューションとは、AWSアーキテクトおよびAWSパートナーによって構築および検証された技術的なリファレンス実装で、以下のような特徴があります

  • 適切なAWSのサービスを利用し、運用面、コスト面で費用対効果が高い設計になっている
  • デプロイガイドが付属している

つまりAWSに詳しい人たちが構築・検証した一般的な問題のソリューションを、自分たちのAWSの環境に用意して、その恩恵に預かれるという事になります。利用しない手はありません。また分散負荷テスト以外にも色々なソリューションが公開されていますので、眺めてるだけでも結構楽しいです。

AWSソリューション実装

AWS分散負荷テスト環境

AWSでの分散負荷テスト

上のリンク先にあるAWSソリューションを実装すると以下のリソースがAWS環境に作成されます

詳細はリンク先の概要を参照して頂きたいですが、要約すると以下のような特徴があります

  • AWS Amplifyを利用した負荷テストを実施するインターフェイスになるフロントエンドを作成し、デプロイします。
  • デプロイされたwebサイトから負荷テストのシナリオを設定でき、Taurusという負荷テスト自動化フレームワークのDockerイメージベースでECS Taskを起動し、シナリオに従った負荷テストを実施します。
  • Taurusを利用しているので、JMeterやGatlingといったテストツールもサポートしています。

ただ単純にデプロイしたままだとGatlingは実行できる状態ではなく、少しカスタマイズする必要があるようです。JMeterテストは問題なく実施できるようでした。

負荷テスト環境の構築

環境の作成に関しては概要のページにCloudFormationのスタックを作成するリンクがあります。
つまり、ある程度慣れている人なら本当に数クリックで環境が完成します。

概要ページ右側の「AWSコンソールで起動する」ボタンです。

必要項目を設定し、構築が始まると5分ほどで完了し、すぐにでも負荷テストが実施できる状態になりますが、このままだと負荷テストを実施するにあたって一つ問題がありました。
それは何かというと、今回負荷をかけたい対象の環境は現在絶賛開発中でクローズドな環境で動いているため、負荷テスト環境からのアクセスが拒否されてしまう事でした

今回対象になっている環境に対してアクセスを許可するために、接続元のIPを固定化する必要があるので少し手を加えて負荷テスト環境から出る通信の送信元を固定にして、負荷テスト環境からアクセスできるようにしましょう。

送信元IPの固定化

負荷テストソリューションでは、VPC内に公開ネットワークを2つ作成してそのネットワーク上にコンテナを立ち上げ通信を行っているようです。

そこでVPC内に新しくNATゲートウェイを作成したネットワークを作成し、NATゲートウェイ経由で通信を行うように公開ネットワークのルートテーブルに変更を加えます。NATゲートウェイ作成は下記のテンプレートを利用します。

AWSTemplateFormatVersion: "2010-09-09"
Description:
  NAT Gateway Create

Parameters:
  VpcId:
    Type: String
  InternetGatewayId:
    Type: String
  PublicSubnetCIDR:
    Type: String
    Default: 192.168.32.0/20

Resources:

  Subnet:
    Type: "AWS::EC2::Subnet"
    Properties:
      CidrBlock: !Ref PublicSubnetCIDR
      AvailabilityZone:
        !Select
          - 0
          - !GetAZs
      VpcId: !Ref VpcId

  NatGwRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VpcId

  RouteToInterne:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      RouteTableId: !Ref NatGwRouteTable
      GatewayId: !Ref InternetGatewayId

  RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref NatGwRouteTable
      SubnetId: !Ref Subnet

  NATGatewayEIP:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  NATGateway:
    Type: "AWS::EC2::NatGateway"
    Properties:
      AllocationId: !GetAtt NATGatewayEIP.AllocationId
      SubnetId: !Ref Subnet
      Tags:
        - Key: Name
          Value: stress-test-natgw

パラメータには先に作成されている負荷テスト環境の値を参照し、設定します

  • VpcId
    • 負荷テスト環境のVPCを指定
  • InternetGatewayId
    • 負荷テスト環境作成時にできたインターネットゲートウェイを指定
  • PublicSubnetCIDR
    • 負荷テスト環境で作られたサブネットのCIDRと違うものを指定します。分散負荷テスト環境作成時にデフォルトのままならこちらも変更しなくても問題ないようにしています。

これらのリソースを作成した後、負荷テストソリューションで作成された公開ネットワークのルートテーブルの中からインターネットゲートウェイへ流れている通信を、NATゲートウェイに向けてあげれば簡単に公開ネットワークからNATゲートウェイ経由の内部ネットワークに変更出来ます。

変更前

変更後

これで無事に非公開な環境に対して負荷テストを行う準備が整いました。

簡単な負荷テスト

早速ブラウザ上から簡単な負荷テストを行ってみます。

特定のURLに対して、1分間。GETリクエストを行う負荷テストになります。
Test TypeはSingle HTTP Endopointの他に、jmxファイルをアップロードする事も出来ます。
上の画像は新しくテストを作成する画面ですが、SUBMITを行うと自動的にテストが開始されます。

指定の時間負荷テストが実施されると、結果を集計して表示してくれます。

パーセンタイルでの表示や、コネクションの時間を分けてくれたりと気が効いています。
途中経過を見たい場合は、メトリクスがCloudWatchにも送られているので
テスト中の画面のリンクからCloudWatchのダッシュボードを開く事が出来ます。

実際に使ってみて思った事。Tips

  • タスク数100、多重度200以上の負荷をかける場合
    • 分散負荷ソリューションを複数個並列に作成するのが良いと感じました
    • 但しFargate ECS Taskの起動APIに制限があり、テストを並列で実施する場合は、最初に実行したテストのTaskが完全に起動し切ってからじゃないと失敗してしまう
      • 多分この辺の制約があり公式には1テストでの起動しかサポートしてない旨の記載があるのだと予想します。
  • ドキュメントの制約で連続テスト時間は4時間との表記があるが、実際はおそらく上限なく設定できる
    • 1440分程度は動く事は確認出来ました。
  • デフォルトだとGatlingが利用できない。
    • 紹介動画だと割と堂々と使える旨の発言があったのでちょっとがっかりしました。多分頑張ればやれる気がします。
  • 立ち上げるTaurusコンテナのリソースを変更したい場合
    • 該当のTask definitionを更新して、それをキックするLambdaの環境変数を変更すれば問題なく出来ました。

まとめ

予め用意されているCloudFormationテンプレートから環境が作成出来るため、テストの実施環境としてかなり手軽に作成する事が出来る上に、環境を削除するのも簡単なので、必要な時にだけ環境を作成し、不要になったら削除を気軽に行えるのでとても便利です。
JMeterのシナリオを利用する事になった場合、jmx資産も生かせる&蓄積していくので、ぜひ皆さんも利用を検討してみて下さい。

それでは皆さん。良いお年を。

Discussion