PowerShellを使用したAzureの詳細な使用状況レポートの構築

Azureでワークロードを実行する上で最も重要な要素の一つは、費用の追跡です。それを行う方法は、Azureの詳細な使用状況レポートを使用してリソースの使用状況を追跡することです。本記事では、PowerShellスクリプトを作成して、日付ごとにすべてのAzureリソースの使用状況と料金を簡単にクエリする方法について学びます。

Azureのリソースは、さまざまな方法で料金がかかり続けています。Webポータルを介してリソースの使用状況を確認することはできますが、制限があります。ただし、いくつかのPowerShellコマンドレットを使用することで、Azureリソースの使用状況(つまり、費用)を一覧表示する便利なレポートを作成できます。

この記事は、TechSnipsのYouTubeビデオから作成されました。視覚的に学ぶ方は、ビデオをチェックしてください。それ以外の場合は、読み進めてください!

Azureアカウントセンターを介してレポートをダウンロードする

Azure Account Centerからは、さまざまな使用状況レポートをダウンロードすることができます。Azure Account Centerは、請求サイクルの履歴を表示したり、請求書をダウンロードしたり、Azureのサブスクリプションの概要を確認したりするためのウェブポータルです。

Azure Account Centerを介してAzureの使用状況レポートをダウンロードできますが、日付範囲を選択する柔軟性はありません。日付は請求サイクルに合わせて固定されているため、日付範囲を制限することはできません。

以下に請求期間の例と使用状況レポートのダウンロードリンクが示されています。

Azure Account Center usage reports

これらの使用状況レポートには、必要のない情報も含まれているかもしれません。

おそらく、過去60日間の使用状況レポートが必要なのかもしれません。Azure Account Centerを使用してこの情報を取得するには、必要な日付をカバーするために少なくとも3つの請求サイクルの使用状況レポートをダウンロードする必要があります。

レポートがダウンロードされた後、余分なデータを削除する必要があります。そのデータをどうやって統合するかを考える必要があります。いやだ!それはあまりにも多くのオーバーヘッドです。

PowerShellを使用すると、Azureのリソース使用状況レポートを取得するための再利用可能なスクリプト、関数、またはモジュールを作成することができます。これらは、数行のコマンドで手動で実行するか、スケジュールされたタスクとして自動化することができます。

前提条件

この記事は手順の説明です。進行するためには、いくつかの事前準備が必要です。

  • Windows 10以降。
  • Windows Powershell v5.1
  • A script editor, like Notepad++ or an Integrated Scripting Environment (ISE) like Windows PowerShell ISE and Visual Studio Code.
  • Azureのサブスクリプション。
  • Azure PowerShellモジュール。この投稿時点での最新バージョンは2.6.0です。このモジュールはマシンにインストールされている必要があります。まだインストールしていない場合は、PowerShellGetを使用してインストールできます。
  • Connect-AzAccountコマンドレットを使用してAzureへの接続を確立してください。

リソース使用状況データの取得方法

スクリプトを作成する前に、まずは基本をGet-UsageAggregatesコマンドレットを使用して説明しましょう。このコマンドレットは、日付範囲や時間帯などのメトリックに基づいてAzureのリソース使用状況を取得するためのものです。このGet-UsageAggregatesコマンドレットは、この記事で学んでいく中でほとんどの処理を行う主要なコマンドレットです。

例として、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プロパティ配列の最後のアイテムを取得します。新しい結果が異なることを確認するために、前の結果と比較します。

比較結果は以下のようなものになるはずです。日付範囲が7日間ずつ異なることに注目してください。 ContinuationTokenを使用することで、2ページ目の結果を取得しました。

Second page of usage reports
First page of usage reports

Azureリソース使用状況レポート機能の構築

ページングの仕組みとContinuationTokenプロパティとパラメータの使い方を知るべきです。しかし、何万件、さらには何十万件もの結果を取得する場合はどうでしょうか?このようにトークンを手動で使用することはあまりうまくいきません。

このページング要件を処理し、さらなる柔軟性を提供するPowerShellスクリプトを作成しましょう。このスクリプトでは、独自のパラメータを指定し、ページング要件を処理することができます。また、必要に応じて他のタスクを実行するために将来拡張する柔軟性も持っています。

パラメータの作成

まず、関数のひな型を作成します。以下はGet-AzureUsageという名前の関数の例です。この関数には3つのパラメータがありますが、おなじみに見えるかもしれません。

以前は、これらのパラメータはGet-UsageAggregatesコマンドレット自体で定義されていました。これからは、値をこのコマンドレットに渡す「ラッパー」関数を作成します。

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関数を4回実行し、各回で次のページの結果を取得しています。関数は、各呼び出しに正しいContinuationToke 値を使用したため、これが可能になりました。

Automatically handling the continuation token

レポートのフィルタリング

この時点で、レポートには利用可能なすべてのリソースタイプの使用詳細が含まれています。ただし、表示するリソースを特定のものに絞り込むために、関数を拡張するか、出力を他のPowerShellコマンドレットにパイプすることができます。

Get-Azure関数の出力はすべてのリソースタイプを返しますが、MeterCategoryというプロパティも含まれています。このプロパティは、その行が表すリソースのタイプを定義しています。たとえば、Azure仮想マシンの使用レポートのみを取得するには、MeterCategoryVirtual Machinesであるオブジェクトをまとめて、Group-Objectコマンドレットを使用することができます。

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でデータを操作したり、ConvertTo-HTMLEnhancedHTML2 PowerShellモジュールを使用してHTMLレポートを作成することもできます。

さらに一歩進んで、Send-MailMessageコマンドレットを使用して結果に電子メール通知を追加することもできます。世界はあなたのものです!

まとめ

この投稿では、Azureからリソース使用状況レポートを取得する方法を学びました。さらに、プロセスを自動化するためのカスタムPowerShell関数を作成し、その関数を使用して出力を操作する方法も学びました。

次に予期せぬAzureの請求書が来たとき、言い訳はできません!いつでもAzureリソースの使用状況をクエリするためのPowerShell関数を作成して、請求書を見守りましょう。

さらに読む

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