エラーの概要

Azure 500エラーは、Azureのサーバー側で予期しない内部エラーが発生したことを示すHTTPステータスコードです。クライアント側に問題がなく、Azureインフラストラクチャ自体に一時的な障害が生じている状態を指します。このエラーが発生すると、リソースへのアクセスやデプロイメント、API呼び出しなどが中断され、進行中の処理は失敗に終わります。

実際のエラーメッセージ例

Azure Portal、Azure CLIまたはREST APIを使用する際に以下のようなエラーが表示されます。

{
  "error": {
    "code": "InternalServerError",
    "message": "An internal error occurred while processing your request. Please try again later.",
    "details": []
  }
}
$ az vm create --resource-group <your-resource-group> --name <your-vm-name> --image UbuntuLTS
InternalServerError: An internal server error occurred. Please retry your request.
RequestId: 12345678-1234-1234-1234-123456789012

よくある原因と解決手順

原因1:Azureインフラの一時的な障害

Azureのグローバルインフラストラクチャでは、稀に一時的な障害が発生します。これは大規模なシステムメンテナンス、ネットワーク障害、またはデータセンター内の機器トラブルなどが原因で起こります。この場合、ユーザー側のコードやリソース設定に問題はなく、Azureのサービス側で自動的に復旧を試みています。

修正例:

#!/bin/bash

# 最大3回まで再試行する関数
retry_command() {
  local max_attempts=3
  local attempt=1
  
  while [ $attempt -le $max_attempts ]; do
    echo "試行 $attempt / $max_attempts..."
    
    if az group create --name myResourceGroup --location eastus; then
      echo "成功しました"
      return 0
    fi
    
    if [ $attempt -lt $max_attempts ]; then
      echo "30秒待機してから再試行します..."
      sleep 30
    fi
    
    attempt=$((attempt + 1))
  done
  
  echo "最大再試行回数に達しました。Azureサポートにお問い合わせください。"
  return 1
}

retry_command

原因2:リソースのデプロイ中における内部処理の失敗

Azure Resource Manager(ARM)テンプレートやBicepテンプレートを使用してリソースをデプロイする際、複雑なテンプレート処理やネストされたリソース作成の途中で500エラーが発生することがあります。特に大量のリソースを一度にデプロイしたり、依存関係が複雑になったりした場合、バックエンド処理がタイムアウト(待機中に時間制限に達する)または例外をスローします。

問題のあるテンプレート:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2021-07-01",
      "name": "vm-complex-setup",
      "location": "[resourceGroup().location]",
      "properties": {
        "hardwareProfile": {
          "vmSize": "Standard_D4s_v3"
        },
        "osProfile": {
          "computerName": "myVM",
          "adminUsername": "azureuser",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "UbuntuServer",
            "sku": "18_04-lts-gen2",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "Premium_LRS"
            }
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', 'nic-1')]"
            }
          ]
        }
      }
    }
  ]
}

修正後(分割したテンプレート):

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2021-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[resourceGroup().location]",
      "kind": "StorageV2",
      "sku": {
        "name": "Standard_LRS"
      },
      "properties": {
        "accessTier": "Hot"
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2021-02-01",
      "name": "nic-primary",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-1', 'subnet-1')]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-1', 'subnet-1')]"
              }
            }
          }
        ]
      }
    }
  ]
}

複数のデプロイメントを分割して実行するスクリプト:

#!/bin/bash

# ステップ1:ネットワークリソースをデプロイ
echo "ステップ1:ネットワークをデプロイしています..."
az deployment group create \
  --resource-group myResourceGroup \
  --template-file network-template.json \
  --parameters networkParams.json

if [ $? -ne 0 ]; then
  echo "ネットワークデプロイに失敗しました"
  exit 1
fi

sleep 10

# ステップ2:ストレージアカウントをデプロイ
echo "ステップ2:ストレージアカウントをデプロイしています..."
az deployment group create \
  --resource-group myResourceGroup \
  --template-file storage-template.json \
  --parameters storageParams.json

if [ $? -ne 0 ]; then
  echo "ストレージデプロイに失敗しました"
  exit 1
fi

sleep 10

# ステップ3:仮想マシンをデプロイ
echo "ステップ3:仮想マシンをデプロイしています..."
az deployment group create \
  --resource-group myResourceGroup \
  --template-file vm-template.json \
  --parameters vmParams.json

原因3:APIリクエストレートの制限または過度なリソース消費

Azure APIには呼び出しレート制限(一定時間に許可される呼び出し回数の上限)が存在します。短時間に大量のAPIリクエストを送信したり、リソースが膨大なデータ処理を実行しようとしたりすると、バックエンド側の処理キューがオーバーフローして500エラーが返されます。特に自動化スクリプトやプログラマティックなリソース管理で並列処理を使用している場合、この問題が顕在化しやすいです。

問題のあるコード(並列処理が過度):

import azure.mgmt.compute
from azure.identity import DefaultAzureCredential
import concurrent.futures

credential = DefaultAzureCredential()
compute_client = azure.mgmt.compute.ComputeManagementClient(
    credential, "<subscription-id>"
)

resource_group = "<your-resource-group>"
vm_names = [f"vm-{i}" for i in range(100)]

# 並列処理で100個のVMを一度に削除しようとする
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
    futures = [
        executor.submit(
            compute_client.virtual_machines.begin_delete,
            resource_group, vm_name
        )
        for vm_name in vm_names
    ]
    concurrent.futures.wait(futures)

修正後(順序処理と待機間隔を追加):

import azure.mgmt.compute
from azure.identity import DefaultAzureCredential
import time

credential = DefaultAzureCredential()
compute_client = azure.mgmt.compute.ComputeManagementClient(
    credential, "<subscription-id>"
)

resource_group = "<your-resource-group>"
vm_names = [f"vm-{i}" for i in range(100)]

# 1つずつ削除し、各操作の間隔を2秒開ける
for i, vm_name in enumerate(vm_names):
    try:
        print(f"削除中: {vm_name} ({i+1}/{len(vm_names)})")
        operation = compute_client.virtual_machines.begin_delete(
            resource_group, vm_name
        )
        operation.wait()  # 操作完了を待機
        time.sleep(2)  # APIレート制限回避のための待機
        
    except Exception as e:
        print(f"エラー: {vm_name} - {str(e)}")
        time.sleep(10)  # エラー時はさらに長く待機
        continue

ツール固有の注意点

Azure Portal経由でのエラー発生

Azure Portal上での操作中に500エラーが発生した場合、まず status.azure.com で対象リージョンのステータスを確認してください。ポータル上のバナーに表示されることもあります。ブラウザーキャッシュをクリアして再度操作を試みることも有効です。

Azure CLI での RequestID の確認

Azure CLI経由でエラーが発生した際、出力メッセージに RequestId が含まれています。このIDはAzure Supportへの問い合わせ時に不可欠です。以下のようにコマンド出力をファイルに保存しておくことをお勧めします。

az deployment group create \
  --resource-group myResourceGroup \
  --template-file template.json \
  2>&1 | tee deployment.log

保存したログファイルからRequestIDを抽出できます。

grep "RequestId" deployment.log

免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。