kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

Azure Pipelinesから Azure Load Testingの負荷テストを実施する

f:id:kkamegawa:20211211130329p:plain この記事はAzure DevOpsアドベントカレンダー12日目の記事です。

qiita.com

Azure Load Testingについて

先日、Azure Load Testingという新しいサービスがプレビュー公開されました。はっきり言ってしまえばJMeterのマネージドサービスです。

azure.microsoft.com

あれ、Azure DevOpsにもLoad Testがあったよね?と思われるかもしれませんが、ありました。そして2020/3/31にディスコンになりました。

azure.microsoft.com

Visual Studioと統合されていて、VSのロードテスト機能からも使えて便利だったのですが引退してしまい、ちょっと困っていました。何回か紹介したことがあります。

kkamegawa.hatenablog.jp

kkamegawa.hatenablog.jp

今ではほかのマネージドサービスを使うか、pnopさんが出しているカスタムイメージ使うか、というくらいでしたが、新しいオプションとして選択できそうです。

www.pnop.co.jp

ちょっと試してみましょう。注意事項としてjmxファイルの内容(サンプラー名やコントローラー名といったメタデータ)は英語で書きましょう。最初日本語で書いていてLoad TestがAcceptedのままずーっと動かなくて悩みました。もしかして、と思って英語に変えたらあっさり動きました。JmeterのUIを日本語にすると自動的に日本語のメタデータが入っていしまうので、英語で使うことをお勧めします。

そういえばAzure DevOps Load Testのときも同じことで悩んでいたような…。jmeterのインストールはchocolateyやmacOSの場合はHomeBrewでできるので省略(いまだにJRE 8をペアで入れさせられるのには閉口しますが…)。そういえば、macOSでjmeterのファイル保存できないのLook & Feelを変えないといけないって誰が気付くんだ。

ポータルから作成する

f:id:kkamegawa:20211208060542p:plain

ポータルから作成します。

f:id:kkamegawa:20211208060549p:plain

サブスクリプション、名前、リージョンを設定します。今のところ限られたリージョンだけですが、米国中南部を選んでみます。Load Testingの枠としてはこれだけなのですぐ作成すればOKです。

ポータルからテストを実行する

Test Plan, Parameter(実行時パラメータ), テスト合格基準、モニタリングなどポータルから設定します。

f:id:kkamegawa:20211208060622p:plain

テスト名は任意。Run after creationにチェックがあるとすぐに実行されます。

f:id:kkamegawa:20211208060626p:plain

ここで作っておいたjmxファイルをアップロードします。くれぐれもリスナー名やクライアント名に日本語を使わないようにしましょう(重要なことなので繰り返し)。

f:id:kkamegawa:20211208060630p:plain

実行時パラメータがあれば指定します。

f:id:kkamegawa:20211208060634p:plain

実行エンジン数を指定します。4を指定すれば1000スレッドまでかけられるようですね。jmxでは250スレッドまでなので、それをいくつの実行エンジンでスケールするかということのようです。

f:id:kkamegawa:20211208060650p:plain

ここでエラー基準を決めます。注意事項としてWeb Appsのお安い(FとかDとか)インスタンスではウォームアップの時間が必要になるので、ここにあるように応答時間(Response Time)に100msなどの短い時間を指定していると初回実行が間に合わなくて失敗します。

f:id:kkamegawa:20211208060642p:plain

モニタリングするリソースを選択します。

f:id:kkamegawa:20211208060654p:plain

作成したら即実行が始まります。

f:id:kkamegawa:20211208060658p:plain

f:id:kkamegawa:20211208060701p:plain

こんな感じで結果が見えます。failedになっているのは上で書いた通り実験用の環境でWeb Appsのウォームアップが間に合ってないからです😅。実行には気を付けて。さて、CI/CDで実行するための準備をします。

CI/CDのためにロール割り当てを設定する

Azure Load Testingはプレビューだからか作っただけではAzure Pipelinesから呼び出せません。ロール割り当てをします。

f:id:kkamegawa:20211208060555p:plain

いつものようにService Connectionを作成して、Azure Load Testingのリソースグループを割り当てます。Manage Service Principalをクリックしてアプリケーションを表示して、アプリケーション表示名をコピペします。

f:id:kkamegawa:20211208060607p:plain

Load Testing Contributorにアプリ追加します。

f:id:kkamegawa:20211208060617p:plain

こんな感じで割り当て終わりです。

Azure Pipelinesから呼び出す。

marketplace.visualstudio.com

Marketplaceからタスクを追加します。実行する前に以下の二つをどこかのレポジトリにコミットしておかなくてはなりません。

  1. Azure Load Testingを実行するテストケースを記述したYAMLファイル
  2. JMeterのjmxファイル

アプリケーション外部のレポジトリでもいいですし、一緒でもいいでしょう。ただし、「Webアプリケーションはこういう基準で動かなければならない」ということが品質のルールで決められているとしたらレビューする人たちにも参照可能な外部レポジトリを用意しておくのがいいかもしれませんね。

jmxファイルも同様です。

サンプルのAzure Load Testing実行するためのYAMLです。

version: v0.1
testName: SampleTest
testPlan: sample1.jmx
description: 'Load test website home page'
engineInstances: 1
failureCriteria:
  - avg(response_time_ms) > 300
  - percentage(error) > 50

CSVでパラメータ指定も可能です。testPlanにはこのYAMLから参照可能なパスで指定してください。ここでは同じフォルダーにダウンロードしているのでパス指定はありません。

f:id:kkamegawa:20211209173720p:plain

YAMLで実行するステージを切り出すとこんな感じですね。

  - stage:
    dependsOn: Deploy
    condition: succeeded()
    jobs:
    - job: LoadTest
      pool:
        vmImage: 'Ubuntu-latest'
      steps:
        - task: DownloadBuildArtifacts@0
          displayName: 'Download Artifact'
          inputs:
            buildType: 'current'
            downloadType: 'single'
            artifactName: 'myWebsiteName'
            downloadPath: '$(System.ArtifactsDirectory)'
        - task: AzureLoadTest@1
          inputs:
            azureSubscription: '{サービス接続名}'
            loadTestConfigFile: '$(System.ArtifactsDirectory)/myWebsiteName/azure-load-testing.yml'
            resourceGroup: '{リソースグループ名}'
            loadTestResource: '{ロードテスト名}'
        - publish: $(System.DefaultWorkingDirectory)/loadTest
          artifact: results

ここでは明示的に別ステージにしています。通常デプロイが成功したらこの手のテストを実行するので、dependsOnにデプロイ用のステージを指定して、conditionsucceeded()を指定しています。

なぜDownloadBuildArtifactsタスクがあるのかと思うかもしれませんが、ステージが異なるとartifactの参照ができません。明示的にダウンロードしてくる必要があります。なので、YAMLとjmxはCopyFilesタスクでBuild.ArtifactStagingDirectoryにコピーして、PublishBuildArtifactsタスクで発行しなくてはなりません。デプロイされるアプリケーションとは別のartifactsにしておく方が望ましいかもしれませんし、同じテストを繰り返すという意味では一緒のほうがいいかもしれません。ここはお好みですかね。

最後のpublish: $(System.DefaultWorkingDirectory)/loadTestでテスト結果を発行しています。

f:id:kkamegawa:20211209173724p:plain

成功するとこんな感じですね。ログにhttpの応答時間や、View the load test run in progress atでAzureポータルのリンクが出ているのでワンクリックで結果が見えます。

f:id:kkamegawa:20211209173727p:plain

ポータルと同じようにYAMLに設定したfailureCriteriaが満たせない場合、ビルドが失敗したと表示されます。

f:id:kkamegawa:20211209173731p:plain

Azureポータルでもこんな風に失敗となります。

注意事項

  • Public InternetにあるURLに対して実施するものなので、閉域にあるサービスに対してはかけられません。JMeterのカスタムイメージ使いましょう。
  • jmxは英語で書きましょう
  • 実施可能なデータセンターの場所が限られていますので、応答時間気にするサービスで日本になくてはならないものだとちょっと注意が必要です。
  • YAMLのステージ分割は必須になる
  • YAMLとjmxをレポジトリに入れて、artifactsとしておくのを忘れずに