1. 程式人生 > >Azure 元資料服務:適用於 Windows VM 的計劃事件(預覽)

Azure 元資料服務:適用於 Windows VM 的計劃事件(預覽)

計劃事件是 Azure 元資料服務中的其中一個子服務。 它負責顯示有關即將發生的事件(例如,重新啟動)的資訊,使應用程式可以為其做準備並限制中斷。 它可用於所有 Azure 虛擬機器型別(包括 PaaS 和 IaaS)。 計劃事件為虛擬機器提供了執行預防性任務的時間,將事件的影響降到最低。

計劃事件可用於 Linux 和 Windows VM。 有關 Linux 上的計劃事件的資訊,請參閱適用於 Linux VM 的計劃事件

為何使用計劃事件?

通過計劃事件,可以採取措施限制由平臺啟動的維護或由使用者啟動的操作對服務帶來的影響。

使用複製技術保持狀態的多例項工作負荷可能易受到跨多個例項頻繁發生的服務中斷的影響。 此類中斷可能導致任務開銷昂貴(例如,重新生成索引)甚至副本丟失。

在很多其他情況下,通過正常關閉序列(如完成或取消正在進行的事務)、將任務重新分配給群集中的其他 VM(手動故障轉移)或從網路負載均衡器池中刪除虛擬機器,可能都可提高服務的整體可用性。

有時通知管理員即將發生的事件或記錄此類事件也可幫助提高在雲中託管的應用程式的可服務性。

Azure 元資料服務在以下用例中顯示計劃事件:

  • 平臺啟動的維護(例如,主機 OS 部署)
  • 使用者啟動的呼叫(例如,使用者重啟或重新部署 VM)

基礎知識

Azure 元資料服務公開在 VM 中使用可訪問的 REST 終結點執行虛擬機器的相關資訊。 該資訊通過不可路由的 IP 提供,因此不會在 VM 外部公開。

範圍

計劃事件會顯示到雲服務中的所有虛擬機器或可用性集中的所有虛擬機器上。 因此,應檢視事件中的 Resources 欄位以確定將受到影響的 VM。

發現終結點

如果在虛擬網路 (VNet) 中建立虛擬機器,可從不可路由 IP 169.254.169.254 獲得元資料服務。 如果不在虛擬網路中建立虛擬機器(雲服務和經典 VM 的預設情況),需要使用其他邏輯發現可使用的終結點。 請參閱此示例,瞭解如何發現主機終結點

版本控制

已對例項元資料服務進行了版本控制。 版本是必需的,當前版本為 2017-03-01

Note

支援的計劃事件的前一預覽版 {latest} 釋出為 api-version。 此格式不再受支援,並且將在未來棄用。

使用標頭

查詢元資料服務時,必須提供標頭 Metadata: true 以確保不會在無意中重定向該請求。

啟用計劃事件

首次請求計劃事件時,Azure 會在虛擬機器上隱式啟用該功能。 因此,第一次呼叫時應該會延遲響應最多兩分鐘。

使用者啟動的維護

使用者通過 Azure 門戶、API、CLI 或 PowerShell 啟動的虛擬機器維護會生成計劃事件。 這樣便可以在應用程式中測試維護準備邏輯,並可以通過應用程式準備使用者啟動的維護。

重啟虛擬機器會計劃 Reboot 型別的事件。 重新部署虛擬機器會計劃 Redeploy 型別的事件。

Note

目前,可以同時計劃最多 10 個使用者啟動的維護操作。 在計劃事件公開發布之前將放寬此限制。

Note

目前,生成計劃事件的使用者啟動的維護不可配置。 可配置性已計劃在將來的版本中推出。

使用 API

查詢事件

只需進行以下呼叫即可查詢計劃事件:

curl -H Metadata:true http://169.254.169.254/metadata/scheduledevents?api-version=2017-03-01

響應包含計劃事件的陣列。 陣列為空意味著目前沒有計劃事件。 如果有計劃事件,響應會包含事件的陣列:

{
    "DocumentIncarnation": {IncarnationID},
    "Events": [
        {
            "EventId": {eventID},
            "EventType": "Reboot" | "Redeploy" | "Freeze",
            "ResourceType": "VirtualMachine",
            "Resources": [{resourceName}],
            "EventStatus": "Scheduled" | "Started",
            "NotBefore": {timeInUTC},              
        }
    ]
}

事件屬性

屬性 說明
EventId 此事件的全域性唯一識別符號。 

示例: 
  • 602d9444-d2cd-49c7-8624-8643e7171297
EventType 此事件造成的影響。 

值: 
  • Freeze:虛擬機器計劃暫停數秒。 暫停 CPU,但不會對記憶體、開啟檔案或網路連線造成影響。
  • Reboot:虛擬機器將計劃重新啟動(非永續性記憶體將丟失)。
  • Redeploy:虛擬機器計劃移到另一個節點(臨時磁碟將丟失)。
ResourceType 此事件影響的資源的型別。 

值:
  • VirtualMachine
資源 此事件影響的資源的列表。 它保證最多隻能包含一個更新域的計算機,但可能不包含該更新域中的所有計算機。 

示例: 
  • ["FrontEnd_IN_0", "BackEnd_IN_0"]
事件狀態 此事件的狀態。 

值:
  • Scheduled:此事件計劃在 NotBefore 屬性指定的時間之後啟動。
  • Started:此事件已啟動。
不提供 Completed 或類似狀態;事件完成後,將不再返回事件。
NotBefore 此事件可能會在之後啟動的時間。 

示例: 
  • 2016-09-19T18:29:47Z

事件計劃

將根據事件型別為每個事件計劃將來的最小量時間。 此時間反映在某個事件的 NotBefore 屬性上。

EventType 最小值通知
凍結 15 分鐘
重新啟動 15 分鐘
重新部署 10 分鐘

啟動事件

瞭解即將發生的事件並完成正常關閉邏輯後,可以通過使用 EventId 對元資料服務進行 POST 呼叫來批准未完成的事件。 這指示 Azure 可以縮短最小通知時間(如可能)。

curl -H Metadata:true -X POST -d '{"DocumentIncarnation":"5", "StartRequests": [{"EventId": "f020ba2e-3bc0-4c40-a10b-86575a9eabd5"}]}' http://169.254.169.254/metadata/scheduledevents?api-version=2017-03-01

Note

確認事件後,即可允許事件針對事件中所有的 Resources 繼續進行,而不僅僅是確認該事件的虛擬機器。 因此,可以選擇一個指揮計算機來協調該確認,為簡單起見,可選擇 Resources 欄位中的第一個計算機。

PowerShell 示例

下例將查詢計劃事件的元資料伺服器並稽核所有未完成的事件。

PowerShell
# How to get scheduled events 
function GetScheduledEvents($uri)
{
    $scheduledEvents = Invoke-RestMethod -Headers @{"Metadata"="true"} -URI $uri -Method get
    $json = ConvertTo-Json $scheduledEvents
    Write-Host "Received following events: `n" $json
    return $scheduledEvents
}

# How to approve a scheduled event
function ApproveScheduledEvent($eventId, $docIncarnation, $uri)
{    
    # Create the Scheduled Events Approval Document
    $startRequests = [array]@{"EventId" = $eventId}
    $scheduledEventsApproval = @{"StartRequests" = $startRequests; "DocumentIncarnation" = $docIncarnation} 

    # Convert to JSON string
    $approvalString = ConvertTo-Json $scheduledEventsApproval

    Write-Host "Approving with the following: `n" $approvalString

    # Post approval string to scheduled events endpoint
    Invoke-RestMethod -Uri $uri -Headers @{"Metadata"="true"} -Method POST -Body $approvalString
}

function HandleScheduledEvents($scheduledEvents)
{
    # Add logic for handling events here
}

######### Sample Scheduled Events Interaction #########

# Set up the scheduled events URI for a VNET-enabled VM
$localHostIP = "169.254.169.254"
$scheduledEventURI = 'http://{0}/metadata/scheduledevents?api-version=2017-03-01' -f $localHostIP 

# Get events
$scheduledEvents = GetScheduledEvents $scheduledEventURI

# Handle events however is best for your service
HandleScheduledEvents $scheduledEvents

# Approve events when ready (optional)
foreach($event in $scheduledEvents.Events)
{
    Write-Host "Current Event: `n" $event
    $entry = Read-Host "`nApprove event? Y/N"
    if($entry -eq "Y" -or $entry -eq "y")
    {
        ApproveScheduledEvent $event.EventId $scheduledEvents.DocumentIncarnation $scheduledEventURI 
    }
}

C# 示例

下例是關於與元資料服務進行通訊的簡單客戶端。

C#
public class ScheduledEventsClient
{
    private readonly string scheduledEventsEndpoint;
    private readonly string defaultIpAddress = "169.254.169.254"; 

    // Set up the scheduled events URI for a VNET-enabled VM
    public ScheduledEventsClient()
    {
        scheduledEventsEndpoint = string.Format("http://{0}/metadata/scheduledevents?api-version=2017-03-01", defaultIpAddress);
    }

    // Get events
    public string GetScheduledEvents()
    {
        Uri cloudControlUri = new Uri(scheduledEventsEndpoint);
        using (var webClient = new WebClient())
        {
            webClient.Headers.Add("Metadata", "true");
            return webClient.DownloadString(cloudControlUri);
        }   
    }

    // Approve events
    public void ApproveScheduledEvents(string jsonPost)
    {
        using (var webClient = new WebClient())
        {
            webClient.Headers.Add("Content-Type", "application/json");
            webClient.UploadString(scheduledEventsEndpoint, jsonPost);
        }
    }
}

無法使用以下資料結構表示計劃事件:

C#
public class ScheduledEventsDocument
{
    public string DocumentIncarnation;
    public List<CloudControlEvent> Events { get; set; }
}

public class CloudControlEvent
{
    public string EventId { get; set; }
    public string EventStatus { get; set; }
    public string EventType { get; set; }
    public string ResourceType { get; set; }
    public List<string> Resources { get; set; }
    public DateTime? NotBefore { get; set; }
}

public class ScheduledEventsApproval
{
    public string DocumentIncarnation;
    public List<StartRequest> StartRequests = new List<StartRequest>();
}

public class StartRequest
{
    [JsonProperty("EventId")]
    private string eventId;

    public StartRequest(string eventId)
    {
        this.eventId = eventId;
    }
}

下例將查詢計劃事件的元資料伺服器並稽核所有未完成的事件。

C#
public class Program
{
    static ScheduledEventsClient client;

    static void Main(string[] args)
    {
        client = new ScheduledEventsClient();

        while (true)
        {
            string json = client.GetDocument();
            ScheduledEventsDocument scheduledEventsDocument = JsonConvert.DeserializeObject<ScheduledEventsDocument>(json);

            HandleEvents(scheduledEventsDocument.Events);

            // Wait for user response
            Console.WriteLine("Press Enter to approve executing events\n");
            Console.ReadLine();

            // Approve events
            ScheduledEventsApproval scheduledEventsApprovalDocument = new ScheduledEventsApproval()
            {
                DocumentIncarnation = scheduledEventsDocument.DocumentIncarnation
            };

            foreach (CloudControlEvent event in scheduledEventsDocument.Events)
            {
                scheduledEventsApprovalDocument.StartRequests.Add(new StartRequest(event.EventId));
            }

            if (scheduledEventsApprovalDocument.StartRequests.Count > 0)
            {
                // Serialize using Newtonsoft.Json
                string approveEventsJsonDocument =
                    JsonConvert.SerializeObject(scheduledEventsApprovalDocument);

                Console.WriteLine($"Approving events with json: {approveEventsJsonDocument}\n");
                client.ApproveScheduledEvents(approveEventsJsonDocument);
            }

            Console.WriteLine("Complete. Press enter to repeat\n\n");
            Console.ReadLine();
            Console.Clear();
        }
    }

    private static void HandleEvents(List<CloudControlEvent> events)
    {
        // Add logic for handling events here
    }
}

Python 示例

下例將查詢計劃事件的元資料伺服器並稽核所有未完成的事件。

Python
#!/usr/bin/python

import json
import urllib2
import socket
import sys

metadata_url = "http://169.254.169.254/metadata/scheduledevents?api-version=2017-03-01"
headers = "{Metadata:true}"
this_host = socket.gethostname()

def get_scheduled_events():
   req = urllib2.Request(metadata_url)
   req.add_header('Metadata', 'true')
   resp = urllib2.urlopen(req)
   data = json.loads(resp.read())
   return data

def handle_scheduled_events(data):
    for evt in data['Events']:
        eventid = evt['EventId']
        status = evt['EventStatus']
        resources = evt['Resources']
        eventtype = evt['EventType']
        resourcetype = evt['ResourceType']
        notbefore = evt['NotBefore'].replace(" ","_")
        if this_host in resources:
            print "+ Scheduled Event. This host is scheduled for " + eventype + " not before " + notbefore
            # Add logic for handling events here

def main():
   data = get_scheduled_events()
   handle_scheduled_events(data)

if __name__ == '__main__':
  main()
  sys.exit(0)

後續步驟

立即訪問http://market.azure.cn