计划事件是 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