PowerShell을 사용하여 Azure 상세 사용 보고서 작성하기

Azure에서 작업 부하를 실행하는 가장 중요한 측면 중 하나는 비용을 추적하는 것입니다. 이를 수행하는 방법은 Azure 자세한 사용 보고서로 리소스 사용을 추적하는 것입니다. 이 문서에서는 PowerShell 스크립트를 만들어 Azure 리소스 사용 및 비용을 날짜별로 쉽게 쿼리하는 방법을 배우게 됩니다.

Azure의 리소스는 많은 다양한 방식으로 계속 비용이 발생합니다. 웹 포털을 통해 리소스 사용량을 볼 수는 있지만, 이는 제한적입니다. 그러나 PowerShell cmdlet 몇 가지를 사용하여 Azure 리소스의 사용량(따라서 비용)을 한 눈에 볼 수 있는 유용한 보고서를 작성할 수 있습니다.

이 문서는 TechSnips YouTube 동영상에서 만들어졌습니다. 시각적으로 더 배우고 싶다면 동영상을 확인해보세요. 그렇지 않으면 계속 읽어보세요!

Azure 계정 센터를 통한 보고서 다운로드

Azure Account Center에서 많은 다양한 사용 보고서를 다운로드할 수 있습니다. Azure Account Center는 빌링 주기 기록을 확인하고 송장을 다운로드하며 Azure 구독 개요를 볼 수 있는 웹 포털입니다.

Azure Account Center를 통해 Azure 사용 보고서를 다운로드할 수는 있지만, 날짜 범위를 선택하는 유연성은 없습니다. 빌링 주기와 일치하도록 고정된 날짜 때문에 날짜 범위를 제한할 수 없습니다.

아래에 빌링 주기의 예와 사용 보고서 다운로드 링크가 나와 있습니다.

Azure Account Center usage reports

이 사용 보고서에는 필요하지 않을 수도 있는 다른 많은 정보가 포함되어 있습니다.

아마도 최근 60일간의 사용 보고서가 필요할 것입니다. Azure Account Center를 사용하여 이 정보를 얻으려면 필요한 모든 날짜를 커버하기 위해 최소한 세 개의 빌링 주기에 대한 사용 보고서를 다운로드해야 합니다.

보고서를 다운로드 한 후에는 초과 데이터를 제거해야합니다. 그런 다음 어떻게든 해당 데이터를 통합하는 방법을 찾아야합니다. 그러나 그건 너무 많은 부담입니다.

PowerShell을 사용하면 Azure 리소스 사용 보고서를 가져올 수 있는 재사용 가능한 스크립트, 함수 또는 모듈을 만들 수 있습니다. 이를 통해 몇 줄의 명령으로 수동으로 실행하거나 예약된 작업으로 자동화할 수 있습니다.

전제 조건

이 문서는 단계별 안내서입니다. 따라하기 위해 몇 가지 사항이 준비되어 있어야합니다.

리소스 사용 데이터 가져오는 방법

스크립트를 생성하기 전에, 먼저 Get-UsageAggregates cmdlet을 사용하여 기본 사항을 논의해 보겠습니다. 이 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 속성 배열의 마지막 항목을 가져옵니다. 새로운 결과와 이전 결과를 비교하여 새로운 결과가 다른지 확인하세요.

비교는 아래에서 보는 것과 유사해야 합니다. 날짜 범위가 7일 차이 나는 것을 확인하세요. 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 cmdlet으로 파이프할 수 있습니다.

Get-Azure 함수의 출력은 모든 리소스 유형을 반환하지만 MeterCategory라는 속성을 포함합니다. 이 속성은 행이 나타내는 리소스 유형을 정의합니다. 예를 들어, Azure 가상 머신 사용 보고서만 가져오려면 MeterCategoryVirtual Machines인 모든 객체를 Group-Object cmdlet을 사용하여 그룹화할 수 있습니다.

Group-Object cmdlet은 출력에 있는 행 수를 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-HTML 또는 EnhancedHTML2 PowerShell 모듈을 사용하여 HTML 보고서를 생성할 수도 있습니다.

또한, Send-MailMessage cmdlet을 사용하여 결과에 이메일 알림을 추가할 수도 있습니다. 세상은 여러분의 소라고래입니다!

요약

이 글에서는 Azure에서 리소스 사용 보고서를 검색하는 방법을 배웠습니다. 또한, 프로세스를 자동화하기 위해 사용자 정의 PowerShell 함수를 작성하고 해당 함수를 사용하여 출력을 조작하는 방법도 배웠습니다.

다음에 예상치 못한 Azure 청구서가 도착하면 변명할 수 없습니다! Azure 리소스 사용량을 언제든지 쿼리할 수 있는 PowerShell 함수를 만들어서 청구서를 확인하세요.

추가 자료

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