AZ別に提供されているEC2インスタンスタイプの一覧を出力するPowerShellスクリプト

EC2インスタンスのインスタンスタンスタイプについて。

インスタンスタイプはリージョン毎に提供されるインスタンスタイプが決定されるものではなく、リージョン単位で決定される要素となります。

このため、2022年6月現在。

下記画像のように、AZ名とAZIDが下記のように関連付けされているAWSアカウントにてm6i.xlarge　をみてみると。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/1cf7b0d2-edfc-1068-52d9-57dd4a7f92d6.png)

- ap-northeast-1a が apne1-az4
- ap-northeast-1c が apne1-az1
- ap-northeast-1d が apne1-az2

r6iインスタンスは `ap-northeast-1c（apne1-az1）`では提供されていない事がわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/377a53e7-e422-3a34-4daa-b3f389750e99.png)

## AZ別に提供されるインスタンスタイプを調べる方法

AZ別に提供されるインスタンスタイプを調べる方法としては。

EC2マネジメントコンソールで提供されている[インスタンスタイプ](https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#InstanceTypes:)を参照する。

もしくは下記のナレッジにあるように`aws-cli`の`describe-instance-type-offerings`コマンドを利用してい調べる事ができます。

[EC2 インスタンスの起動時に「Your requested instance type is not supported in your requested Availability Zone (リクエストされたインスタンスタイプはリクエストされたアベイラビリティーゾーンでサポートされていません)」というエラーが表示されるのはなぜですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-instance-type-not-supported-az-error/)

## PowerShellで一覧表示するコマンドを作成してみた

下記画像の用に、一覧を出力するスクリプトを作成してみました。
前提条件として、aws-cliがインストールされている必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/577a4024-7972-1414-3e83-3055cc33e971.png)

やってる事としては、`describe-availability-zones`で取得したAZ別のインスタンスタイプ情報と`describe-availability-zones`で取得したAZ名とAZIDの紐づけを整形して出力している。

`ProfileName`オプションで`aws-cli`で利用するプロファイルを指定する。
指定しない場合はdefaultのプロファイルを利用して実行します。

```PowerShell:Get-EC2InstanceTypeByAZ.ps1
#!/usr/bin/env pwsh
<#
.SYNOPSIS
    AZ別のEC2インスタンスリスト
.DESCRIPTION
    AZ毎に提供されているEC2インスタンスの一覧を出力する。
    aws-cliのインストールが必要    
.EXAMPLE
    PS C:\> Get-EC2InstanceTypeByAZ.ps1
.EXAMPLE
    PS C:\> Get-EC2InstanceTypeByAZ.ps1 -Region ap-northeast-1
    対象となるリージョンを指定（デフォルト 東京）
.EXAMPLE
    PS C:\> Get-EC2InstanceTypeByAZ.ps1 -ProfileName default
    aws-cliで利用するprofileを指定して実行（指定がなければデフォルト）
.EXAMPLE
    PS C:\> Get-EC2InstanceTypeByAZ.ps1 | CovertTo-Json
    Jsonで出力
.PARAMETER Region
    AWS Region
.PARAMETER ProfileName
    aws-cli profile
.OUTPUTS
    Output System.Collections.ArrayList
#>

[CmdletBinding()]
param (
    [Parameter(Mandatory = $false)][String]$Region = 'ap-northeast-1',
    [Parameter(Mandatory = $false)][String]$ProfileName = 'default'
)

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    # AWS_PROFILEが設定されていれば退避
    $oldProfile=$null
    if(Test-Path Env:AWS_PROFILE){
        $oldProfile = (Get-Item Env:AWS_PROFILE).Value
    }

    # パラメータで指定されたプロファイル名をセット
    Set-Item Env:AWS_PROFILE $ProfileName

    $accountId = aws sts get-caller-identity --query Account --output text
    $az = aws ec2 describe-availability-zones --region $region --output json | ConvertFrom-Json | Select-Object -ExpandProperty AvailabilityZones | Group-Object ZoneName -AsHashTable
    $offer = aws ec2 describe-instance-type-offerings --location-type availability-zone --region $region --output json | ConvertFrom-Json | Select-Object -ExpandProperty InstanceTypeOfferings | Group-Object InstanceType -AsHashTable

    # AWS_PROFILEを元に戻す
    Set-Item Env:AWS_PROFILE $oldProfile

    # 出力用構造
    $outputArray = New-Object System.Collections.ArrayList

    # 一覧作成
    foreach ($offerKey in $($offer.Keys | Sort-Object) ) {

        # creteOutputRow
        $outputRow = New-Object PSCustomObject
        $outputRow | Add-Member -MemberType NoteProperty -Name AccountId -Value $accountId
        $outputRow | Add-Member -MemberType NoteProperty -Name InstanceType -Value $offerKey

        foreach ( $azKey in $az.keys) {
            $propertyName = '{0}({1})' -f $az.($azKey).ZoneName , $az.($azKey).ZoneId
            $outputRow | Add-Member -MemberType NoteProperty -Name $propertyName -Value $(if ($azKey -in $offer.($offerKey).Location) { Write-Output '✓' })
        }

        $outputArray.add($outputRow) | Out-Null
    }

    Write-Output $outputArray

}
```

## 総評

いままで`describe-availability-zones`と`describe-availability-zones`からjson形式で出力してExcel（PowerQuery）でマージしたりしてましたが、PowerShellでスクリプト書いてみました。

意外と、AZ毎に提供されているインスタンスタイプに細かい差異があると言うのは忘れがち？　な部分かと思いますので、構築時には意識しておきたいポイントではあります。