Haikos Blog Blog von Haiko Hertes zu allen Themen rund um Microsoft und Datacenter

11Jan/200

Azure & PowerShell – Das UsageDetails CSV nach Tags auswerten

Hinweis: Der Großteil des Artikels ist auch in meinem YouTube-Video zu diesem Thema enthalten:

Auf Grund vieler Nachfragen aus Community und Kunden habe ich mich dazu entschieden, dieses Thema etwas genauer zu beleuchten... Wenn man Azure in größerem Umfang nutzt, dann kommt schnell die Frage nach interner Kostenverrechnung ("Innerbetriebliche Leistungsverrechnung" / "Charge back") oder zumindest der Möglichkeit, die Kosten den jeweiligen Verursachern zuzuordnen und transparent darzustellen. Ein wesentliches Hilfsmittel dafür ist das Tagging von Ressourcen. Klar, man könnte die Ressourcen auch nach Kostenstellen getrennt in unterschiedlichen Subscriptions unterbringen, das stößt in der Praxis aber schnell an Grenzen und auf Probleme.

Hat man nun seine Ressourcen mit den entsprechenden Tags versehen, z.B. nach Besitzer ("Owner"), Kostenstelle ("Cost center") oder Abteilung ("Department"), dann tauchen diese Tags leider noch nicht in der regulären Rechnung auf.

Nun kann man sich aus dem Azure Portal (oder auch aus dem EA / Enterprise Portal oder via REST API) eine Detail-Aufstellung der Kosten herunterladen. Dazu muss man zu "Cost Management + Billing" / Billing-Scope auswählen / "Usage + Charges" / Monat wählen / Download-Button klicken / Kurz warten / " Usage Details Version 2" auswählen. Diese "Usage Details" enthalten dann auch die Tags. Allerdings: Selbst wenn man das CSV-File so umformatiert, dass Excel damit umgehen kann, ergibt sich noch ein Problem:

Die einzelnen Tags werden alle zusammen geworfen und in einer "Spalte" vermischt. Damit ist das Suchen oder Filtern nach einzelnen Tags schon recht schwer - eine bestimmte Kombination aus Tags ist damit unmöglich zu filtern. Dazu müsste man die Tags jeweils in einzelnen Spalten ablegen. Und da kommt PowerShell und dessen Möglichkeit, mit dem JSON-Format umzugehen, ins Spiel! Ich habe eine Script geschrieben, was die Spalte in die einzelnen Tags aufteilt. Dabei werden auch gleich Zahlen und Daten in das lokale Format überführt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Script to expand tags from the usage details CSV provided by Azure / Microsoft
# to filter usage by tags; also converts some numbers to local format
# Download CSV file by hand first!
 
 
# This is needed for the FileOpen Dialog	
Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
    InitialDirectory = [Environment]::GetFolderPath('Desktop') 
    Filter = 'CSV-Files (*.csv)|*.csv'
}
$null = $FileBrowser.ShowDialog() # Just to open the dialog
 
If($FileBrowser.FileName -eq "")
{
    Write-Verbose "No file selected - aborting."
    Break    
}
 
$CSV = Import-Csv $FileBrowser.FileName -Delimiter ","
 
for ($i=0; $i -lt $CSV.length; $i++) 
{
    # Showing progress
    Write-Progress -Activity "Expanding in Progress..." -Status "$([math]::truncate($i / $($CSV.length) * 100))% complete..." -PercentComplete $($i / $($CSV.length) * 100)
 
    # Converting dates and numbers to local format
    $CSV[$i].Date = [datetime]::ParseExact( $CSV[$i].Date, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].BillingPeriodStartDate = [datetime]::ParseExact( $CSV[$i].BillingPeriodStartDate, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].BillingPeriodEndDate = [datetime]::ParseExact( $CSV[$i].BillingPeriodEndDate, 'MM/dd/yyyy', $null).ToString("d")
    $CSV[$i].Quantity = [float]$CSV[$i].Quantity
    $CSV[$i].EffectivePrice = [float]$CSV[$i].EffectivePrice
    $CSV[$i].Cost = [float]$CSV[$i].Cost
    $CSV[$i].UnitPrice = [float]$CSV[$i].UnitPrice
 
 
    # Expand Tags
    $Tags = "{ $($CSV[$i].Tags) }" | ConvertFrom-Json # We need to add some brackets here...
    if ($Tags -ne $null) {
         $Tags.PSObject.Properties | ForEach { 
            $TagName = "Tag-$($_.Name)" 
            Add-Member -InputObject $CSV[$i] $TagName $_.Value 
            # Adding the heading - what a rhyme (; ...
            if ($CSV[0].PSObject.Properties[$TagName] -eq $null) {
                Add-Member -InputObject $CSV[0] $TagName $null -Force
            }
        }
    }
 
}
 
# Saving as Excel-readable CSV
$CSV | Export-Csv "$([System.IO.Path]::GetDirectoryName($FileBrowser.FileName))\$([io.path]::GetFileNameWithoutExtension($FileBrowser.FileName))_expanded.csv" -NoTypeInformation -Delimiter ";"

Das Script findet ihr natürlich auch auf meinem GitHub Repo:

https://github.com/HaikoHertes/scripts/blob/master/Azure/Management/Expand-AzureTagsFromUsageDetails.ps1 

Das Resultat der Umwandlung wird dann in eine neue Excel-Datei im selben Folder wie die Originaldatei abgespeichert und kann dann problemlos in Excel geöffnet werden:

Wie man hier sieht sind die Tags nun in separaten Spalten untergebracht, so dass man sehr gut danach sortieren, darauf filtern oder mehr tun kann.

Viel Spaß beim Ausprobieren bzw. Benutzen!

17Sep/190

PowerShell – Nicht verwendete Azure Ressourcen finden

Ein regelmäßiges Problem im Azure-Alltag ist das Aufräumen nicht mehr benötigter Azure-Ressourcen. Diese kosten in der Regel unnötig Geld und stellen zum Teil auch ein (Sicherheits-)Risiko dar (wenn zum Beispiel eine nicht mehr verwendete VM aus dem Fokus gerät und über Jahre nicht gepatcht wird).

Um dieser Herausforderung zu begegnen gilt es zunächst, die Ressourcen, die "weg" können, zu identifizieren. Dazu habe ich eine erste Version eines PowerShell Skriptes erstellt, welches:

  • Nicht verwendete Public IPs
  • Nicht verwendete NICs
  • Nicht verwendete NSGs
  • Nicht verwendete Managed Disks

findet und aufführt.

Über die Zeit möchte ich das Skript weiter ausbauen.

Ihr findet es in meinem GitHub Repository:

https://github.com/HaikoHertes/scripts/blob/master/Azure/Management/GetOrphanedAzureRessources.ps1

Und ja, natürlich bietet Azure mit seinen Recommendations hier auch schon einiges, allerdings eben nicht "live"...

Viel Spaß beim Ausprobieren - über Kommentare freue ich mich!