1
1

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 1 year has passed since last update.

Azure Load Testingを使って簡単な負荷テストをCI/CDに組み込む

Last updated at Posted at 2023-05-15

表題の通り、Azure Load Testingを使って簡単な負荷テストをGithubActionで自動化するといった内容をやってみた際の備忘録です。
ほぼ、こちらのドキュメントをなぞっている形になります🙏

テスト用のサンプルサイトを作成

Next.jsでサンプルサイトは作りました。GETリクエストが合った度に適当なデータをCosmosDBへ保存し、格納されているデータの合計数を表示する。といった簡単なものをWebAppにGithub Actionsでデプロイできるようにしておきます。
こんなサイトをテスト用に用意👇
image.png
ターゲットとなるアプリはなんでもいいので、こちらについては省略します。

サービスプリンシパルの作成

それでは本題。まずはGithub ActionsのワークフローからAzureにアクセスできるように共同作成者ロールを割り当てる作業です。
AzureにログインしてCloud Shell を立ち上げます。
image.png

以下のコマンドを入力します。

bash
subscription=$(az account show --query "id" -o tsv)
echo $subscription
bash
az ad sp create-for-rbac --name "my-load-test-cicd" --role contributor \
                         --scopes /subscriptions/$subscription \
                         --sdk-auth

するとサービスプリンシパルを表すJSONが出力されます、
これをコピーしてメモっておきます。

{
  "clientId": "00000000-0000-0000-0000-000000000000",
  "clientSecret": "00000000-0000-0000-0000-000000000000",
  "subscriptionId": "00000000-0000-0000-0000-000000000000",
  "tenantId": "00000000-0000-0000-0000-000000000000",
  "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
  "resourceManagerEndpointUrl": "https://management.azure.com/",
  "activeDirectoryGraphResourceId": "https://graph.windows.net/",
  "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
  "galleryEndpointUrl": "https://gallery.azure.com/",
  "managementEndpointUrl": "https://management.core.windows.net/"    
}

AzureADで見ると追加されている事が分かります。
image.png

続いて、サービスプリンシパルに Load Test Contributor ロールを割り当てます。

bash
object_id=$(az ad sp list --filter "displayname eq 'my-load-test-cicd'" --query "[0].id" -o tsv)

az role assignment create --assignee $object_id --role "Load Test Contributor" --scope /subscriptions/$subscription --subscription $subscription

Azure Load Testing

AzureポータルからLoad Testingをデプロイしておきます。
image.png

今回、テスト用のスクリプトはJMeterで簡単なものを作成しました。

quick_test.jmx
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">1</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">500</stringProp>
        <stringProp name="ThreadGroup.ramp_time">0</stringProp>
        <boolProp name="ThreadGroup.scheduler">true</boolProp>
        <stringProp name="ThreadGroup.duration">100</stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
      </ThreadGroup>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">******.azurewebsites.net</stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.protocol">https</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

  • ThreadGroup.main_controller:
    • ループコントローラーがどのように動作するかを制御します。ここでは、"continue_forever"が"false"、"loops"が"1"なので、テストは一回だけ実行されます。
  • ThreadGroup.num_threads:
    • このパラメータはスレッドの数(つまり仮想ユーザーの数)を指定します。ここでは500と設定したので、500の仮想ユーザーがテストを行います。
  • ThreadGroup.ramp_time:
    • これは全てのユーザーが起動するまでの時間(秒)を指定します。ここでは0と設定したので、すべてのユーザーがすぐに起動します。
  • ThreadGroup.scheduler:
    • スケジューラを使用するかどうかを制御します。ここでは"true"と設定したので、スケジューラが使用されます。
  • ThreadGroup.duration:
    • スケジューラが有効な場合、このパラメータはテストの実行時間(秒)を指定します。ここでは100と設定したので、テストは100秒間実行されます。
  • HTTPSampler.domain:
    • これはリクエストが送信されるドメイン(またはIPアドレス)を指定します。
  • HTTPSampler.port:
    • これは接続するポート番号を指定します。ここでは空欄です。
  • HTTPSampler.protocol:
    • これは使用するプロトコルを指定します。ここでは "https" を指定しています。
  • HTTPSampler.path:
    • これはリクエストのパスを指定します。
  • HTTPSampler.method:
    • これは使用するHTTPメソッド(GET、POST、PUTなど)を指定します。ここでは "GET" を指定してます。

設定ファイルはこちらを用意。

quick_test.yaml
displayName: Get_load-test-apps-001.azurewebsites.net
testPlan: quick_test.jmx
description: 
engineInstances: 3 #エンジンインタンスの数
testId: 5886d1f4-2033-45c5-b80c-c40f3df317a5

Github

Githubレポジトリのシークレットに先程のJSONで出力されたサービスプリンシパルの情報を設定しておきます。
名前はAZURE_CREDENTIALSとして、値には先程のJSONを貼り付けます。
image.png
image.png

デプロイしてテスト実行

quick_test.jmxquick_test.yamlをワークディレクトリの直下に保存します。
.github/workflow/内のyamlファイルを編集します。
以下を追記しました。

yaml
  loadTest:
    name: Load Test
    needs: deploy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout GitHub Actions 
        uses: actions/checkout@v2
          
      - name: Login to Azure
        uses: azure/login@v1
        continue-on-error: false
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
          
      - name: 'Azure Load Testing'
        uses: azure/load-testing@v1
        with:
          loadTestConfigFile: 'quick_test.yaml' #configFileName
          loadTestResource: 'my-load-test-test' #ResourceName
          resourceGroup: 'my-load-test-rg' #ResourceGroupName
              
      - uses: actions/upload-artifact@v2
        with:
          name: loadTestResults
          path: ${{ github.workspace }}/loadTest

変更が終わったら、Pushします。
無事デプロイからテストが実行されたようです。
image.png

ここからテスト結果をcsv形式でダウンロードもできます。
image.png

因みに、こういった条件を追加する事でテストに不合格の条件を追加できます。

quick_test.yaml
displayName: Get_load-test-apps-001.azurewebsites.net
testPlan: quick_test.jmx
description: 
engineInstances: 3
testId: 5886d1f4-2033-45c5-b80c-c40f3df317a5

+ failureCriteria: 
+  - percentage(error) > 50

エラー割合が50%以上なので不合格になりました。
ぽんこつアプリが爆誕しました…
image.png

さいごに

今回、CI/CDに組み込むという部分だけ抜粋しましたが、公式のチュートリアルではここからボトルネックを特定して改善するといった一連の流れも記載されています。
負荷テスト初心者なので、JMeterの使い方含めて継続して学習していこうと思います。

Azureに作成したリソースは使い終わったら削除する事を忘れずに!

参考

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?