Azure Metadata Service: Linux VM の Scheduled Events
適用対象: ✔️ Linux VM ✔️ フレキシブル スケール セット ✔️ 均一スケール セット
スケジュールされたイベントとは、仮想マシン (VM) のメンテナンスに備えるための時間をアプリケーションに与える Azure Metadata Service です。 今後のメンテナンス イベント (再起動など) に関する情報を提供することで、アプリケーションがイベントの準備を行い、中断を制限できるようにします。 このサービスは、Windows および Linux の、PaaS と IaaS を含むすべての Azure Virtual Machine の種類で利用できます。
Windows のスケジュールされたイベントの詳細については、Windows VM のスケジュールされたイベントに関する記事をご覧ください。
スケジュール化されたイベントでは、今後のイベントに関するプロアクティブ通知が提供されます。既に発生しているイベントに関する事後対応情報については、「Azure Resource Graph の VM 可用性に関する情報」および「Azure 仮想マシンの可用性アラート ルールを作成する」を参照してください。
注意
Scheduled Events は、すべての Azure リージョンで一般公開されています。 最新リリースについては、「利用可能なバージョンとリージョン」をご覧ください。
Scheduled Events を使用する理由
多くのアプリケーションに、VM のメンテナンスに備える時間が得られるメリットがあります。 この時間を使用して、可用性、信頼性、およびサービスを向上させる、次のようなアプリケーション固有のタスクを実行できます。
- チェックポイントと復元
- 接続のドレイン
- プライマリ レプリカのフェールオーバー
- ロード バランサー プールからの削除
- イベント ログ
- グレースフル シャットダウン
Scheduled Events を使用すると、アプリケーションはメンテナンスが行われる時期を検出し、その影響を制限するタスクをトリガーできます。
Scheduled Events は、次のユース ケースでイベントを提供します。
- プラットフォームで開始されるメンテナンス (例: VM の再起動、ライブ マイグレーション、ホストの更新を保持するメモリ)。
- 仮想マシンは、まもなく故障することが予測されている劣化したホスト ハードウェアで実行されている。
- ハードウェア障害が発生したホストで仮想マシンが実行されていた。
- ユーザーが開始するメンテナンス (たとえば、ユーザーによる再起動や VM の再デプロイ)。
- スポット VM およびスポット スケール セット インスタンスの削除。
基本操作
Metadata Service では、VM 内部からアクセスできる REST エンドポイントを使用した VM の実行に関する情報が公開されます。 情報はルーティング不可能な IP 経由で提供され、VM の外部には公開されません。
範囲
スケジュールされたイベントは以下に配信され、以下が確認できます。
- スタンドアロンの仮想マシン。
- Azure クラウド サービス (クラシック) 内のすべての VM。
- 可用性セット内のすべての VM。
- スケール セットの配置グループすべての VM。
可用性セット全体または仮想マシン スケール セットの配置グループ内のすべての仮想マシン (VM) に対してスケジュール化されたイベントは、可用性ゾーンの使用状況に関係なく、同じグループまたはセット内の他のすべての VM に配信されます。
そのため、イベント内の Resources
フィールドをチェックして、影響を受ける VM を特定する必要があります。
Note
1 障害ドメイン (FD = 1) を使用するスケール セット内の GPU 加速仮想マシンが受け取るスケジュールされたイベントは影響を受けるリソースに関するものだけです。 イベントは、同じ配置グループ内のすべての VM にブロードキャストされるわけではありません。
エンドポイントの検出
VNET が有効な VM の場合は、静的でルーティング不可能な IP アドレス 169.254.169.254
から Metadata Service を利用できます。 Scheduled Events の最新バージョンのフル エンドポイントは次のとおりです。
http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01
VM が仮想ネットワーク内で作成されていない場合 (クラウド サービスと従来の VM の既定のケース)、使用する IP アドレスを検出する追加のロジックが必要となります。 ホスト エンドポイントの検出方法の詳細については、このサンプルを参照してください。
利用可能なバージョンとリージョン
Scheduled Events のサービスは、バージョンによって管理されています。 バージョンは必須で、現在のバージョンは 2020-07-01
です。
バージョン | リリースの種類 | リージョン | リリース ノート |
---|---|---|---|
2020-07-01 | 一般公開 | All | |
2019-08-01 | 一般公開 | All | |
2019-04-01 | 一般公開 | All | |
2019-01-01 | 一般公開 | All | |
2017-11-01 | 一般公開 | All | |
2017-08-01 | 一般公開 | All | |
2017-03-01 | プレビュー | All |
注意
Scheduled Events の前のプレビュー リリースでは、api-version として {latest} がサポートされていました。 この形式はサポートされなくなり、今後非推奨となる予定です。
Scheduled Events の有効化と無効化
Scheduled Events は、ユーザーが初めてイベントを要求したときに、サービスに対して有効になります。 最初の呼び出しでは最大 2 分の応答遅延が発生すると予想されますが、5 分以内にはイベントの受信が開始されます。 スケジュール化されたイベントは、サービスで 24 時間エンドポイントへの要求が行われないと、サービスに対して無効になります。
ユーザー開始メンテナンス
ユーザーが Azure Portal、API、CLI または PowerShell を使用して開始した VM のメンテナンスによって、スケジュールされたイベントが発生します。 これによって、アプリケーションでメンテナンス準備ロジックをテストすることができ、アプリケーションでは、ユーザーが開始したメンテナンスの準備をすることができます。
VM を再起動すると、型 Reboot
のイベントがスケジュールされます。 VM を再デプロイすると、型 Redeploy
のイベントがスケジュールされています。 通常、ユーザー イベント ソースを含むイベントは、ユーザーが開始するアクションの遅延を回避するために、すぐに承認できます。 プライマリ VM が応答しなくなる場合に備えて、プライマリ VM とセカンダリ VM を通信させ、ユーザーが生成したスケジュールされたイベントが承認されるようにすることをお勧めします。 イベントをすぐに承認すると、アプリケーションを適切な状態に回復する遅延を防ぐことができます。
VMSS ゲスト OS のアップグレードまたは再イメージ化のスケジュール化されたイベントは、メモリ保持更新をサポートする汎用 VM サイズでのみサポートされます。 G、M、N、および H シリーズでは機能しません。 VMSS ゲスト OS のアップグレードと再イメージ化のスケジュール化されたイベントは、既定で無効になっています。 サポートされる VM サイズでこれらの操作のスケジュール化されたイベントを有効にするには、まず OSImageNotificationProfile を使用してそれらを有効にします。
API の使用
概要
Scheduled Events の処理、準備、回復には、2 つの主要なコンポーネントがあります。 VM に影響する現在のスケジュール化されたイベントはすべて、IMDS のスケジュール化されたイベント エンドポイント経由で読み取ることができます。 イベントが終了状態に達すると、イベントの一覧から削除されます。 次の図は、1 つのスケジュールされたイベントで発生する可能性があるさまざまな状態遷移を示しています:
EventStatus:"Scheduled" 状態のイベントの場合は、ワークロードを準備するための手順を実行する必要があります。 準備が完了したら、スケジュール化されたイベント API を使用してイベントを承認する必要があります。 それ以外の場合、NotBefore 時間に達すると、イベントは自動的に承認されます。 VM が共有インフラストラクチャ上にある場合、システムは、同じハードウェア上の他のすべてのテナントもジョブまたはタイムアウトを承認するまで待機します。 影響を受けるすべての VM から承認が収集されるか、NotBefore 時間に達すると、Azure は EventStatus:"Started" を使用して新しいスケジュールされたイベント ペイロードを生成し、メンテナンス イベントの開始をトリガーします。 イベントが終了状態に達すると、イベントの一覧から削除されます。 これは、顧客が VM を復旧するためのシグナルとして機能します。
アプリケーションでスケジュールされたイベントを読み取って管理する方法を示す疑似コードを次に示します:
current_list_of_scheduled_events = get_latest_from_se_endpoint()
#prepare for new events
for each event in current_list_of_scheduled_events:
if event not in previous_list_of_scheduled_events:
prepare_for_event(event)
#recover from completed events
for each event in previous_list_of_scheduled_events:
if event not in current_list_of_scheduled_events:
receover_from_event(event)
#prepare for future jobs
previous_list_of_scheduled_events = current_list_of_scheduled_events
スケジュール化されたイベントは高可用性要件を持つアプリケーションでよく使用されるため、考慮すべき例外的なケースがいくつかあります:
- スケジュール化されたイベントが完了し、配列から削除されると、別の EventStatus:"Scheduled" イベントを含む新しいイベントがない限り、それ以上の影響はありません
- Azure はフリート全体のメンテナンス操作を監視し、まれにメンテナンス操作が適用されるリスクが高すぎると判断します。 その場合、スケジュール化されたイベントは "Scheduled" から直接 events 配列から削除されます
- ハードウェア障害が発生した場合、Azure は "Scheduled" 状態をバイパスし、すぐに EventStatus:"Started" 状態に移行します。
- イベントがまだ EventStatus:"Started" 状態にあるときでも、スケジュール化されたイベントに公開されたよりも短い期間による別の影響が発生する場合があります。
Azure の可用性保証の一環として、異なる障害ドメイン内の VM は、定期的なメンテナンス操作によって同時に影響を受けることはありません。 ただし、操作が次々にシリアル化される場合があります。 1 つの障害ドメイン内の VM は、別の障害ドメインのメンテナンスが完了した直後に、EventStatus:"Scheduled" でスケジュールされたイベントを受信できます。 選択したアーキテクチャに関係なく、VM に対して保留中の新しいイベントを常にチェックし続けます。
イベントの正確なタイミングは異なりますが、次の図は、一般的なメンテナンス操作の進め方に関する大まかなガイドラインを示しています:
- EventStatus:"Scheduled" から Approval Timeout: 15 分
- 影響時間: 7 秒
- EventStatus:"Started" から Completed (イベント配列から削除されたイベント): 10 分
VM の可用性に影響を与えるすべての操作はスケジュールされたイベントになりますが、すべてのスケジュールされたイベントが Azure アクティビティ ログや Resource Health など、他の Azure の表示面に現れるわけではありません。 スケジュールされたイベントを定期的にチェックすることで、VM への今後の影響に関する最新情報を確実に得られます。
ヘッダー
メタデータ サービスのクエリを実行するときには、要求が意図せずリダイレクトされないように、ヘッダー Metadata:true
を指定する必要があります。 Metadata:true
ヘッダーは、スケジュールされたイベントのすべての要求で必要です。 要求にヘッダーを含めないと、メタデータ サービスから Bad Request (無効な要求) という応答があります。
イベントのクエリ
次の呼び出しを行うと、スケジュールされたイベントのクエリを実行できます。
Bash のサンプル
curl -H Metadata:true http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01
PowerShell のサンプル
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01" | ConvertTo-Json -Depth 64
Python のサンプル
import json
import requests
metadata_url ="http://169.254.169.254/metadata/scheduledevents"
header = {'Metadata' : 'true'}
query_params = {'api-version':'2020-07-01'}
def get_scheduled_events():
resp = requests.get(metadata_url, headers = header, params = query_params)
data = resp.json()
return data
応答には、スケジュールされたイベントの配列が含まれています。 空の配列は、現在スケジュールされているイベントがないことを意味します。 スケジュールされたイベントがある場合は、応答にイベントの配列が含まれます。
{
"DocumentIncarnation": {IncarnationID},
"Events": [
{
"EventId": {eventID},
"EventType": "Reboot" | "Redeploy" | "Freeze" | "Preempt" | "Terminate",
"ResourceType": "VirtualMachine",
"Resources": [{resourceName}],
"EventStatus": "Scheduled" | "Started",
"NotBefore": {timeInUTC},
"Description": {eventDescription},
"EventSource" : "Platform" | "User",
"DurationInSeconds" : {timeInSeconds},
}
]
}
イベントのプロパティ
Property | 説明 |
---|---|
Document Incarnation | イベント配列が変更されたときに増加する整数。 同じインカネーションを持つドキュメントには同じイベント情報が含まれており、イベントが変更されると、インカネーションが増加されます。 |
EventId | このイベントのグローバル一意識別子。 例:
|
EventType | このイベントによって発生する影響。 値:
|
ResourceType | このイベントが影響を与えるリソースの種類。 値:
|
リソース | このイベントが影響を与えるリソースの一覧。 例:
|
EventStatus | このイベントの状態。 値:
Completed や類似の状態が提供されることはありません。 イベントが完了すると、イベントは返されなくなります。 |
NotBefore | このイベントが開始される時間。 このイベントは、この時刻より前に開始されないことが保証されます。 イベントが既に開始されている場合は空白になります 例:
|
説明 | このイベントの説明。 例:
|
EventSource | イベントのイニシエーター。 例:
|
DurationInSeconds | イベントによって発生する中断の予想される期間。 この影響期間に短い期間、二次的影響が生じる可能性があります。 例:
|
イベントのスケジューリング
各イベントは、スケジュールされているイベントの種類に基づいて、将来の最小値の時間でスケジュールされます。 この時間は、イベントの NotBefore
プロパティに反映されます。
EventType | 最小値の通知 |
---|---|
Freeze | 約 15 分 |
再起動 | 約 15 分 |
Redeploy | 10 分 |
Terminate | ユーザーが構成可能:5 から 15 分 |
つまり、遅くともイベントが発生する前の最小通知時間までに、イベントの今後のスケジュールを検出できます。 イベントはスケジュールされると、それが承認されるか、または NotBefore
時間が経過した後に、Started
状態に移動します。 ただし、まれに、操作が開始される前に Azure によって取り消されます。 その場合、イベントは Events 配列から削除され、影響は、以前にスケジュールしたようには発生しません。
Note
Azure では、劣化したハードウェアに起因するホストの故障を予測することが可能になり、移行をスケジュールすることでサービスの中断を軽減しようとすることがあります。 影響を受ける仮想マシンには、スケジュールされているイベントと NotBefore
が届きます。これは通常、2、3 日先になります。 実際の時間は、予測された故障のリスク評価によって異なります。 Azure では、可能であれば、7 日前に通知を行いますが、実際の時間はさまざまであり、ハードウェアが今にも故障する可能性が高い場合、7 日より短くなることがあります。 システムによって開始される移行の前にハードウェアで障害が発生した場合に備えて、サービスのリスクを最小限に抑えるために、できるだけ早く仮想マシンをご自身で再デプロイすることをお勧めします。
注意
ホスト ノードでハードウェア障害が発生した場合、Azure では最小通知期間を無視して、影響を受けた仮想マシンの復旧プロセスを直ちに開始します。 これにより、影響を受けた VM が応答できない場合の復旧時間が短縮されます。 復旧プロセス中に、影響を受けるすべての VM に対して、EventType = Reboot
および EventStatus = Started
が設定されたイベントが作成されます。
ポーリング頻度
更新のエンドポイントは、任意の頻度でポーリングできます。 ただし、要求間の間隔が長くなるほど、発生するイベントに対応するのが遅くなる可能性があります。 ほとんどのイベントは、5 - 15 分前に通知されますが、場合によっては、通知がわずか 30 秒前ということもあります。 対策を講じるための時間をできるだけ多く確保するために、1 秒に 1 回サービスをポーリングすることをお勧めします。
イベントの開始
今後予定されているイベントを確認し、グレースフル シャットダウンのロジックを完了すると、EventId
を使用してメタデータ サービスに POST
呼び出しを行うことにより、未処理のイベントを承認できます。 この呼び出しは、通知の最小時間を短縮できる (可能な場合) ことが Azure に示されます。 イベントは、承認されてもすぐには開始されない場合があります。場合によっては、イベントを続行する前に、ノードでホストされているすべての VM の承認を Azure が必要とする場合があります。
次に示すのは、POST
要求本文で求められている JSON のサンプルです。 要求には、StartRequests
の一覧を含める必要があります。 各 StartRequest
には、迅速に進める必要があるイベントの EventId
が含まれます。
{
"StartRequests" : [
{
"EventId": {EventId}
}
]
}
有効なイベント ID が渡されると、別の VM がそのイベントを既に承認している場合でも、サービスは常に 200 の成功コードを返します。 400 エラー コードは、要求ヘッダーまたはペイロードの形式が正しくないことを示します。
Note
イベントは、POST メッセージまたは NotBefore 時間の経過によって許可されない限り続行されません。 これには、Azure portal からの VM の再起動などのユーザーによってトリガーされたイベントが含まれます。
Bash のサンプル
curl -H Metadata:true -X POST -d '{"StartRequests": [{"EventId": "f020ba2e-3bc0-4c40-a10b-86575a9eabd5"}]}' http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01
PowerShell のサンプル
Invoke-RestMethod -Headers @{"Metadata" = "true"} -Method POST -body '{"StartRequests": [{"EventId": "5DD55B64-45AD-49D3-BBC9-F57D4EA97BD7"}]}' -Uri http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01 | ConvertTo-Json -Depth 64
Python のサンプル
import json
import requests
def confirm_scheduled_event(event_id):
# This payload confirms a single event with id event_id
payload = json.dumps({"StartRequests": [{"EventId": event_id }]})
response = requests.post("http://169.254.169.254/metadata/scheduledevents",
headers = {'Metadata' : 'true'},
params = {'api-version':'2020-07-01'},
data = payload)
return response.status_code
注意
イベントの受信確認により、イベントを受信確認した VM だけでなく、イベント内のすべての Resources
でイベントが続行されます。 そのため、受信確認を調整するリーダーを選択できます。これは、Resources
フィールド内の最初のマシンと同様に簡単です。
応答の例
次のイベントは、ライブ状態で別のノードに以降された 2 つの VM で発生した一例です。
DocumentIncarnation
は、Events
に新しい情報があるたびに変化していきます。 イベントの承認により、WestNO_0 と WestNO_1 の両方で凍結を続行できます。 -1 の DurationInSeconds
は、操作にどれほどの時間がかかるか、プラットフォームで認識されないことを示します。
{
"DocumentIncarnation": 1,
"Events": [
]
}
{
"DocumentIncarnation": 2,
"Events": [
{
"EventId": "C7061BAC-AFDC-4513-B24B-AA5F13A16123",
"EventStatus": "Scheduled",
"EventType": "Freeze",
"ResourceType": "VirtualMachine",
"Resources": [
"WestNO_0",
"WestNO_1"
],
"NotBefore": "Mon, 11 Apr 2022 22:26:58 GMT",
"Description": "Virtual machine is being paused because of a memory-preserving Live Migration operation.",
"EventSource": "Platform",
"DurationInSeconds": 5
}
]
}
{
"DocumentIncarnation": 3,
"Events": [
{
"EventId": "C7061BAC-AFDC-4513-B24B-AA5F13A16123",
"EventStatus": "Started",
"EventType": "Freeze",
"ResourceType": "VirtualMachine",
"Resources": [
"WestNO_0",
"WestNO_1"
],
"NotBefore": "",
"Description": "Virtual machine is being paused because of a memory-preserving Live Migration operation.",
"EventSource": "Platform",
"DurationInSeconds": 5
}
]
}
{
"DocumentIncarnation": 4,
"Events": [
]
}
Python サンプル
次のサンプルでは、スケジュールされたイベントのメタデータ サービスにクエリを実行し、未処理の各イベントを承認しています。
#!/usr/bin/python
import json
import requests
from time import sleep
# The URL to access the metadata service
metadata_url ="http://169.254.169.254/metadata/scheduledevents"
# This must be sent otherwise the request will be ignored
header = {'Metadata' : 'true'}
# Current version of the API
query_params = {'api-version':'2020-07-01'}
def get_scheduled_events():
resp = requests.get(metadata_url, headers = header, params = query_params)
data = resp.json()
return data
def confirm_scheduled_event(event_id):
# This payload confirms a single event with id event_id
# You can confirm multiple events in a single request if needed
payload = json.dumps({"StartRequests": [{"EventId": event_id }]})
response = requests.post(metadata_url,
headers= header,
params = query_params,
data = payload)
return response.status_code
def log(event):
# This is an optional placeholder for logging events to your system
print(event["Description"])
return
def advanced_sample(last_document_incarnation):
# Poll every second to see if there are new scheduled events to process
# Since some events may have necessarily short warning periods, it is
# recommended to poll frequently
found_document_incarnation = last_document_incarnation
while (last_document_incarnation == found_document_incarnation):
sleep(1)
payload = get_scheduled_events()
found_document_incarnation = payload["DocumentIncarnation"]
# We recommend processing all events in a document together,
# even if you won't be actioning on them right away
for event in payload["Events"]:
# Events that have already started, logged for tracking
if (event["EventStatus"] == "Started"):
log(event)
# Approve all user initiated events. These are typically created by an
# administrator and approving them immediately can help to avoid delays
# in admin actions
elif (event["EventSource"] == "User"):
confirm_scheduled_event(event["EventId"])
# For this application, freeze events less that 9 seconds are considered
# no impact. This will immediately approve them
elif (event["EventType"] == "Freeze" and
int(event["DurationInSeconds"]) >= 0 and
int(event["DurationInSeconds"]) < 9):
confirm_scheduled_event(event["EventId"])
# Events that may be impactful (for example, reboot or redeploy) may need custom
# handling for your application
else:
#TODO Custom handling for impactful events
log(event)
print("Processed events from document: " + str(found_document_incarnation))
return found_document_incarnation
def main():
# This will track the last set of events seen
last_document_incarnation = "-1"
input_text = "\
Press 1 to poll for new events \n\
Press 2 to exit \n "
program_exit = False
while program_exit == False:
user_input = input(input_text)
if (user_input == "1"):
last_document_incarnation = advanced_sample(last_document_incarnation)
elif (user_input == "2"):
program_exit = True
if __name__ == '__main__':
main()
次のステップ
- Scheduled Events のコード サンプルは、Azure Instance Metadata Scheduled Events の GitHub リポジトリをご覧ください。
- Azure Samples GitHub リポジトリにある Node.js Scheduled Events コード サンプルを確認します。
- 「インスタンス メタデータ サービス」で使用可能な API の詳細についてご覧ください。
- Azure での Linux 仮想マシンの計画的メンテナンスに関するページをご覧ください。
- Azure Samples GitHub リポジトリで Azure Event Hubs を使用してスケジュールされたイベントをログに記録する方法について学習してください。