分享方式:


取得資源變更

資源會在每日使用、重新設定,甚至重新部署的過程中進行變更。 大部分的變更都是根據設計,但有時則不會。 您可以:

  • 了解何時在 Azure Resource Manager 屬性上偵測到變更。
  • 檢視屬性變更詳細資料。
  • 大規模查詢跨訂用帳戶、管理群組或租用戶變更。

在本文章中,您將了解:

  • 承載 JSON 的外觀。
  • 如何使用 CLI、PowerShell 或 Azure 入口網站,透過 Resource Graph 查詢資源變更。
  • 查詢資源變更的查詢範例和最佳做法。
  • 變更分析會使用「變更執行者」功能:
    • changedBy:資源變更的起始者,例如應用程式識別碼或已授權人員的電子郵件地址。
    • clientType:進行變更的用戶端,例如 Azure 入口網站
    • operation:呼叫的作業 (部分機器翻譯),例如 Microsoft.Compute/virtualmachines/write

必要條件

  • 若要啟用 Azure PowerShell 來查詢 Azure Resource Graph,新增模組
  • 若要讓 Azure CLI 可查詢 Azure Resource Graph,新增延伸模組

了解變更事件屬性

建立、更新或刪除資源時,系統會建立新的變更資源 (Microsoft.Resources/changes) 來擴充修改的資源,並代表變更的屬性。 應會在五分鐘內提供變更記錄。 下列範例 JSON 承載示範變更資源屬性:

{
  "targetResourceId": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/myResourceGroup/providers/microsoft.compute/virtualmachines/myVM",
  "targetResourceType": "microsoft.compute/virtualmachines",
  "changeType": "Update",
  "changeAttributes": {
    "previousResourceSnapshotId": "11111111111111111111_22222222-3333-aaaa-bbbb-444444444444_5555555555_6666666666",
    "newResourceSnapshotId": "33333333333333333333_44444444-5555-ffff-gggg-666666666666_7777777777_8888888888",
    "correlationId": "11111111-1111-1111-1111-111111111111",
    "changedByType": "User",
    "changesCount": 2,
    "clientType": "Azure Portal",
    "changedBy": "john@contoso.com",
    "operation": "microsoft.compute/virtualmachines/write",
    "timestamp": "2024-06-12T13:26:17.347+00:00"
  },
  "changes": {
    "properties.provisioningState": {
      "newValue": "Succeeded",
      "previousValue": "Updating",
      "changeCategory": "System",
      "propertyChangeType": "Update",
      "isTruncated": "true"
    },
    "tags.key1": {
      "newValue": "NewTagValue",
      "previousValue": "null",
      "changeCategory": "User",
      "propertyChangeType": "Insert"
    }
  }
}

請參閱變更資源屬性的完整參考指南 (部分機器翻譯)。

執行查詢

試用 resourcechanges 資料表的租用戶型 Resource Graph 查詢。 此查詢會傳回前五個最新的 Azure 資源變更,其中包含變更時間、變更類型、目標資源識別碼、目標資源類型,以及每個變更記錄的變更詳細資料。

# Login first with az login if not using Cloud Shell

# Run Azure Resource Graph query
az graph query -q 'resourcechanges | project properties.changeAttributes.timestamp, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | limit 5'

您可以更新此查詢,為 timestamp 屬性指定使用者更容易理解的資料行名稱。

# Run Azure Resource Graph query with 'extend'
az graph query -q 'resourcechanges | extend changeTime=todatetime(properties.changeAttributes.timestamp) | project changeTime, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | limit 5'

若要將查詢結果限制為最近的變更,請將查詢更新為 order by 並搭配使用者定義的 changeTime 屬性。

# Run Azure Resource Graph query with 'order by'
az graph query -q 'resourcechanges | extend changeTime=todatetime(properties.changeAttributes.timestamp) | project changeTime, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | order by changeTime desc | limit 5'

您也可以使用 -ManagementGroup-Subscription 參數,分別依管理群組 (部分機器翻譯) 或訂用帳戶進行查詢。

注意

如果查詢未從您可存取的訂用帳戶傳回結果,則 Search-AzGraphPowerShell Cmdlet 是為預設內容中的訂用帳戶所預設。

Resource Graph Explorer 也提供了全新介面,供您將某些查詢的結果轉換成可釘選到 Azure 儀表板的圖表。

查詢資源變更

透過 Resource Graph,您可以查詢 resourcechangesresourcecontainerchangeshealthresourcechanges 資料表,以依任何變更資源屬性進行篩選或排序。 下列範例會查詢 resourcechanges 資料表,但也可以套用至 resourcecontainerchangeshealthresourcechanges 資料表。

注意

若想深入了解 healthresourcechanges 資料,請參閱專案 Flash 文件 (部分機器翻譯)。

範例

在查詢和分析資源中的變更之前,請先檢閱下列最佳做法。

  • 在特定時間範圍內查詢變更事件,並評估變更詳細資料。
    • 此查詢最適合在事件管理期間用來了解可能相關的變更。
  • 將組態管理資料庫 (CMDB) 保持最新狀態。
    • 不要以排程的頻率重新整理所有資源及其完整的屬性集,改為只接收變更的內容。
  • 了解當資源變更合規性狀態時,其他哪些屬性已變更。
    • 藉由評估這些額外的屬性,可深入解析其他可能需要透過 Azure 原則定義來管理的屬性。
  • 查詢命令的順序很重要。 在下列範例中,order by 必須位於 limit 命令之前。
    • order by 命令會依變更時間排序查詢結果。
    • limit 命令接著會限制已排序的結果,以確保您得到五個最新的結果。
  • Unknown 是什麼意思? 
    • 當變更發生在無法辨識的用戶端上時,便會顯示 Unknown。 用戶端的識別是根據與原始變更要求相關聯的使用者代理程式和用戶端應用程式識別碼。
  • System 是什麼意思?
    • 當背景變更發生與任何直接使用者動作無關時,changedBy 值便會顯示為 System。

過去 24 小時期間的所有變更

resourcechanges
| extend changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId),
changeType = tostring(properties.changeType), correlationId = properties.changeAttributes.correlationId, 
changedProperties = properties.changes, changeCount = properties.changeAttributes.changesCount
| where changeTime > ago(1d)
| order by changeTime desc
| project changeTime, targetResourceId, changeType, correlationId, changeCount, changedProperties

在特定資源群組中刪除的資源

resourcechanges
| where resourceGroup == "myResourceGroup"
| extend changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId),
  changeType = tostring(properties.changeType), correlationId = properties.changeAttributes.correlationId
| where changeType == "Delete"
| order by changeTime desc
| project changeTime, resourceGroup, targetResourceId, changeType, correlationId

特定屬性值的變更

resourcechanges
| extend provisioningStateChange = properties.changes["properties.provisioningState"], changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType)
| where isnotempty(provisioningStateChange)and provisioningStateChange.newValue == "Succeeded"
| order by changeTime desc
| project changeTime, targetResourceId, changeType, provisioningStateChange.previousValue, provisioningStateChange.newValue

過去七天內的變更,依變更者、用戶端以及計數排序

resourcechanges 
| extend changeTime = todatetime(properties.changeAttributes.timestamp), 
  targetResourceId = tostring(properties.targetResourceId), 
  changeType = tostring(properties.changeType), changedBy = tostring(properties.changeAttributes.changedBy), 
  changedByType = properties.changeAttributes.changedByType, 
  clientType = tostring(properties.changeAttributes.clientType) 
| where changeTime > ago(7d) 
| project changeType, changedBy, changedByType, clientType 
| summarize count() by changedBy, changeType, clientType 
| order by count_ desc 

虛擬機器大小的變更

resourcechanges
| extend vmSize = properties.changes["properties.hardwareProfile.vmSize"], changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType) 
| where isnotempty(vmSize) 
| order by changeTime desc 
| project changeTime, targetResourceId, changeType, properties.changes, previousSize = vmSize.previousValue, newSize = vmSize.newValue

依變更類型和訂用帳戶名稱的變更計數

resourcechanges  
| extend changeType = tostring(properties.changeType), changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceType=tostring(properties.targetResourceType)  
| summarize count() by changeType, subscriptionId 
| join (resourcecontainers | where type=='microsoft.resources/subscriptions' | project SubscriptionName=name, subscriptionId) on subscriptionId 
| project-away subscriptionId, subscriptionId1
| order by count_ desc  

使用特定標籤所建立資源的最新資源變更

resourcechanges 
|extend targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType), createTime = todatetime(properties.changeAttributes.timestamp) 
| where createTime > ago(7d) and changeType == "Create" or changeType == "Update" or changeType == "Delete"
| project  targetResourceId, changeType, createTime 
| join ( resources | extend targetResourceId=id) on targetResourceId
| where tags ['Environment'] =~ 'prod' 
| order by createTime desc 
| project createTime, id, resourceGroup, type

下一步