使用PowerShell构建Azure详细使用报告

在 Azure 中运行工作负载的最重要方面之一是跟踪费用。您可以通过使用 Azure 详细使用报告跟踪资源使用情况来实现这一点。在本文中,您将学习如何创建一个 PowerShell 脚本,以便通过日期轻松查询 Azure 资源使用情况和费用。

Azure 中的资源以多种方式不断增加您的费用。虽然您可以通过 Web 门户查看资源使用情况,但有一定限制。但是,通过使用一些 PowerShell 命令,您可以构建一个方便的报告,让您一目了然地了解您的 Azure 资源正在进行何种使用(从而产生了什么费用)。

本文是从 TechSnips 的 YouTube 视频创建的。如果您更喜欢通过视觉方式学习,请随时观看视频。否则,请继续阅读!

通过 Azure 账户中心下载报告

你可以从 Azure 账户中心 下载许多不同的使用报告。Azure 账户中心是一个 Web 门户,允许您查看您的计费周期历史,下载发票,并查看 Azure 订阅的概述。

虽然您可以通过 Azure 账户中心下载 Azure 使用报告,但在选择日期范围方面没有灵活性。您无法限制使用到一个日期范围,因为日期与您的计费周期相吻合。

您可以在下面看到一个计费周期的示例和下载使用报告的链接。

Azure Account Center usage reports

这些使用报告中包含许多您可能不需要的其他信息。

也许您需要过去 60 天的使用报告。要使用 Azure 账户中心获取此信息,您需要至少下载三个计费周期的使用报告,以涵盖所有所需的日期。

当报告下载完成后,您需要删除多余的数据。然后,您需要想出一种方法来合并这些数据。谢谢,但这太繁琐了。

使用PowerShell,您可以构建一个可重复使用的脚本、函数或模块来提取Azure资源使用报告。这些报告可以手动运行,只需几行命令,也可以作为定期任务自动执行。

先决条件

这是一篇详细的文章。要跟着操作,您需要有一些先决条件。

如何获取资源使用数据

在创建脚本之前,让我们首先使用 Get-UsageAggregates cmdlet 讨论基础知识。这是一个允许您按日期范围、按小时或按日等指标提取 Azure 资源使用情况的 cmdlet。 Get-UsageAggregates cmdlet 是本文中大部分魔力所在的主要 cmdlet。

为了演示 Get-UsageAggregates cmdlet,假设您需要从2019年4月1日到2019年9月12日查找 Azure 资源使用情况。相同的技术可用于任何日期范围。以下是一个查找基于这些日期的使用数据的片段。

$params = @{
    ReportedStartTime = '04-01-19'
    ReportedEndTime = '09-12-19'
    AggregationGranularity = 'Hourly'
    ShowDetails = $true
}
$usageData = Get-UsageAggregates @params
Parameter Value Usage Explanation
ReportStartTime 04-01-19 This is the oldest date you want to retrieve.

(月 日 年)

ReportEndTime 09-12-19 This is the latest date you want to retrieve.

(月 日 年)

AggregationGranularity Hourly The granularity of data to return. Valid values are “Daily” and “Hourly”
ShowDetails $True Indicates whether the instance-level details are expanded

如果有数据返回,您应该会得到类似下面截屏的结果。您可以看到实际使用数据存储在 UsageAggregations 属性中。

Raw UsageAggregations output properties

处理 Get-UsageAggregates 中的分页

在上面的部分中,该命令通常会返回许多对象,尤其是对于长时间范围而言。为了防止 API 被压垮,Get-UsageAggregates 命令仅返回最多 1000 个结果。如果您已经像前一部分所述保存了 $usageData 变量,您可以通过运行以下命令确认:$usageData.UsageAggregations.count

如果结果超过1000个怎么办?你可能需要做更多的工作。

当你检查Get-UsageAggregates返回的属性时,你会注意到一个叫做ContinuationToken的属性,如下所示。你可以看到这个标记是一个长字符串。

Usage aggregates continuation token

ContinuationToken是指向下一组结果的指针。该属性充当书签,用于知道从哪个页面获取下一批结果。

为了演示,使用$usageData.UsageAggregations[-1]获取上一个结果中的最后一项,如下所示。注意Usage StartUsage End的时间。

First usage object

现在,再次将相同的参数传递给Get-UsageAggregates命令。但这次,使用ContinuationToken参数,并使用先前返回的ContinuationToken属性的值。下面是如何做的一个示例。

$params = @{
    ReportedStartTime      = '04-01-19'
    ReportedEndTime        = '09-12-19'
    AggregationGranularity = 'Hourly'
    ShowDetails            = $true
    ContinuationToken      = $usageData.ContinuationToken
}
$usageData = Get-UsageAggregates @params

现在,使用$usageData.UsageAggregations[-1]获取UsageAggregations属性数组中的最后一项。将其与先前的结果进行比较,以确认新的结果是否不同。

比较应该类似于下面你看到的那些。注意日期范围相隔七天。通过使用ContinuationToken,你检索了第二页的结果。

Second page of usage reports
First page of usage reports

构建Azure资源使用报告函数

您应该了解分页是如何工作的,以及如何使用ContinuationToken属性和参数。但是,如果要检索数以万计甚至数十万个结果呢?手动使用令牌的方式效果并不太好。

让我们构建一个 PowerShell 脚本来处理这个分页需求,并允许我们进一步灵活地使用。这个脚本将允许您提供自己的参数并处理分页需求。它还将为您提供灵活性,以后如果需要,可以扩展其执行其他任务。

构建参数

首先构建一些函数框架。下面您可以看到一个名为Get-AzureUsage的示例函数。这个函数有三个参数,可能看起来很熟悉。

以前,这些参数是在Get-UsageAggregates cmdlet本身上定义的。现在您正在构建一个“包装”函数,它将向此 cmdlet 传递值。

Function Get-AzureUsage {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [datetime]$FromTime,
 
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [datetime]$ToTime,
 
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Hourly', 'Daily')]
        [string]$Interval = 'Daily'
    )

下面是一个表格,提供了关于所有这些参数的进一步信息。

Parameter Usage
FromTime This is a mandatory parameter that accepts a DateTime value. The value represents the oldest date of the report.
ToTime This is a mandatory parameter that accepts a DateTime value. The value represents the latest date of the report.
Interval This is a non-empty parameter that accepts two possible values: ‘Daily’ and ‘Hourly’. The default value is Daily. This represents the granularity of the report to return.

查询资源使用情况

一旦函数被创建并且所有参数被定义,就该填写函数的其余部分了。

您可以在下面看到Get-AzureUsage函数的其余部分。确保查看注释以更深入地理解代码的作用。

Write-Verbose -Message "Querying usage data [$($FromTime) - $($ToTime)]..."
    $usageData = $null
    ## 开始使用do/while循环自动处理继续令牌
    do {    
        ## 定义传递给Get-UsageAggregates的所有参数
        $params = @{
            ReportedStartTime      = $FromTime
            ReportedEndTime        = $ToTime
            AggregationGranularity = $Interval
            ShowDetails            = $true
        }
        ## 如果这不是第一次运行,则仅使用ContinuationToken参数
        if ((Get-Variable -Name usageData -ErrorAction Ignore) -and $usageData) {
            Write-Verbose -Message "Querying usage data with continuation token $($usageData.ContinuationToken)..."
            $params.ContinuationToken = $usageData.ContinuationToken
        }
        $usageData = Get-UsageAggregates @params
        $usageData.UsageAggregations | Select-Object -ExpandProperty Properties
    } while ('ContinuationToken' -in $usageData.psobject.properties.name -and $usageData.ContinuationToken)
}

已完成的脚本(可复制/粘贴)

将参数和功能代码放在一起后,您将得到一个完整的脚本,如下所示。您现在可以将其复制到您自己的脚本中,或直接粘贴到PowerShell控制台进行测试。

Function Get-AzureUsage {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [datetime]$FromTime,
 
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [datetime]$ToTime,
 
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('Hourly', 'Daily')]
        [string]$Interval = 'Daily'
    )
    
    Write-Verbose -Message "Querying usage data [$($FromTime) - $($ToTime)]..."
    $usageData = $null
    do {    
        $params = @{
            ReportedStartTime      = $FromTime
            ReportedEndTime        = $ToTime
            AggregationGranularity = $Interval
            ShowDetails            = $true
        }
        if ((Get-Variable -Name usageData -ErrorAction Ignore) -and $usageData) {
            Write-Verbose -Message "Querying usage data with continuation token $($usageData.ContinuationToken)..."
            $params.ContinuationToken = $usageData.ContinuationToken
        }
        $usageData = Get-UsageAggregates @params
        $usageData.UsageAggregations | Select-Object -ExpandProperty Properties
    } while ('ContinuationToken' -in $usageData.psobject.properties.name -and $usageData.ContinuationToken)
}

使用我们的函数查询资源使用情况

现在是测试函数的时候了。要么将上面的代码粘贴到脚本中并在当前的PowerShell会话中进行点源,要么直接将代码复制到您的PowerShell会话中。

提示:如果您正在使用PowerShell ISE或Visual Studio Code,您可以突出显示要导入的代码,然后按F8。否则,将代码复制并粘贴到PowerShell会话中会更容易。

现在运行该函数,提供一个值给FromTimeToTime,以及您想要查看结果的间隔。您可以看到下面的示例,演示如何调用此函数。

$usage = Get-AzureUsage -FromTime '08-12-19' -ToTime '09-12-19' -Interval Hourly -Verbose

一旦运行,如果您选择使用可选的Verbose参数,您将看到一些冗长的消息。从下面的示例可以看出,使用报告计数为4,659。您还会注意到,函数每次运行Get-UsageAggregates函数四次,每次获取下一页的结果。函数能够做到这一点,是因为它对每个调用都使用了正确的ContinuationToke值。

Automatically handling the continuation token

过滤报告

此时,报告包含有关所有可用资源类型的所有使用详细信息。但您可以过滤报告以仅显示您想要的资源。要做到这一点,您可以扩展函数以允许此功能,或将输出管道传递到其他PowerShell命令。

Get-Azure函数的输出返回所有资源类型,但包含一个名为MeterCategory的属性。此属性定义了该行表示的资源类型。例如,要仅获取Azure虚拟机使用情况报告,您可以使用Group-Object命令将所有具有MeterCategoryVirtual Machines的对象分组。

Group-Object命令将返回输出中存在的行数作为Count属性。然后,将输出限制为仅包含CountName属性(MeterCategory的值),您可以看到所有Azure资源类型的使用报告行数。

如您在下面的截图中所见,报告中有768个虚拟机的条目。

Azure Virtual Machines resource usage

为了进一步理解这个过滤的概念,您还可以利用计算属性,以创建下面显示的更友好的输出。

$usage | Where-Object {$_.MeterCategory -eq 'Virtual Machines'} | `
Format-Table UsageStartTime,UsageEndTime,@{n="VM Name";e={(($_.InstanceData | `
ConvertFrom-Json).'Microsoft.Resources'.resourceURI -split "/")[-1]}},Quantity,Unit

当您运行上面的代码片段时,您应该看到类似于下面所示的输出。

Advanced filtering for Get-AzureUsage

扩展报告的思路

使用本文中的代码,您可以以多种不同的方式扩展所创建工具的功能。

您可以将输出导出到CSV文件,并在Excel中操作数据,或者使用创建HTML报告,使用ConvertTo-HTMLEnhancedHTML2 PowerShell模块。

再进一步,通过Send-MailMessage命令,将电子邮件通知添加到结果中。世界是你的牡蛎!

总结

在本文中,您学会了如何从Azure检索资源使用报告。您还学会了如何构建一个定制的PowerShell函数来自动化该过程,并使用该函数来操作输出。

下次收到意外的 Azure 账单时,你就没有借口了!编写一个 PowerShell 函数来随时查询 Azure 资源使用情况,以便关注账单。

进一步阅读

Source:
https://adamtheautomator.com/azure-detailed-usage-report/