はじめに ISID X(クロス) イノベーション 本部 の池田です。 Azure Portal から Azure Load Testing を操作する方法については以下の記事もご覧ください。 tech.isid.co.jp 負荷試験 の計画の中でいろいろな利用パターンでの試験により環境を分析するケースがあります。 しかし、Azure Portal からの操作では JMeter スクリプト のアップロードや参照できるリソース選択など選択項目が多く、複数パターンを何度も手動で作成するのは手間です。 そこで CLI から操作して複数テストを一括登録する方法を試しましたのでご紹介します。 利用ツール 通常のAzureリソースの CLI 操作としては、Azure CLI や Azure Power Shell, ARMテンプレート を利用するのが一般的です。しかし、2023年2月にGAしたばかりの Azure Load Testing においては 2023年5月時点でこれらのツールでAzureリソース作成はできるものの詳細な設定ができませんでした。Azure Load Testing REST API では先行してテスト作成の機能が提供されていたため、こちらを利用して作成します。(現在はAzure CLI によるテスト作成もサポートされるようになっています) 今回の スクリプト 実行環境は以下のとおりです。 スクリプト の記載は環境依存のものが含まれますので、参考にされる際はご自身の環境に合わせて調整してください。 PowerShell 7.3.4 azure-cli 2.49.0 curl 8.0.1 (Windows) libcurl/8.0.1 Schannel WinIDN 試験環境の概要 今回使用するテスト環境の構成は以下のとおりです。App Service 既定のWebサイトをテスト対象としてAzure Load TestingからHTTPリク エス トを連続送信します。その上でAzureリソースの負荷状況を Azure Load Testing の ダッシュ ボードに表示する構成となります。 Azure Load Testingリソースの作成 Azureリソース作成はAzure CLI で機能提供されていましたので、この部分はこちらのコマンドを利用して作成します。 az load create --name ${loadTestName} -- resource-group ${resourceGroupName} --location eastasia データプレーン URI の取得 Azure リソースマネージャーに対する要求では az rest コマンドを利用すると認証ヘッダーを自動付与できて便利です。 az rest で REST API を呼び出して作成されたリソースのデータプレーンエンドポイントを取得します。 $loadTest = ( az rest ` --method get ` --uri https: // management.azure.com / subscriptions / ${subscriptionId} / resourceGroups / ${resourceGroupName} / providers / Microsoft.LoadTestService / loadTests / ${loadTestName} ? api-version = 2022 - 12 - 01 ` | ConvertFrom-Json ) $Endpoint = $loadTest .properties.dataPlaneURI $Endpoint 以下のような出力が得られます。これでデータプレーン操作に必要なエンドポイントが取得できました。 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.eastasia.cnt-prod.loadtesting.azure.com データプレーン用アクセス トーク ンの取得 ここからは Azureリソースマネージャー へのアクセスではなくデータプレーンエンドポイントへの操作となります。データプレーン用のアクセス トーク ンを取得する必要があります。 必要なアクセス トーク ン Azure Load Testing REST API のリファレンスを参照すると、「 https://cnt-prod.loadtesting.azure.com/.default%E3%80%8D%E3%82%92Scope%E3%81%A8%E3%81%97%E3%81%9F%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82 Load Test Administration - Create Or Update Test アクセス トーク ンの取得 az account get- access -token コマンドを利用して、該当スコープに対するアクセス トーク ンを取得します。 ( 参考: az account get-access-token ) $accessToken = (az account get-access-token ` --scope 'https://cnt-prod.loadtesting.azure.com/.default' ` --query 'accessToken' ` --output tsv) テストの構成 データプレーンエンドポイントとアクセス トーク ンがそろいましたので、続いてデータプレーンの操作をします。 データプレーンはTemplateファイルを用意してそれを curl コマンドで投げ込む形で操作します。 ID採番 まずは、テストIDとして使用するGuidを採番します。 $testId = ( New-Guid ) テスト作成 実際にAzure Load Testing REST API を呼び出してテストを作成していきます。 (参考: Load Test Administration - Create Or Update Test ) curl ` --request PATCH ` --header "Authorization: Bearer $accessToken " ` --header "Content-Type: application/merge-patch+json" ` --url "https:// ${Endpoint} /tests/ ${testId} ?api-version=2022-11-01" ` -- upload-file TestTemplate.json 送信ファイルに記述するパラメータが以下となります。Azure Portal 上で作成したテストの内容を API で取得して参考にしつつ作るのがおすすめです。 (参考: Load Test Administration - Get Test ) { "displayName": "displayName_test1", "description": "", "keyvaultReferenceIdentityType": "SystemAssigned", "passFailCriteria": { "passFailMetrics": {} }, "loadTestConfiguration": { "engineInstances": 10, "splitAllCSVs": false, "quickStartTest": false } } アプリ コンポーネント 登録 次にテスト結果画面に表示するアプリ コンポーネント (Azure リソースのコレクション)を登録します。 (参考: Load Test Administration - Create Or Update App Components ) curl ` --request PATCH ` --header "Authorization: Bearer $accessToken " ` --header "Content-Type: application/merge-patch+json" ` --url "https:// ${Endpoint} /tests/ ${testId} /app-components?api-version=2022-11-01" ` -- upload-file AppComponents.json アプリ コンポーネント は以下のように列挙していく形で登録します。参考とする既存設定の取得 API は以下です。 (参考: Load Test Administration - Get App Components ) { "components": { "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda": { "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda", "resourceName": "app-demo-ikeda", "resourceType": "Microsoft.Web/sites", "resourceGroup": "rg-load-test", "subscriptionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "kind": "app" }, "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo": { "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo", "resourceName": "plan-load-demo", "resourceType": "Microsoft.Web/serverfarms", "resourceGroup": "rg-load-test", "subscriptionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "kind": "app" } } } メトリック登録 続いて、テスト結果画面に表示するメトリックを登録します。 (参考: Load Test Administration - Create Or Update Server Metrics Config ) curl ` --request PATCH ` --header "Authorization: Bearer $accessToken " ` --header "Content-Type: application/merge-patch+json" ` --url "https:// ${Endpoint} /tests/ ${testId} /server-metrics-config?api-version=2022-11-01" ` -- upload-file ServerMetricsConfig.json 前段で登録したアプリ コンポーネント に対するメトリックを列挙します。参考とする既存設定の取得 API は下記です。 (参考: Load Test Administration - Get Server Metrics Config ) { "metrics": { "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/Http5xx": { "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/Http5xx", "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda", "metricNamespace": "microsoft.web/sites", "name": "Http5xx", "aggregation": "Total", "resourceType": "microsoft.web/sites" }, "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/Requests": { "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/Requests", "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda", "metricNamespace": "microsoft.web/sites", "name": "Requests", "aggregation": "Total", "resourceType": "microsoft.web/sites" }, "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/HttpResponseTime": { "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda/providers/microsoft.insights/metricdefinitions/HttpResponseTime", "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/sites/app-demo-ikeda", "metricNamespace": "microsoft.web/sites", "name": "HttpResponseTime", "aggregation": "Average", "resourceType": "microsoft.web/sites" }, "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo/providers/microsoft.insights/metricdefinitions/CpuPercentage": { "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo/providers/microsoft.insights/metricdefinitions/CpuPercentage", "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo", "metricNamespace": "microsoft.web/serverfarms", "name": "CpuPercentage", "aggregation": "Average", "resourceType": "microsoft.web/serverfarms" }, "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo/providers/microsoft.insights/metricdefinitions/MemoryPercentage": { "id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo/providers/microsoft.insights/metricdefinitions/MemoryPercentage", "resourceId": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg-load-test/providers/Microsoft.Web/serverfarms/plan-load-demo", "metricNamespace": "microsoft.web/serverfarms", "name": "MemoryPercentage", "aggregation": "Average", "resourceType": "microsoft.web/serverfarms" } } } JMeter スクリプト 登録 以下の操作でテストで実行する JMeter スクリプト をアップロードします。 (参考: Load Test Administration - Upload Test File ) curl ` --request PUT ` --header "Authorization: Bearer $accessToken " ` --header "Content-Type: application/octet-stream content" ` --url "https:// ${Endpoint} /tests/ ${testId} /files/ ${NAME_JMX} ?api-version=2022-11-01&fileType=JMX_FILE" ` -- upload-file lt-demo .jmx こちらが JMeter で作成した JMX ファイルです。今回はHTTP Getリク エス トをループするシンプルな スクリプト を使用しています。 <?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.5"> <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> <intProp name="LoopController.loops">-1</intProp> </elementProp> <stringProp name="ThreadGroup.num_threads">10</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></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">app-demo-ikeda.azurewebsites.net</stringProp> <stringProp name="HTTPSampler.port">443</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> テストの実行 テスト実行 ボディ部にテストIDを指定することで登録したテスト内容を実行できます。テスト表示名は スクリプト 内で日時から作成しています。 (参考: Load Test Run - Create Or Update Test Run ) curl ` --request PATCH ` --header "Authorization: Bearer $accessToken" ` --header "Content-Type: application/merge-patch+json" ` --url "https://${Endpoint}/test-runs/$(New-Guid)?api-version=2022-11-01" ` --data "{'testId': '${testId}','displayName':'TestRun_$((Get-Date).ToString("yyyy/MM/dd_HH:mm:ss"))'}" 実行結果の確認 Azure Portal での確認 Azure Portal 上で作成したテストが実行されていることを確認できます。 アプリ コンポーネント テスト画面の「アプリ コンポーネント 」から REST API で登録したアプリ コンポーネント が確認できます。 メトリックの構成 同じく「メトリックの構成」から表示メトリックも反映されていることが確認できます。 備考 ドキュメントが整備されていない場合、 API の利用方法を調べるのにブラウザのDevToolsでAzure Portal の通信内容を見るのも参考になります。今回もAzure Portal 上での設定項目と API 項目に差異があり、通信内容を見てみると新しい Preview バージョンの API を利用していました。新しいサービスではドキュメント化が遅れているケースもありますので必要に応じて参考にしましょう。 まとめ Azure Load Testing の操作を REST API を利用して スクリプト 化することで、複数パターンの試験登録が簡単にできるようになりました。新しいサービスでは周辺ツールがまだ提供されていないケースもありますが、ベースとなる REST API が先行して提供されていることがあります。 REST API による操作も活用することでAzureでできることが広がります。ご参考になれば幸いです。 私たちは同じチームで働いてくれる仲間を探しています。 クラウド アーキテクトの業務に興味がある方のご応募をお待ちしています。 クラウドアーキテクト 執筆: @ikeda.jun 、レビュー: @mizuno.kazuhiro ( Shodo で執筆されました )