Scheduled Actions を利用して大量の仮想マシンの電源操作を簡素化する

azure
Published: 2025-11-19

はじめに

Scheduled Actions という機能が突然(のはず)一般公開になりました。

API のスロットリングやリトライをいい感じにやりつつ大量の仮想マシンを起動、停止、休止してくれる機能のようです。

従来、大量の仮想マシンの電源を操作するためには、仮想マシン1台1台に対して起動や停止の要求を投げる必要がありました。Get-AzVM で仮想マシンの一覧を取得したうえで、その一覧をループで回して Start-AzVM を実行するスクリプトを書いたことがある方は多いと思います。その結果、Azure Resource Manager や Compute Resource Provider に対して短期間に大量の要求が届くこととなり、要求がスロットリングされて電源操作が行われないことがありました。この仕様を回避するためには、要求を出すクライアントや要求を出す時間を分散させてスロットリングを回避する、もしスロットリングされた場合にエラーをハンドリングして指数関数的バックオフでリトライを試みるなどの対応が必要です。この対応がめちゃくちゃ手間でした。

ですが Scheduled Actions を使うと、利用者が行う API リクエストは1回で済み、スロットリングや一時的なエラーを Scheduled Actions が自動的に対処してくれるようです。すばらしい。

ドキュメントがあっさりしていて使い方がイメージしにくかったので、実際に調べて試しました。一通り調べた後に Azure PowerShell の存在に気が付いたので、API 直叩きでのお試し結果になっています。ご了承ください。

試して分かったこと

指定した時間の実行と今すぐ実行の2種類があります。例えば、起動には、起動予定を登録する API(Submit Start) と今すぐ起動する API(Execute Start) が存在しています。

現時点で毎日・毎週という定期実行の設定はできないみたいです。そのため、定期的に起動や停止を行いたい場合には、Azure Function や Automation Account などを利用して定期的に起動・停止を行う必要があります。サービス組み込みで定期実行の設定が来てくれることを切に願います。

実行できる処理は、起動、割り当て解除、休止と作成です。電源操作が主眼だと思いますが、API 的には「今すぐ作成」が存在します。

Scheduled Actions - Virtual Machines Execute Create

1度の処理の対象にできる仮想マシンは100台です。

起動の際には optimizationPreference を指定する必要があります。選択肢は「Cost」と「Availability」、「CostAvailabilityBalanced」です。API のリファレンスに違いが記載されています。

Value Description
Cost Optimize while considering cost savings
Availability Optimize while considering availability of resources
CostAvailabilityBalanced Optimize while considering a balance of cost and availability

記載があっさりで仕様が不明瞭です…きっと、Cost を選ぶと仮想マシンの費用を節約するために指定した時間ギリギリまで粘って起動を試みる、Availability を選ぶと確実な起動を目指すべく早めに起動を試みる、CostAvailabilityBalanced はその間を狙う、みたいな感じでしょうか…

スケジュールの指定方法は2種類あります。InitiateAt と CompleteBy です。InitiateAt を指定した場合には、指定した時間から処理が始まります。CompleteBy の場合には、指定した時間までに終わるように処理が始まります。ただし、CompleteBy で割り当て解除はできません(エラーになりました)。割り当て解除は InitiateAt 必須です。

実践

サブスクリプションに Microsoft.ComputeSchedule を登録する必要があります。登録していないと以下のエラーが発生します。

{
  "error": {
    "code": "SubscriptionNotRegistered",
    "message": "The subscription 'MY-SUB-ID' is not registered to 'Microsoft.ComputeSchedule'."
  }
}

あとは以下の様に要求を作って API に投げれば OK です。「Cost 重視で 11月19日の16時30分までに CompleteBy して」という要求を virtualMachinesSubmitStart の API に投げます。対象にしたい仮想マシンの ID を配列の中に含めます。なお、タイムゾーンというプロパティはありますが、現時点で指定できるのは UTC だけです。

$correlationid = (New-guid).Guid
$body = @"
{
  "schedule": {
    "deadline": "2025-11-19T07:30:00.000Z",
    "deadLine": "2025-11-19T07:30:00.000Z",
    "timezone": "UTC",
    "timeZone": "UTC",
    "deadlineType": "CompleteBy"
  },
  "executionParameters": {
    "optimizationPreference": "Cost"
  },
  "resources": {
    "ids": [
      "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
      "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0"
    ]
  },
  "correlationid": "$correlationid"
}
"@
> 
> Invoke-AzRestMethod -Method POST -Uri "https://management.azure.com/subscriptions/MY-SUB-ID/providers/Microsoft.ComputeSchedule/locations/japaneast/virtualMachinesSubmitStart?api-version=2025-05-01" -Payload $body

要求が受け付けられると以下のような応答が返ってきます。各仮想マシンごとに結果が管理され、現在の状況が results.operation.state で確認できます。


StatusCode : 200
Content    : {
   "description": "Start Resource request",
   "type": "VirtualMachines",
   "location": "japaneast",
   "results": [
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "744d05da-aa1a-411f-ae88-e572616a140e",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "55f49ed4-e386-455d-895d-8033234b6a7c",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "64a83c28-27c5-47e7-b7f5-fc565072113a",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "40270442-2b2a-4657-a39f-6af5bc0b1e3f",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "ca90cd4c-f9ab-4553-82ec-db2c95836adf",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "c5701dba-14a0-43fa-8027-c96f0f798d95",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     },
     {
       "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0",
       "errorCode": null,
       "errorDetails": null,
       "operation": {
         "operationId": "e0658dc5-b99e-4166-a510-6addc6e7f1ad",
         "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0",
         "opType": "Start",
         "subscriptionId": "MY-SUB-ID",
         "deadline": "2025-11-19T16:30:00+09:00",
         "deadlineType": "CompleteBy",
         "state": "PendingScheduling",
         "timeZone": "UTC",
         "resourceOperationError": null,
         "completedAt": null,
         "retryPolicy": null
       }
     }
   ]
 }

登録後に現在の状況を確認するためには、登録時の correlationid と各仮想マシンごとの operationId が必要になります。設定済みの Scheduled Actions を List する API がなさそうなので、これらの値を保持しておくのマジ大事。

現在の状況を確認するためには、次の API を利用します。

Scheduled Actions - Virtual Machines Get Operation Status

API を叩く際に、確認したい correlationid と operationIds を含める必要があります。

$body = @"
{
  "operationIds": [
    "744d05da-aa1a-411f-ae88-e572616a140e",
    "55f49ed4-e386-455d-895d-8033234b6a7c",
    "64a83c28-27c5-47e7-b7f5-fc565072113a",
    "40270442-2b2a-4657-a39f-6af5bc0b1e3f",
    "ca90cd4c-f9ab-4553-82ec-db2c95836adf",
    "c5701dba-14a0-43fa-8027-c96f0f798d95",
    "e0658dc5-b99e-4166-a510-6addc6e7f1ad"
  ],
"correlationid": "6a30d009-180f-49b3-a7ea-dbfc8ae6aabc"
}
"@

while ($true) {
    $res = Invoke-AzRestMethod -Method POST -Uri "https://management.azure.com/subscriptions/MY-SUB-ID/providers/Microsoft.ComputeSchedule/locations/japaneast/virtualMachinesGetOperationStatus?api-version=2025-05-01" -Payload $body

    write-host (Get-Date)
    ($res.content | ConvertFrom-Json -Depth 10).results | Select-Object resourceId, @{Label="state"; Expression={$_.operation.state}} | ConvertTo-Json
    Start-Sleep -Seconds 300
}

上記のコマンドを利用して5分毎に状況を確認し続けたところ、「Cost 重視で 16時30分まで」と指示したにもかかわらず16時から起動を始めました。結構ビビりですね。Failed になっているのは存在しない仮想マシンの ID を誤って指定してしまったためです。すでに起動中の仮想マシン vm0509-0 への起動要求はエラーではなく成功になりました。時間になったときに既にあるべき状態になっていたので成功ということでしょう。

2025/11/19 16:01:05
[
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
    "state": "Executing"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
    "state": "Executing"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
    "state": "Executing"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
    "state": "Succeeded"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
    "state": "Executing"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
    "state": "Failed"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0",
    "state": "Succeeded"
  }
]

次は停止してみます。11月19日17時30分から開始です。割り当て解除時には optimizationPreference を指定できません。

$body = @"
{
  "schedule": {
    "deadline": "2025-11-19T08:30:00.000Z",
    "deadLine": "2025-11-19T08:30:00.000Z",
    "timezone": "UTC",
    "timeZone": "UTC",
    "deadlineType": "InitiateAt"
  },
  "executionParameters": {
  },
  "resources": {
    "ids": [
      "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
      "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
      "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0"
    ]
  },
  "correlationid": "$correlationid"
}
"@

Invoke-AzRestMethod -Method POST -Uri "https://management.azure.com/subscriptions/MY-SUB-ID/providers/Microsoft.ComputeSchedule/locations/japaneast/virtualMachinesSubmitDeallocate?api-version=2025-05-01" -Payload $body

先程と同じ要領で5分に1回状態を確認し続けたところ、17時31分に確認した際には全ての仮想マシンが成功になっていました。ほぼ30分台には割り当て解除を始めたようです。

($res.content | ConvertFrom-Json -Depth 10).results | Select-Object resourceId, @{Label="state"; Expression={$_.operation.state}}, @{Label="completedAt"; Expression={$_.operation.completedAt}}  | ConvertTo-Json
[
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/tester/providers/Microsoft.Compute/virtualMachines/avd-0",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:26.2472295+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd04-0",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:30.1533873+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-dc/providers/Microsoft.Compute/virtualMachines/dc03",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:24.0126295+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/test1106/providers/Microsoft.Compute/virtualMachines/iis01",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:26.2789106+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/multi-0",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:45.6216497+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/rg-avd/providers/Microsoft.Compute/virtualMachines/avd03-0",
    "state": "Failed",
    "completedAt": "2025-11-19T17:30:00.1570234+09:00"
  },
  {
    "resourceId": "/subscriptions/MY-SUB-ID/resourceGroups/acs/providers/Microsoft.Compute/virtualMachines/vm0509-0",
    "state": "Succeeded",
    "completedAt": "2025-11-19T17:30:54.7150993+09:00"
  }
]

まとめ

突然一般公開になった Scheduled Actions を試しました。とてもよさそうです。Azure ポータルからの設定と定期実行の機能が追加されたらめちゃくちゃ便利だと思います。

Note

  • 当サイトは個人のブログです。このブログに示されている見解や意見は個人的なものであり、所属組織の見解や意見を表明するものではありません。
  • 公開情報を踏まえて正確な情報を掲載するよう努めますが、その内容の完全性や正確性、有用性、安全性、最新性について一切保証しません。
  • 添付文章やリンク先などを含む本サイトの内容は作成時点でのものであり、予告なく変更される場合があります。