Azure 中繼資料服務:Linux VM 的已排定事件
適用於:✔️ Linux VM ✔️ 彈性擴展集 ✔️ 統一擴展集
已排定的事件是一項「Azure 中繼資料服務」,可讓您的應用程式有時間準備虛擬機器維護。 它提供即將進行維護事件 (例如重新啟動) 的相關資訊,讓您的應用程式可進行準備以及限制中斷。 它適用於所有 Azure 虛擬機器類型 (包括 Windows 和 Linux 上的 PaaS 和 IaaS)。
如需 Windows 上已排定事件的資訊,請參閱 Windows VM 的已排定事件。
已排定事件可針對近期活動發出主動式通知。有關已發生事件的回應式資訊,請參閱 Azure Resource Graph 中的 VM 可用性資訊,以及為 Azure 虛擬機器建立可用性警示規則。
注意
已排定事件已在所有 Azure 區域中正式推出。 請參閱版本和區域可用性以取得最新的版本資訊。
為什麼要使用已排定事件?
許多應用程式可受益於 VM 維護的準備時間。 這些時間可用來執行應用程式特定的工作,能改善可用性、可靠性與服務性,包括:
- 檢查點和還原。
- 清空連線。
- 主要複本容錯移轉。
- 從負載平衡器移除集區。
- 事件記錄。
- 順利關機。
使用已排定事件,應用程式就可以探索維護所發生的時間,以及限制其影響的觸發工作。
排程的事件會提供下列使用案例中的事件:
- 平台起始的維護 (例如,主機的 VM 重新啟動、即時移轉或記憶體保留更新)。
- 虛擬機器正於預期即將失敗的降級主機硬體 (英文) 上執行。
- 虛擬機器在發生硬體失敗的主機上執行。
- 使用者起始的維護 (例如,使用者重新啟動或重新部署 VM)。
- 現成 VM 和現成擴展集執行個體收回。
基本概念
如果您是使用可由 VM 內存取的 REST 端點來執行 VM,中繼資料服務會公開這類相關資訊。 這項資訊是透過無法路由傳送的 IP 所取得,且不會在 VM 之外公開。
範圍
已排定事件會傳送到下列目標,並由其進行認可:
- 獨立虛擬機器。
- Azure 雲端服務 (傳統) 中的所有 VM。
- 可用性設定組中的所有 VM。
- 擴展集放置群組中的所有 VM。
在整個可用性設定組,或虛擬機器擴展集的放置群組中,不論可用性區域的使用方式,所有虛擬機器 (VM) 的已排定事件都會傳送至相同群組或集合中的所有其他 VM。
因此,請檢查事件中的 Resources
欄位以找出哪些 VM 受到影響。
注意
使用 1 個容錯網域 (FD = 1) 的擴展集中的 GPU 加速虛擬機器只會接收受影響資源的排定事件。 事件不會傳播到相同位置群組中的所有 VM。
端點探索
針對已啟用 VNET 的 VM,可以從靜態非可路由 IP 169.254.169.254
取得「中繼資料服務」。 最新版已排定事件的完整端點為:
http://169.254.169.254/metadata/scheduledevents?api-version=2020-07-01
如果 VM 不是建立在虛擬網路內 (雲端服務和傳統 VM 的預設案例),就需要額外的邏輯,才能探索要使用的 IP 位址。 請參閱此範例以了解如何探索主機端點 \(英文\)。
版本和區域可用性
已排定事件服務已進行版本設定。 版本是必要項目;目前版本為 2020-07-01
。
版本 | 版本類型 | 地區 | 版本資訊 |
---|---|---|---|
2020-07-01 | 正式發行 | 全部 | |
2019-08-01 | 正式發行 | 全部 | |
2019-04-01 | 正式發行 | 全部 | |
2019-01-01 | 正式發行 | 全部 | |
2017-11-01 | 正式發行 | 全部 | |
2017 年 8 月 1 日 | 正式發行 | 全部 | |
2017-03-01 | 預覽 | 全部 |
注意
先前排定事件的預覽版支援作為 API 版本的 {latest}。 此格式將不再受到支援且之後會遭到取代。
啟用和停用已排定事件
系統會在您第一次提出事件要求時,為您的服務啟用「已排定事件」。 您應該會在第一次呼叫多達兩分鐘時遇到延遲的回應,而您會在 5 分鐘內開始接收事件。 如果長達 24 小時未向端點提出要求,服務就會停用已排定事件。
使用者起始的維護
使用者透過 Azure 入口網站、API、CLI 或 PowerShell 起始的 VM 維護,將會產生「已排定事件」。 這可讓您測試應用程式中的維護準備邏輯,讓應用程式可以為使用者起始的維護預作準備。
如果您重新啟動 VM,則會排定類型為 Reboot
的事件。 如果您重新部署 VM,則會排定類型為 Redeploy
的事件。 一般而言,可以立即核准具有使用者事件來源的事件,以避免延遲使用者起始的動作。 建議以主要與次要 VM 進行通訊,並核准使用者產生的已排定事件,避免主要 VM 沒有回應。 藉由立即核准事件,可防止在應用程式復原過程中出現延遲。
只有適用於支援記憶體保留更新的一般用途 VM 大小,才支援 虛擬機器擴展集客體 OS 升級或重新安裝映像的已排定事件。 但不適用於 G、M、N 和 H 系列。 根據預設,虛擬機器擴展集客體 OS 升級或重新安裝映像的已排定事件會處於停用狀態。 若要在支援的 VM 大小上為這些作業啟用已排定事件,請先使用 OSImageNotificationProfile 加以啟用。
使用 API
高階概述
處理已排定事件時,可使用準備與復原兩個主要元件。 所有影響 VM 的目前已排定事件,都能透過 IMDS 已排定事件端點進行讀取。 事件到達終止狀態時,就會從事件清單中移除。 下圖說明了單一已排定事件可能經歷的各種狀態轉換:
針對 EventStatus 為「已排程」狀態的事件,必須執行相關步驟以準備工作負載。 準備完成後,應使用已排定事件 API 來核准事件。 否則,一旦到達 NotBefore 時間,即會自動核准事件。 如果 VM 位於共用基礎結構上,系統則會等待相同硬體上的所有其他租用戶也核准作業或逾時。 一旦已從所有受影響的 VM 收集到核准,或已到達 NotBefore 時間,Azure 就會產生 EventStatus 為「已啟動」狀態的已排定事件承載,並觸發維護事件。 事件到達終止狀態時,就會從事件清單中移除。 這可做為客戶復原其 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 為「已啟動」狀態的事件),便不會再產生影響
- Azure 會監視整個機群的維護作業,並在極少數情況下,因認為維護作業的風險太高而判斷無法套用。 在此情況下,已排定事件將會直接由「已排程」狀態,轉而從事件陣列中移除
- 若發生硬體失敗,Azure 會略過「已排程」狀態,並立即將 EventStatus 改為「已啟動」狀態。
- 雖然事件仍處於 EventStatus 為「已啟動」的狀態,也可能會因持續時間比已排定事件中公告的還短,而產生其他影響。
不同容錯網域的 VM 不會同時受到例行維護作業的影響,以保障 Azure 的可用性。 然而,作業可一個接一個連續執行。 一個容錯網域中的 VM 可以在另一個容錯網域維護完成後,立即接收 EventStatus 為「已排程」的已排定事件。 無論選擇何種結構,請始終檢查 VM 是否有待處理的新事件。
雖然事件發生的具體時間各不相同,但可根據下圖提供的粗略指導方針,了解典型維護作業如何是如何進行:
- 從 EventStatus「已排程」到「核准逾時」:15 分鐘
- 影響持續時間:7 秒
- 從 EventStatus「已啟動」到「已完成」(事件從事件陣列中移除):10 分鐘
標頭
查詢中繼資料服務時,您必須提供 Metadata:true
標頭以免不小心重新導向要求。 所有排程的事件都需要 Metadata:true
標頭。 要求中未包含標頭會導致中繼資料服務「不正確的要求」回應。
查詢事件
您只要進行下列呼叫,即可查詢已排定事件:
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},
}
]
}
事件屬性
屬性 | 說明 |
---|---|
文件內建 | 當事件陣列變更時增加的整數。 具有相同內建的文件包含相同的事件資訊,而且當事件變更時,將會遞增內建。 |
EventId | 此事件的全域唯一識別碼。 範例:
|
EventType | 此事件造成的影響。 值:
|
ResourceType | 受此事件影響的資源類型。 值:
|
資源 | 受此事件影響的資源清單。 範例:
|
EventStatus | 此事件的狀態。 值:
Completed 或類似的狀態。 當事件完成時,不會再傳回事件。 |
NotBefore | 自此之後可啟動此事件的時間。 事件保證不會在此時間之前啟動。 如果事件已經啟動,則為空白 範例:
|
描述 | 此事件的描述。 範例:
|
EventSource | 事件啟動器。 範例:
|
DurationInSeconds | 事件所造成的中斷預期持續時間。 在影響期間,可能有較短持續時間的次要影響。 範例:
|
事件排定
系統會根據事件類型,為每個事件在未來安排最少的時間量。 事件的 NotBefore
屬性會反映這個時間。
EventType | 最短時間通知 |
---|---|
凍結 | 15 分鐘 |
重新啟動 | 15 分鐘 |
重新部署 | 10 分鐘 |
終止 | 使用者可設定:5 至 15 分鐘 |
這表示在事件發生前的最短通知時間內,您能夠偵測到事件的未來排程。 事件已排定後,會在通過核准或 NotBefore
時間後進入 Started
狀態。 然而,在極少數情況下,Azure 會在作業啟動前取消作業。 在這類情況下,事件會從事件陣列中移除,影響也不會如期發生。
注意
在某些情況下,Azure 能夠預測主機因為硬體效能下降而失敗,並嘗試排定移轉來減輕服務中斷的影響。 受影響的虛擬機器會收到含有 NotBefore
(通常是未來幾天) 的已排定事件。 實際時間依預測的失敗風險評量而有所不同。 Azure 會盡可能提前 7 天通知,但實際時間並不一定,如果預期硬體很可能即將失敗,則時間可能更短。 若要將您服務的風險降至最低,以防萬一硬體在系統起始移轉之前失敗,我們建議您盡快重新部署虛擬機器。
注意
如果主機節點遇到硬體失敗,Azure 將會略過最低通知期間,立即開始進行受影響虛擬機器的復原流程。 這可減少受影響 VM 無法回應時的復原時間。 在復原流程中,將會針對所有受影響且具有 EventType = Reboot
和 EventStatus = Started
的 VM 建立事件。
輪詢頻率
您可以自行決定輪詢端點更新的頻率。 然而,要求間隔時間越久,您可能會花更多時間回應即將發生的事件。 大部分事件都有 5 到 15 分鐘的事先通知,但在某些情況下,預先通知可能不到 30 秒。 為確保盡可能有較多時間採取緩和動作,建議您每秒輪詢一次服務。
啟動事件
在您得知即將發生的事件,並完成正常關機邏輯之後,即可使用 EventId
向中繼資料服務進行 POST
呼叫,以核准未處理的事件。 對 Azure 來說,此呼叫可以將通知時間縮到最短 (可能的話)。 在核准時,事件可能不會立即啟動,在某些情況下,Azure 會要求核准節點上託管的所有 VM,再繼續處理事件。
以下是 POST
要求本文中必須要有的 JSON 範例。 要求需包含 StartRequests
清單。 每個 StartRequest
都包含您需要加速之事件的 EventId
:
{
"StartRequests" : [
{
"EventId": {EventId}
}
]
}
如果服務傳遞了有效的事件識別碼,則即使另一個 VM 已核准事件,也一律會傳回 200 成功碼。 400 錯誤碼表示要求標頭或酬載的格式錯誤。
注意
除非是透過 POST 訊息核准,或已過了 NotBefore 時間,否則事件不會繼續。 這包括使用者觸發的事件,例如從 Azure 入口網站重新啟動 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
注意
認可事件時,即會允許事件中所有 Resources
的事件繼續進行,而不僅是認可此事件 VM。 因此,您可以選擇一個領導者來協調認可;最簡單的方法是選擇 Resources
欄位的第一部機器。
範例回應
以下事件範例說明了即時移轉至另一個節點的兩部 VM 所看到的內容。
每當 Events
中有新的資訊時,DocumentIncarnation
就會變動。 事件的核准可讓 WestNO_0 和 WestNO_1 的凍結繼續。 DurationInSeconds
為 -1,表示平台不知道作業需時多久。
{
"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()
下一步
- 在 Azure 執行個體中繼資料已排定事件 GitHub 存放庫 \(英文\) 中檢閱排程的事件程式碼範例。
- 檢閱 Azure 範例 GitHub 存放庫中的 Node.js 已排定事件程式碼範例。
- 深入了解執行個體中繼資料服務中提供的 API。
- 了解 Azure 中 Linux 虛擬機器預定進行的維修。
- 瞭解如何在 Azure 範例 GitHub存放庫中,使用 Azure 事件中樞來記錄已排定事件。