다음을 통해 공유


리소스 변경 내용 가져오기

리소스는 일상적인 사용, 다시 구성 및 재배치 과정을 통해 변경됩니다. 대부분의 변경은 의도적이지만 때로는 그렇지 않습니다. 마케팅 목록의 구성원을 관리할 수 있습니다.

  • Azure Resource Manager 속성에서 변경이 탐지된 시기를 확인합니다.
  • 속성 변경 세부 정보 보기
  • 구독, 관리 그룹 또는 테넌트 전반에 걸쳐 대규모로 변경 내용 쿼리

이 문서에서는 다음에 대해 알아봅니다.

  • 페이로드 JSON의 모양입니다.
  • CLI, PowerShell 또는 Azure Portal을 사용하여 Resource Graph를 통해 리소스 변경 내용을 쿼리하는 방법입니다.
  • 리소스 변경 내용을 쿼리하기 위한 쿼리 예 및 모범 사례입니다.
  • 변경 분석은 변경 행위자 기능을 사용합니다.
    • changedBy: 앱 ID 또는 권한 있는 사용자의 아메일 주소와 같은 리소스 변경을 시작한 사용자입니다.
    • clientType: 변경 작업을 수행한 클라이언트입니다(예: Azure Portal).
    • operation: 호출된 작업입니다(예: Microsoft.Compute/virtualmachines/write).

필수 조건

  • Azure PowerShell을 사용하여 Azure Resource Graph를 쿼리하려면 모듈을 추가합니다.
  • Azure CLI를 사용하여 Azure Resource Graph를 쿼리하려면 확장을 추가합니다.

변경 이벤트 속성 이해

리소스를 만들거나 업데이트하거나 삭제하면 수정된 리소스를 확장하고 변경된 속성을 나타내는 새 변경 리소스(Microsoft.Resources/changes)가 만들어집니다. 변경 기록은 5분 이내에 사용할 수 있어야 합니다. 다음 예 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 리소스 변경 내용 중 처음 5개를 변경 시간, 변경 유형, 대상 리소스 ID, 대상 리소스 종류 및 각 변경 레코드의 변경 세부 정보와 함께 반환

# 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'

쿼리 결과를 가장 최근 변경 내용으로 제한하려면 쿼리를 사용자 정의 changeTime 속성인 order by로 업데이트합니다.

# 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-AzGraph PowerShell cmdlet은 기본 컨텍스트에서 구독으로 기본 설정됩니다.

Resource Graph Explorer는 일부 쿼리의 결과를 Azure 대시 보드에 고정할 수 있는 차트로 변환하는 깔끔한 인터페이스도 제공합니다.

쿼리 리소스 변경

Resource Graph를 사용하면 resourcechanges, resourcecontainerchanges 또는 healthresourcechanges 테이블을 쿼리하여 변경 리소스 속성을 기준으로 필터링하거나 정렬할 수 있습니다. 다음 예에서는 resourcechanges 테이블을 쿼리하지만 resourcecontainerchanges 또는 healthresourcechanges 테이블에도 적용될 수 있습니다.

참고 항목

Project Flash 설명서에서 healthresourcechanges 데이터에 대해 자세히 알아봅니다.

예제

리소스의 변경 내용을 쿼리하고 분석하기 전에 다음 모범 사례를 검토합니다.

  • 특정 시간 창에서 변경 이벤트를 쿼리하고 변경 세부 정보 평가
    • 이 쿼리는 인시던트 관리 중에 잠재적으로 관련된 변경 내용을 이해하는 데 가장 효과적입니다.
  • 최신 CMDB(구성 관리 데이터베이스)를 유지합니다.
    • 예약된 빈도에 따라 모든 리소스와 전체 속성 집합을 새로 고치는 대신 변경 내용만 수신하게 됩니다.
  • 리소스가 준수 상태를 변경했을 때 변경되었을 수 있는 다른 속성을 이해합니다.
    • 이러한 추가 속성을 평가하면 Azure Policy 정의를 통해 관리해야 할 수 있는 다른 속성에 대한 인사이트를 제공할 수 있습니다.
  • 쿼리 명령의 순서는 중요합니다. 다음 예에서 order bylimit 명령 앞에 와야 합니다.
    • order by 명령은 변경 시간을 기준으로 쿼리 결과를 정렬합니다.
    • 그런 다음 limit 명령은 순서가 지정된 결과를 제한하여 가장 최근 결과 5개를 가져올 수 있도록 합니다.
  • 알 수 없음은 무엇을 의미하나요? 
    • 인식할 수 없는 클라이언트에서 변경이 발생하면 알 수 없음이 표시됩니다. 클라이언트는 원래 변경 요청과 연결된 사용자 에이전트 및 클라이언트 애플리케이션 ID를 기반으로 인식됩니다.
  • 시스템은 무엇을 의미하나요?
    • 직접 사용자 작업과 상관 관계가 없는 백그라운드 변경이 발생한 경우 시스템은 changedBy 값으로 표시됩니다.

지난 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

지난 7일 동안의 변경 내용: 사용자 및 클라이언트 및 주문 수별 변경

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

다음 단계