Azure スポット仮想マシン (スポットインスタンス)

スポンサーリンク

Azure スポット仮想マシン(AWS用語では「スポットインスタンス」と呼称)は余剰リソースを利用した仮想マシンです。余剰リソースのため、SLAを保証された仮想マシンよりも割安な傾向がありますが、その代わりAzure全体のリソース不足の場合は停止してしまうデメリットがあります。再実行が許されるバッチ処理や検証用途などに使用すると上手に費用削減できるでしょう。

このページではAzure スポット仮想マシンの使い方をまとめます。

最も安価なBシリーズの仮想マシンはAzure Spot Virtual Machinesを使用できません。

前提

公式ドキュメント

参考になる公式ドキュメントを以下に示します。

事前設定

以下、リソースグループを作成します。

az group create --name MyResourceGroup --location japaneast

スポットインスタンスの作成

価格指定なしのスポットインスタンス

仮想マシン作成時に引数priorityににSpotを指定すると、Azure Spot Virtual Machinesを作成する事ができます。操作例は以下の通りです。

az vm create \
  --resource-group MyResourceGroup \
  --name linux010 \
  --image UbuntuLTS \
  --size Standard_D1_v2 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/authorized_keys  \
  --priority Spot

価格指定なしのスポットインスタンス

引数max-priceを指定すると、指定した価格を下回る場合のみ仮想マシンを起動するようになります。なお、max-priceは「ドル/時間」の単位で指定してください。

az vm create \
  --resource-group MyResourceGroup \
  --name linux020 \
  --image UbuntuLTS \
  --size Standard_D1_v2 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/authorized_keys  \
  --priority Spot \
  --max-price 0.5

立ち退き(eviction)時の挙動

Azureのリソース逼迫によってAzure Spot Virtual Machinesが停止した時に、ディスク等のリソース含めて削除するのか、それとも割り当て解除のみでVirtual Machineの再起動が可能な状態にするかは選択できます。

引数eviction-policyに「Deallocate(割り当て解除)」か「Delete(削除)」を指定する事で、立ち退き(eviction)時の挙動を明示的に定義できます。設定例は以下の通りです。

az vm create \
  --resource-group MyResourceGroup \
  --name linux030 \
  --image UbuntuLTS \
  --size Standard_D1_v2 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/authorized_keys  \
  --priority Spot \
  --eviction-policy Delete

スポットインスタンスの作成

削除予定の通知

Azure Spot Virtual Machinesは突然削除される事はなく、削除がスケジュールされた後に削除処理が実行されます。言い換えれば、スケジュールを事前に検知できれば、削除前にアプリケーションが正常終了するための処理を実行できます。

削除のスケジュールはIMDS(Azure Instance Metadata Service) APIを介して情報収集できます。各仮想マシンにログインし、169.254.169.254宛にHTTP requestを送信すると、その仮想マシンに関する情報を入手する事ができます。例えば、スケジュールに関する情報を取得するならば、以下のように操作します。

スケジュール以外の情報収集方法は「Azure Instance Metadata Service (Linux) – エンドポイント カテゴリ」等の資料を参照ください。

curl \
  -H Metadata:true \
  http://169.254.169.254/metadata/scheduledevents?api-version=2019-08-01

操作ログは以下の通りです。初回実行のみ2分程度の時間を要します。

jqコマンドがインストールされていない場合は「python -m json.tool」で代用する事もできます。

[azureuser@linux010 ~]$ curl \
>   -H Metadata:true \
>   http://169.254.169.254/metadata/scheduledevents?api-version=2019-08-01 \
>     | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    37    0    37    0     0      0      0 --:--:--  0:00:55 --:--:--    12
{
    "DocumentIncarnation": 0,
    "Events": []
}

削除の擬似テスト

以下のようなazコマンドでAzure Spot Virtual Machinesの削除を擬似できます。

az vm simulate-eviction \
  --resource-group MyResourceGroup \
  --name linux010

削除がスケジュールされると、IMDS(Azure Instance Metadata Service) APIで得たスケジュールに、NotBeforeの時刻が記述されています。以下の場合、1分程度しか猶予はありませんが、NotBeforeで指定された時刻より前に仮想マシンが削除される事はないので、それまでの時間を使ってアプリケーションが正常終了するための処理を遂行できます。

[azureuser@linux010 ~]$ date
2022年  3月  7日 月曜日 13:58:37 UTC
[azureuser@linux010 ~]$ 
[azureuser@linux010 ~]$ 
[azureuser@linux010 ~]$ curl \
>   -H Metadata:true \
>   http://169.254.169.254/metadata/scheduledevents?api-version=2019-08-01 \
>     | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   278  100   278    0     0  19868      0 --:--:-- --:--:-- --:--:-- 21384
{
    "DocumentIncarnation": 1,
    "Events": [
        {
            "Description": "",
            "EventId": "9EC3D2A6-E1E3-4472-8B57-F5C0502179DD",
            "EventSource": "Platform",
            "EventStatus": "Scheduled",
            "EventType": "Preempt",
            "NotBefore": "Mon, 07 Mar 2022 13:59:48 GMT",
            "ResourceType": "VirtualMachine",
            "Resources": [
                "linux010"
            ]
        }
    ]
}
[azureuser@linux010 ~]$

価格調査

APIを使った価格調査

Azure Spot Virtual Machinesの価格はAPIを使った調査が可能です。先頭100件に絞り込まれてしまいますが、特段のクエリなしに全量を表示するならば、以下のHTTP requestを送付します。

 https://prices.azure.com/api/retail/prices

最近のブラウザはJSONも綺麗に表示してくれますので、上記URLをブラウザに入力しただけでも、以下のように表示されます。

Azure 仮想マシン価格調査 01

もし、絞り込みをしたいならば、クエリ文字列を使って絞り込みが可能です。例えば、Virtual Machineのみを表示したいならば、以下URLをブラウザに入力します。

APIの仕様は「Azure 小売価格の概要」「クエリ パラメーターを使用して応答をカスタマイズする」等のドキュメントを参照ください。

 https://prices.azure.com/api/retail/prices?$filter=serviceName eq 'Virtual Machines'

Azure 仮想マシン価格調査 02

コードで記述する場合は、URLエンコーディングやエスケープに注意しつつ実装します。bashでcurlコマンドを使用する例ならば以下のようになります。

QUERY_STR="\$filter=serviceName eq 'Virtual Machines'"
QUERY_STR=${QUERY_STR}" and armRegionName eq 'japanwest'"
QUERY_STR=${QUERY_STR}" and contains(skuName,'Spot')"
QUERY_STR=${QUERY_STR}" and armSkuName eq 'Standard_D1_v2'"

curl 'https://prices.azure.com/api/retail/prices' \
  --get \
  --data-urlencode "${QUERY_STR}" | jq

実行例は以下の通りです。

admin@mac19 ~ % curl 'https://prices.azure.com/api/retail/prices' \
  --get \
  --data-urlencode "${QUERY_STR}" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1860  100  1860    0     0   1099      0  0:00:01  0:00:01 --:--:--  1107
{
  "BillingCurrency": "USD",
  "CustomerEntityId": "Default",
  "CustomerEntityType": "Retail",
  "Items": [
    {
      "currencyCode": "USD",
      "tierMinimumUnits": 0,
      "retailPrice": 0.01223,
      "unitPrice": 0.01223,
      "armRegionName": "japanwest",
      "location": "JA West",
      "effectiveStartDate": "2022-03-01T00:00:00Z",
      "meterId": "45d942dd-a2b4-53c2-834a-9e75e0e62726",
      "meterName": "D1 v2/DS1 v2 Spot",
      "productId": "DZH318Z0BQ34",
      "skuId": "DZH318Z0BQ34/02GT",
      "productName": "Virtual Machines Dv2 Series",
      "skuName": "D1 v2 Spot",
      "serviceName": "Virtual Machines",
      "serviceId": "DZH313Z7MMC8",
      "serviceFamily": "Compute",
      "unitOfMeasure": "1 Hour",
      "type": "Consumption",
      "isPrimaryMeterRegion": true,
      "armSkuName": "Standard_D1_v2"
    },
    {
      "currencyCode": "USD",
      "tierMinimumUnits": 0,
      "retailPrice": 0.01223,
      "unitPrice": 0.01223,
      "armRegionName": "japanwest",
      "location": "JA West",
      "effectiveStartDate": "2022-03-01T00:00:00Z",
      "meterId": "c298287a-838a-5daf-99ba-c918f597bb92",
      "meterName": "D1 v2/DS1 v2 Spot",
      "productId": "DZH318Z0BPVM",
      "skuId": "DZH318Z0BPVM/01HL",
      "productName": "Virtual Machines Dv2 Series Windows",
      "skuName": "D1 v2 Spot",
      "serviceName": "Virtual Machines",
      "serviceId": "DZH313Z7MMC8",
      "serviceFamily": "Compute",
      "unitOfMeasure": "1 Hour",
      "type": "DevTestConsumption",
      "isPrimaryMeterRegion": true,
      "armSkuName": "Standard_D1_v2"
    },
    {
      "currencyCode": "USD",
      "tierMinimumUnits": 0,
      "retailPrice": 0.02641,
      "unitPrice": 0.02641,
      "armRegionName": "japanwest",
      "location": "JA West",
      "effectiveStartDate": "2022-03-01T00:00:00Z",
      "meterId": "c298287a-838a-5daf-99ba-c918f597bb92",
      "meterName": "D1 v2/DS1 v2 Spot",
      "productId": "DZH318Z0BPVM",
      "skuId": "DZH318Z0BPVM/01HL",
      "productName": "Virtual Machines Dv2 Series Windows",
      "skuName": "D1 v2 Spot",
      "serviceName": "Virtual Machines",
      "serviceId": "DZH313Z7MMC8",
      "serviceFamily": "Compute",
      "unitOfMeasure": "1 Hour",
      "type": "Consumption",
      "isPrimaryMeterRegion": true,
      "armSkuName": "Standard_D1_v2"
    }
  ],
  "NextPageLink": null,
  "Count": 3
}

エラーメッセージによる調査

やや乱暴な方法ですが、エラーメッセージから調査する方法もあります。以下のようにmax-priceに極端に小さな値を指定すると、エラーメッセージで最小価格を教えてもらえます。実行例は以下の通りです。

$ az vm create \
  --resource-group MyResourceGroup \
  --name linux050 \
  --image UbuntuLTS \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/authorized_keys  \
  --priority Spot \
  --max-price 0.01
Argument '--max-price' is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
It is recommended to use parameter "--public-ip-sku Standard" to create new VM with Standard public IP. Please note that the default public IP used for VM creation will be changed from Basic to Standard in the future.
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one 
resource deployment operation failed. Please list deployment operations for details. 
Please see https://aka.ms/DeployOperations for usage 
details.","details":[{"code":"Conflict","message":"{\r\n  \"error\": {\r\n    \"code\": 
\"OperationNotAllowed\",\r\n    \"message\": 
\"Unable to perform operation 'Create VM' 
since the provided max price '0.01 USD' is lower than 
the current spot price '0.01885 USD' 
for Azure Spot VM size 'Standard_DS1_v2'. For more information, 
see http://aka.ms/AzureSpot/errormessages.\"\r\n  }\r\n}"}]}}
タイトルとURLをコピーしました