Azure虚拟机成本分析报表生成及API资源组过滤问题排查
解决Azure Consumption REST API资源组过滤失效问题,获取单VM月度总成本
核心问题分析
你遇到的资源组过滤失效,大概率是两个原因:
- OData过滤语法错误:Consumption API的资源组字段路径是
properties/resourceGroup,而非直接resourceGroup,写错路径会导致过滤条件被忽略,返回全订阅数据。 - 预留实例的特殊属性:预留实例(Reservation)属于订阅级资源,其记录的
properties/resourceGroup字段为空,如果只过滤资源组,会漏掉这部分成本,同时可能因逻辑不完整导致过滤失效。
正确的过滤方案
要同时覆盖VM本体、磁盘、公网IP和关联的预留实例成本,需要组合多维度过滤条件:
1. 修正OData过滤路径
必须使用完整的字段路径properties/resourceGroup,同时结合资源类型、VM名称、预留实例标识构建过滤条件:
$filter=properties/usageStart ge 'YYYY-MM-DD' and properties/usageStart lt 'YYYY-MM-DD' and ( (properties/resourceGroup eq '你的资源组名称' and (properties/resourceType eq 'Microsoft.Compute/virtualMachines' or properties/resourceType eq 'Microsoft.Compute/disks' or properties/resourceType eq 'Microsoft.Network/publicIPAddresses')) or (properties/reservationId ne null and properties/instanceName eq '你的VM名称' and properties/consumedService eq 'Microsoft.Compute') )
- 时间范围:用
usageStart限定月度(比如5月就是ge '2024-05-01' and lt '2024-06-01') - 资源组内的附属资源:过滤指定资源组下的VM、磁盘、公网IP
- 预留实例:通过
reservationId ne null识别预留记录,再用instanceName关联到目标VM
2. PowerShell完整示例代码
# 初始化Azure上下文,获取访问令牌 $context = Get-AzContext $token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate( $context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://management.azure.com" ).AccessToken # 配置参数 $subscriptionId = "你的订阅ID" $resourceGroupName = "你的资源组名称" $vmName = "你的VM名称" $startDate = "2024-05-01" # 月度起始日 $endDate = "2024-06-01" # 月度结束日(下一月第一天) # 构建过滤条件 $filter = @" properties/usageStart ge '$startDate' and properties/usageStart lt '$endDate' and ( (properties/resourceGroup eq '$resourceGroupName' and (properties/resourceType eq 'Microsoft.Compute/virtualMachines' or properties/resourceType eq 'Microsoft.Compute/disks' or properties/resourceType eq 'Microsoft.Network/publicIPAddresses')) or (properties/reservationId ne null and properties/instanceName eq '$vmName' and properties/consumedService eq 'Microsoft.Compute') ) "@ # 调用Consumption API $uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Consumption/usageDetails?api-version=2023-11-01`&`$filter=$filter" $usageDetails = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Bearer $token"} -Method Get # 计算月度总成本 $totalPreTaxCost = ($usageDetails.value | Measure-Object -Property properties/preTaxCost -Sum).Sum Write-Host "单VM月度实际总成本(含预留、磁盘、公网IP): $([math]::Round($totalPreTaxCost, 2)) USD"
关键注意事项
- API版本:使用最新稳定版(如
2023-11-01),旧版本的字段结构可能不同,导致过滤失效。 - 权限要求:执行脚本的账号需要拥有订阅级的
Cost Management Reader或Contributor权限,否则无法读取完整的成本数据。 - 预留实例关联:如果预留实例是跨订阅共享的,需要确保当前订阅能读取到对应的使用记录,否则会遗漏这部分成本。
- 精准匹配:用
instanceName关联预留实例和VM,确保不会把其他VM的预留成本计算进来。
内容的提问来源于stack exchange,提问作者Dieter
相关产品推荐
相关产品推荐

