PowerShell Script: 使用されていない不要な Azure リソースを自動検知して削除する

こんにちは Azure サポートチームの山口です。
今日は、Azure を使っているうちに溜まってしまったゴミリソースをお掃除する Powershell スクリプトをご紹介したいと思います。

Azure リソース漂流記


昔々、あるところに Azure VM を作成したおじいさんがいました。

おじいさんは VM をずっと大切に使っていましたが、ある日 VM との決別を決意します。そこで VM リソースを削除すると・・・

そうなんです。VM 以外の Azure リソースは自動的に削除されないんです。
おじいさんは VM を削除したことで満足してしまい、このことに気が付きません。
こうやって取り残された 6 つの Azure リソースは、サブスクリプションの海をいつまでもいつまでも漂っていたのでした。
完。

・・・こんな状態は良くないですよね。
このような使用されていない Azure リソースが増えるとリソース管理が煩わしくなるだけでなく、さらにストレージ アカウントなどの一部のリソースは放置しているだけでも課金されてしまうので、早急に削除しなければいけません。

せっせと手動でリソースを 1 個ずつ消すのも一つの手ですが、この手の自動化タスクにおいて、人類は Powershell に屈服すること必至です。Powershell に任せましょう。

PowerShell Script


というわけで、上記のようなシナリオを想定した PowerShell スクリプトをご紹介いたします。
このスクリプトは、不要だと判断された Azure リソース一覧を取得し、その中の任意のリソースを削除することが出来ます。

ダウンロード

CleanupUnusedResource.ps1

実行手順

  • 上記のリンクからスクリプトをダウンロードしてください。
  • スクリプト ファイルの拡張子を .ps1 に変更して、適当なフォルダに配置しください。 (ブログのアップロードファイルの制限のため、".txt" にしてあります)
  • PowerShell を起動し、先程配置したスクリプト ファイルを実行します。

パラメータ

  • SubscriptionNameOrId
    削除対象となるサブスクリプションを、名前か ID で指定します。
    省略可能で、指定しない場合は、すべてのサブスクリプションのうちどれを対象とするかを一つ又は複数選択することが出来るダイアログが表示されます。
    なお指定した場合は、名前か ID によってサブスクリプションが一意に特定できる必要があります。
  • RemoveStorage
    switch パラメータで、このパラメータをオンにすると後述のストレージ関連リソースを削除します。
  • RemoveNetwork
    switch パラメータで、このパラメータをオンにすると後述のネットワーク関連リソースを削除します。
  • RemoveResourceGroup
    switch パラメータで、このパラメータをオンにするとリソース グループを削除します。
  • RemoveAll
    switch パラメータで、このパラメータをオンにすると、ストレージ関連リソース、ネットワーク関連リソース、およびリソース グループを削除します。

削除する Azure リソース

本スクリプトが削除対象とする Azure リソースは、大きく次の 3 種類に分類することが出来ます。

  1. ストレージ関連リソース

    • VHD BLOB
    • 管理ディスク
    • ストレージ アカウント
  2. ネットワーク関連リソース

    • ネットワーク インターフェイス
    • パブリック IP アドレス
    • ネットワーク セキュリティ グループ
    • 仮想ネットワーク
  3. リソース グループ

削除する Azure リソースの詳細


ストレージ関連リソース

本スクリプトでは、3 つの Azure リソースをストレージ関連リソースと呼んでいます。以下は、それらリソースの概要と、不使用 / 使用中の判定基準の説明です。

  • VHD BLOB

    BLOB とは、ストレージ アカウントを使用して Azure 上に保存できる、任意の種類 / サイズのファイルのことですが、ここででは、特に「名前が vhdsであるようなストレージ コンテナ中の、.vhd という拡張子をもつ BLOB」を VHD BLOB と呼んでいます。

    本スクリプトでは、関連付けられている VM がない、すなわち、リース中でない VDH BLOB が、「使用されていない VHD BLOB」であると見なされます。

    # Get all blobs which filename have the extension ".vhd".
    $AllVhdsContainers = Get-AzureRmStorageAccount | Get-AzureStorageContainer | Where { $_.Name -eq "vhds" }
    $AllVhdBlobs = $AllVhdsContainers | Get-AzureStorageBlob | Where { $_.Name.EndsWith('.vhd') }
    
    # Find unused vhd blobs, where a vhd blob is defined as unused iff its lease status/state is unlocked/available.
    $LostVhdBlobs = $AllVhdBlobs | Where { $_.ICloudBlob.Properties.LeaseStatus -eq "Unlocked" -and $_.ICloudBlob.Properties.LeaseState -eq "Available" }
    
  • 管理ディスク

    管理ディスクは、VM ディスク (VHD) の作成および管理を自動で行ってくれる Azure のストレージ サービスの一つです。詳細は 『Azure Managed Disks の概要』 をご覧ください。

    本スクリプトでは、関連付けられている VM がない管理ディスクが、「使用されていない」と見なされます。

    # Find unused disks, where we define a disk is unused iff its owner is null.
    $LostDisks = Get-AzureRmDisk | Where { $_.OwnerId -eq $null }
    
  • ストレージ アカウント

    ストレージ アカウントは、Azure Storage サービスを利用する際に必要となる、Azure リソースのひとつです。詳細は 『Azure ストレージ アカウントについて』 をご覧ください。

    本スクリプトでは、以下の 4 つの条件をすべて満たすストレージ アカウントが、「使用されていない」と見なされます。

    • BLOB ストレージが存在しないか、存在してもすべての BLOB が使用されていない
    • ファイル共有が存在しない
    • テーブル ストレージが存在しない
    • キュー ストレージが存在しない

    ここで、使用されていない BLOB は、以下の条件をすべてみたす BLOB を指します。

    • VM のブート診断時に作成された BLOB (*.screenshot.bmp*.serialconsole.log) である
    • ブート診断した VM はもうすでに存在しない
    
    # Find unused storage account.
    # See the function description if you want to know the definition of "unused".
    $LostStAccounts = Get-AzureRmStorageAccount | Where { $_ | Is-UnusedStorageAccount }
    

ネットワーク関連リソース

本スクリプトでは、4 つの Azure リソースをネットワーク関連リソースと呼んでいます。以下は、それらリソースの概要と、不使用 / 使用中の判定基準の説明です。

  • ネットワーク インターフェイス

    ネットワーク インターフェイス (NIC) は、インターネット / Azure / オンプレミスのリソースと VM の通信を可能にする、Azure リソースの一つです。詳細は 『ネットワーク インターフェイスの作成、変更、削除』 をご覧ください。

    本スクリプトでは、関連付けられている VM がない NIC が、「使用されていない」と見なされます。

    # Get NICs which are no longer attached to any VM.
    $LostNICs = Get-AzureRmNetworkInterface | Where { $_.VirtualMachine -eq $null }
    
  • パブリック IP アドレス

    パブリック IP アドレスは Azure リソースの一つで、インターネットに公開されたサービスと Azure リソースを接続するために、リソースに対して IP アドレスを割り当てる機能をもちます。詳細は 『パブリック IP アドレスの作成、変更、削除』 をご覧ください。

    本スクリプトでは、関連付けられているネットワーク インターフェイスがないパブリック IP アドレスが、「使用されていない」と見なされます。

    # Get public IP addresses detached from NICs.
    $LostIPs = Get-AzureRmPublicIpAddress | Where { $_.IpConfiguration -eq $null -and $_.DnsSettings -eq $null }
    
  • ネットワーク セキュリティ グループ

    ネットワーク セキュリティ グループ (NSG) は、仮想ネットワーク (VNet) へネットワーク トラフィックを管理する Azure リソースの一つです。詳細は 『ネットワーク セキュリティ グループによるネットワーク トラフィックのフィルタリング』 をご覧ください。

    本スクリプトでは、関連付けられた NIC / サブネットがどちらも存在しない NSG が、「使用されていない」と見なされます。

    # Get network security groups (NSGs) detached from both NICs and subnets.
    $LostNSGs = Get-AzureRmNetworkSecurityGroup | Where {$_.NetworkInterfaces.Count -eq 0 -and $_.Subnets.Count -eq 0}
    
  • 仮想ネットワーク

    仮想ネットワーク (VNet) は Azure リソースの一つで、任意の Azure リソースを安全に相互接続するための論理的ネットワークを構築します。詳細は 『Azure Virtual Network』 をご覧ください。

    本スクリプトでは、パブリック IP アドレスをひとつも持たない VNet が、「使用されていない」と見なされます。

    # Get virtual networks which have no public IP address.
    $LostVNets = Get-AzureRMVirtualNetwork | Where { $_.Subnets.IpConfigurations.Count -eq 0 }
    

リソースグループ

  • リソースグループ

    リソース グループは、Azure リソースを保持するコンテナーです。詳細は 『Azure Resource Manager の概要 - リソース グループ』 をご覧ください。

    本スクリプトでは、Azure リソースをひとつも保持していないリソース グループが、「使用されていない」と見なされます。

    $UsedRGNames = Get-AzureRmResource | Select -ExpandProperty ResourceGroupname | Get-Unique
    $LostRGs = Get-AzureRmResourceGroup | Where { $UsedRGNames -notcontains $_.ResourceGroupname }