自分の VM に何が起きるか把握する Scheduled Events (Instance Metadata Service) のご紹介

Teppei Ishii

2018/1/12 追記: 当機能は、VM が所属する可用性セット内、あるいはクラシック デプロイメントの同じクラウド サービス内に存在するほかの VM 全てのイベントが通知される点にご注意ください。

ドキュメント: Azure Metadata Service: Windows VM のスケジュールされたイベント (プレビュー) より抜粋します。

Scope

スケジュールされたイベントの配信先は次のとおりです。

そのため、イベント内の Resources フィールドをチェックして、影響を受ける VM を特定する必要があります。

 

2017/10/13 追記: 一時停止 (Freeze) を伴うメンテナンスのサンプルを文末に追記しました。

 


こんにちは、Azure サポート部の石井です。

 

今回は、Azure の Instance Metadata Service について、実例を交えて紹介します。VM 内部から、自身のメンテナンス時間が把握でき、猶予時間内に適切な処理が行えるというものです。

 


詳しい内容は以下技術情報をご参考ください:

Windows VM 用の Azure Instance Metadata Service

https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/instance-metadata-service

Azure Metadata Service: Windows VM のスケジュールされたイベント (プレビュー)

https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/scheduled-events

 

[機能の紹介]

VM の内部のシステム管理者やアプリケーション開発・運用者から見ると、Azure プラットフォーム側から何らかの操作をされる、ということは、実際にシステムに影響が出るまで分からないものです。それが問題となるケースにおいては、Instance Metadata Service を使うことで事前に対応ができる猶予時間を得られることができます。

Azure VM の内部から、以下のような操作を知ることができるというものになります。

・非通知のメンテナンスとして VM を一時停止 (フリーズ) 状態にして行うもの

・Azure 仮想マシン管理者のポータル・CLI などの操作による再起動や再デプロイ

マイクロソフトが行うメンテナンスのほか、Azure のリソース管理者が行う再起動・再デプロイなど、広義の意味でのメンテナンス作業があるかどうか、VM 内部でプログラム的に知ることができるということがメリットです。

 

具体例を交え、役に立つシナリオは以下の通りです。

・メンテナンスの有無を記録しておき、VM 内のアプリの不調・切断といった事象の手がかりとする

・シャットダウンに時間がかかる、といった通常のシャットダウンや再起動命令に間に合わないシステムで猶予時間が得られ、あらかじめ停止処理・フェールオーバー処理が開始できる

後者についてより詳しい例を挙げると、「データベースと連動するアプリケーションがあり、シャットダウンに 15 分かかる。」というような場合、Azure からシャットダウンをするとシャットダウンの 15 分が待たれず強制再起動されてしまいます。つまり、アプリケーションが終了中、強制 Kill されてしまうというリスクがあります。

つまり、Azure 管理者は、VM 内部のシステムにログインし、データベースを止めてから Azure VM を停止するという手間をかけるという、パブリック クラウド時代の目標となる自動化とは程遠い運用が必要でした。Instance Metadata Service を使えば、Azure 基盤側から再起動が行われるとき、内部のアプリケーションが事前にシャットダウン処理を実行できるため、管理者がわざわざ VM にログインする手間が省けます。

[使用例と考察]

Instance Metadata Service とは、VM 内部からのみアクセスが出来る特殊な Web サイト http://169.254.169.254/ にアクセスすることで、VM 自身のメンテナンス情報が受け取れるというものです。

メンテナンスが特に無い状態では、空白のコンテンツが返され、メンテナンスがスケジュールされている場合、適切なパラメーターが入った文字列が得られます。パラメーターについての詳細は、冒頭にもあったリンクを参照してください。

 

メンテナンスは、最長でも 15 分前に知ることが出来る、というものです。何時間前、何日前、といったスパンではない点に注意してください。

あくまでも自動処理を意図したものというデザインになっています。

 

このことから、ベースとなるのは、以下のようなシンプルな PowerShell Script によるループ処理です。

運用に組み込む場合、OS の Task Scheduler でバックグラウンド実行させることが前提となります。

while($true){

$message = curl http://169.254.169.254/metadata/scheduledevents?api-version=2017-04-02

$message | Out-File C:\test\metadata.txt -append

$message.Content | Out-File C:\test\metadata.txt -append

# $message.Content の内容によって何か処理を行う

Start-Sleep -seconds 10

}

まずは、テキスト ログに出力される内容から、何がおきるのか見てみます。

何もスケジュールされていない時は、このようなアウトプットになります。

//$message の中身。正常に情報が取れたことを示す StatusCode 200 と、日時が記録されています。

StatusCode : 200

StatusDescription : OK

Content : {"DocumentIncarnation":0,"Events":[]}

RawContent : HTTP/1.1 200 OK

x-ms-package-infosource: ProcessRequestFromPAAgent

Content-Length: 37

Content-Type: application/json

Date: Wed, 04 Oct 2017 01:27:00 GMT

ETag: 813064690011386043

Server: Microsof...

Forms : {}

Headers : {[x-ms-package-infosource, ProcessRequestFromPAAgent], [Content-Length, 37], [Content-Type,

application/json], [Date, Wed, 04 Oct 2017 01:27:00 GMT]...}

Images : {}

InputFields : {}

Links : {}

ParsedHtml : System.__ComObject

RawContentLength : 37

// $message.Content の中身は、何もないので空白です

{"DocumentIncarnation":0,"Events":[]}

 

さて、実際にポータルの Virtual Machines ブレードから [再起動] をクリックしてみます。ここで、Instance Metadata Service をコールしている VM では、15 分後に再起動がスケジュールされます。

以下のように $message.Content の中身 が変わります。

//$message の文字列

StatusCode : 200

StatusDescription : OK

Content : {"DocumentIncarnation":1,"Events":[{"EventId":"C6125276-A766-40DE-AC13-370AC02C8C88","EventStatus":

"Scheduled","EventType":"Reboot","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBe

fo...

RawContent : HTTP/1.1 200 OK

x-ms-package-infosource: ProcessRequestFromPAAgent

Content-Length: 238

Content-Type: application/json

Date: Wed, 04 Oct 2017 01:30:44 GMT

ETag: 5865132596377058819

Server: Micros...

Forms : {}

Headers : {[x-ms-package-infosource, ProcessRequestFromPAAgent], [Content-Length, 238], [Content-Type,

application/json], [Date, Wed, 04 Oct 2017 01:30:44 GMT]...}

Images : {}

InputFields : {}

Links : {}

ParsedHtml : System.__ComObject

RawContentLength : 238

// $message.Content の内容

{"DocumentIncarnation":1,"Events":[{"EventId":"C6125276-A766-40DE-AC13-370AC02C8C88","EventStatus":"Scheduled","EventType":"Reboot","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBefore":"Wed, 04 Oct 2017 01:45:39 GMT"}]}

上記 Instance Metadata を取得した時間が 1:30 、再起動の NotBefore は 1:45 とあることから、ドキュメントの記載どおり 15 分の猶予がもたれていることが分かります。

つまり、Instance Metadata Service をコールしている VM には、シャットダウンに猶予時間が生じるということですね。

// 対象の Windows のシステム イベント ログより、実際に NotBefore の時間以降にシャットダウンが行われていることが確認できます

Information 10/4/2017 1:46:03 AM User32 1074 None

The process C:\Windows\System32\svchost.exe (tidv2promo) has initiated the shutdown of computer tidv2promo on behalf of user NT AUTHORITY\SYSTEM for the following reason: Other (Planned)

Reason Code: 0x80000000

Shutdown Type: shutdown

Comment:

なお、VM のメニューから、[再デプロイ] ボタンを押した場合の Content は以下のとおりでした。EventType が Redeploy (再デプロイ) であることに注目してください。(長いので Instance Metadata 自体は省略しますが、公開情報どおり再デプロイ= 10 分間の猶予ということも確認できました。)

{"DocumentIncarnation":4,"Events":[{"EventId":"9618CBC9-96E1-4F2C-8A5C-CBB9D1F1C7A0","EventStatus":"Scheduled","EventType":"Redeploy","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBefore":"Wed, 04 Oct 2017 02:13:09 GMT"}]}

 

"EventType" が Freeze のものはすぐに検証が出来ませんでしたが、これは Azure で不定期に行われるメモリ保護更新 (あるいはインプレース VM 移行) と呼ばれる処理です。過去の事例ですと、月に 1 度、といった頻度で不定期に行われています。

この処理では、最長で 30 秒ほど一時停止状態になりますが、メモリ情報などは完全に保存されるので、一時的なネットワーク通信エラーやタイムアウトになる程度の影響となります。この動作が何か問題となるケースではログを残しておいたり、意図的にフェールオーバーをさせてしまうといったことも有効かもしれません。

ただし、Freeze を伴うメンテナンスでは多くの場合、TCP/IP の再送、あるいはアプリケーション レイヤーでのリトライ処理で問題にならないケースがほとんどです。Azure サポート チームとしては、特別な理由がない限り、Freeze のイベントについては、イベント ログやテキスト ログに痕跡を残しておき、アプリケーションなどのトラブルの自己分析のために役立てるといった活用法をお勧めします。

 

ここまでの記載で、Instance Metadata Service でどういった情報が取れるのかや、挙動について把握が出来ました。

PowerShell スクリプトによって、$message.Content の文字列の "EventType" が存在するか否か、という条件によって、何らかのアプリケーションのバッチ処理をキックするといった対応が一般的です。

 

[補足: 準備が出来た場合に、即時メンテナンス実行を許可する]

上記の例では、再起動を行った場合 15 分、といった猶予時間が得られましたが、Instance Metadata Service では VM 内部から準備が出来次第、「もうメンテナンスしてもいいよ」という許可を出すことも可能です。

許可を出さないと、Azure 管理者が再起動命令をした後、15分ぎりぎりまで再起動がはじまらない、ということになるため、タイムリーな対応にならないということが懸念されます。そのような場合には処理が完了次第、許可を出すようにスクリプトを組むことをお勧めします。

サンプル スクリプトは、冒頭のリンクにて紹介されていますので、手動で行った例を添えておきます。

 

// Azure Portal から VM の再起動をクリックした状態で、Instance Meatadata を取得します。

$message = curl http://169.254.169.254/metadata/scheduledevents?api-version=2017-04-02

// 上記で得られた Content を出力すると、以下の DocumentIncarnation 番号と、EventID が得られました。

$message.Content

{"DocumentIncarnation":7,"Events":[{"EventId":"053CDB29-A979-4532-958F-42C814B35DDF","EventStatus":"Scheduled","EventType":"Reboot","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBefore":"Wed, 04 Oct 2017 04:17:42 GMT"}]}

 

上記に対して、許可のメソッドを発行します。

 

Invoke-RestMethod -Uri http://169.254.169.254/metadata/scheduledevents?api-version=2017-04-02 -Headers @{"Metadata"="true"} -Method POST -Body '{"DocumentIncarnation":"7", "StartRequests": [{"EventId": "053CDB29-A979-4532-958F-42C814B35DDF"}]}'

 

本来なら、スケジュールされた 4:17 を待って再起動されるはずですが、上記 Invoke-RestMethod 実行後すぐにシャットダウン処理が行われ、全体的なメンテナンス完了を早めることができました。

 

近日、Azure 基盤で大々的に、再起動を伴うメンテナンスも計画されています。このため、VM 管理者側からの対応策としてこの機能を使い、アプリケーションやシステムへの影響を極力抑えるといった工夫も行えるかと存じます。

 

 

- 2017/10/13追記: 一時停止 (Freeze) を伴うメンテナンスのサンプル

以下の通り、一時停止を伴うメンテナンスが行われる際のサンプルを記載します。

 

// およそ 15 分前に検知しています。

StatusCode : 200

StatusDescription : OK

Content : {"DocumentIncarnation":10,"Events":[{"EventId":"9C7442D3-9206-45D8-8DA8-26A94E577C51","EventStatus"

:"Scheduled","EventType":"Freeze","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotB

ef...

RawContent : HTTP/1.1 200 OK

x-ms-package-infosource: ProcessRequestFromPAAgent

Content-Length: 239

Content-Type: application/json

Date: Thu, 12 Oct 2017 14:45:56 GMT

ETag: 436105654349333084

Server: Microso...

Forms : {}

Headers : {[x-ms-package-infosource, ProcessRequestFromPAAgent], [Content-Length, 239], [Content-Type,

application/json], [Date, Thu, 12 Oct 2017 14:45:56 GMT]...}

Images : {}

InputFields : {}

Links : {}

ParsedHtml : System.__ComObject

RawContentLength : 239

{"DocumentIncarnation":10,"Events":[{"EventId":"9C7442D3-9206-45D8-8DA8-26A94E577C51","EventStatus":"Scheduled","EventType":"Freeze","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBefore":"Thu, 12 Oct 2017 14:59:54 GMT"}]}

 

// その後、"Scheduled" から "Started" に変化

StatusCode : 200

StatusDescription : OK

Content : {"DocumentIncarnation":11,"Events":[{"EventId":"9C7442D3-9206-45D8-8DA8-26A94E577C51","EventStatus"

:"Started","EventType":"Freeze","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBef

or...

RawContent : HTTP/1.1 200 OK

x-ms-package-infosource: ProcessRequestFromPAAgent

Content-Length: 208

Content-Type: application/json

Date: Thu, 12 Oct 2017 15:00:59 GMT

ETag: 3582917624938094783

Server: Micros...

Forms : {}

Headers : {[x-ms-package-infosource, ProcessRequestFromPAAgent], [Content-Length, 208], [Content-Type,

application/json], [Date, Thu, 12 Oct 2017 15:00:59 GMT]...}

Images : {}

InputFields : {}

Links : {}

ParsedHtml : System.__ComObject

RawContentLength : 208

{"DocumentIncarnation":11,"Events":[{"EventId":"9C7442D3-9206-45D8-8DA8-26A94E577C51","EventStatus":"Started","EventType":"Freeze","ResourceType":"VirtualMachine","Resources":["_tidv2promo"],"NotBefore":""}]}