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) 中创建虚拟机,可从不可路由 IP169.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 eventsfunctionGetScheduledEvents($uri){$scheduledEvents=Invoke-RestMethod-Headers@{"Metadata"="true"}-URI$uri-Methodget$json=ConvertTo-Json$scheduledEventsWrite-Host"Received following events: `n"$jsonreturn$scheduledEvents}# How to approve a scheduled eventfunctionApproveScheduledEvent($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$scheduledEventsApprovalWrite-Host"Approving with the following: `n"$approvalString# Post approval string to scheduled events endpointInvoke-RestMethod-Uri$uri-Headers@{"Metadata"="true"}-MethodPOST-Body$approvalString}functionHandleScheduledEvents($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 serviceHandleScheduledEvents$scheduledEvents# Approve events when ready (optional)foreach($eventin$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#复制

publicclassScheduledEventsClient{privatereadonlystringscheduledEventsEndpoint;privatereadonlystringdefaultIpAddress ="169.254.169.254";// Set up the scheduled events URI for a VNET-enabled VMpublicScheduledEventsClient(){        scheduledEventsEndpoint =string.Format("http://{0}/metadata/scheduledevents?api-version=2017-03-01", defaultIpAddress);    }// Get eventspublicstringGetScheduledEvents(){        Uri cloudControlUri =newUri(scheduledEventsEndpoint);using(varwebClient =newWebClient())        {            webClient.Headers.Add("Metadata","true");returnwebClient.DownloadString(cloudControlUri);        }      }// Approve eventspublicvoidApproveScheduledEvents(stringjsonPost){using(varwebClient =newWebClient())        {            webClient.Headers.Add("Content-Type","application/json");            webClient.UploadString(scheduledEventsEndpoint, jsonPost);        }    }}

无法使用以下数据结构表示计划事件:

C#复制

publicclassScheduledEventsDocument{publicstringDocumentIncarnation;publicList Events {get;set; }}publicclassCloudControlEvent{publicstringEventId {get;set; }publicstringEventStatus {get;set; }publicstringEventType {get;set; }publicstringResourceType {get;set; }publicList Resources {get;set; }publicDateTime? NotBefore {get;set; }}publicclassScheduledEventsApproval{publicstringDocumentIncarnation;publicList StartRequests =newList();}publicclassStartRequest{    [JsonProperty("EventId")]privatestringeventId;publicStartRequest(stringeventId){this.eventId = eventId;    }}

下例将查询计划事件的元数据服务器并审核所有未完成的事件。

C#复制

publicclassProgram{staticScheduledEventsClient client;staticvoidMain(string[] args){        client =newScheduledEventsClient();while(true)        {stringjson = client.GetDocument();            ScheduledEventsDocument scheduledEventsDocument = JsonConvert.DeserializeObject(json);            HandleEvents(scheduledEventsDocument.Events);// Wait for user responseConsole.WriteLine("Press Enter to approve executing events\n");            Console.ReadLine();// Approve eventsScheduledEventsApproval scheduledEventsApprovalDocument =newScheduledEventsApproval()            {                DocumentIncarnation = scheduledEventsDocument.DocumentIncarnation            };foreach(CloudControlEventeventinscheduledEventsDocument.Events)            {                scheduledEventsApprovalDocument.StartRequests.Add(newStartRequest(event.EventId));            }if(scheduledEventsApprovalDocument.StartRequests.Count >0)            {// Serialize using Newtonsoft.JsonstringapproveEventsJsonDocument =                    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();        }    }privatestaticvoidHandleEvents(List events){// Add logic for handling events here}}

Python 示例

下例将查询计划事件的元数据服务器并审核所有未完成的事件。

Python复制

#!/usr/bin/pythonimportjsonimporturllib2importsocketimportsysmetadata_url ="http://169.254.169.254/metadata/scheduledevents?api-version=2017-03-01"headers ="{Metadata:true}"this_host = socket.gethostname()defget_scheduled_events():req = urllib2.Request(metadata_url)  req.add_header('Metadata','true')  resp = urllib2.urlopen(req)  data = json.loads(resp.read())returndatadefhandle_scheduled_events(data):forevtindata['Events']:        eventid = evt['EventId']        status = evt['EventStatus']        resources = evt['Resources']        eventtype = evt['EventType']        resourcetype = evt['ResourceType']        notbefore = evt['NotBefore'].replace(" ","_")ifthis_hostinresources:print"+ Scheduled Event. This host is scheduled for "+ eventype +" not before "+ notbefore# Add logic for handling events heredefmain():data = get_scheduled_events()  handle_scheduled_events(data)if__name__ =='__main__':  main()  sys.exit(0)

后续步骤

有关 API 的更多信息,请参阅实例元数据服务

了解Azure 中 Windows 虚拟机的计划内维护。立即访问http://market.azure.cn

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容