Availability Zone によって利用可能な EC2 インスタンスタイプは異なります

記事タイトルとURLをコピーする

こんにちは。コーポレートエンジニアリング部の橋本 (@hassaku_63)です。

us-east-1 で EC2 構築する手順が含まれるワークショップをしていたら予想外の場所でハマってしまい、色々調べていたら掲題のような話に行き着きました。

普段は Step Functions や Lambda ばかりなので EC2 はおろか VPC すらほとんど触ることがない私なのですが、せっかくの機会なので色々調べてみましたのでその結果を共有しようと思います。

結論

最終的に言いたいことに対して過程の話が長いので、先にこの記事の結論を述べます。

us-east-1 を使う場合、 use1-az3 には(少なくとも)EC2 を作らない方が無難です。

use1-az3 で提供されている EC2 インスタンスタイプは極端に少ないです。ざっくり集計した結果、us-east-1 リージョン全体で提供されている約 760 種類に対し use1-az3 でサポートされているのは約 8% ほどで、例えば t3 系や m5 系などが利用不可能です。

よって、これから us-east-1 で EC2 を作る場合は、use1-az3 を利用しないように留意すると良いでしょう。また、教育用のワークショップコンテンツの作成を担われている方なども、us-east-1 を利用する場合はこの AZ を回避するように設計するのが良いと思います。

(補足)普段の私たちは AZ を呼ぶとき AZ Name で会話することが多く、あまり AZ ID を意識することはありません。また、AWS アカウントによって AZ ID と Name の対応関係は異なります。ご自身のアカウントにおいて use1-az3 がどの AZ に割り当てられているかは、以下のようなコマンドで確認できます。ご自身の AWS アカウントで適宜 AZ Name に読み替えてください。

$ aws ec2 --region us-east-1 describe-availability-zones \
    | jq -r '.AvailabilityZones[] | [.ZoneId, .ZoneName] | @tsv'

# use1-az1        us-east-1a
# use1-az2        us-east-1b
# use1-az4        us-east-1c
# use1-az6        us-east-1d
# use1-az3        us-east-1e
# use1-az5        us-east-1f

はじめに

あるワークショップを試していたら、Availability Zone によって利用可能な EC2 インスタンスタイプに差があることに気づきました。

そのワークショップは us-east-1 の3つの AZ を利用してインスタンスを構築する手順が含まれていました。 作成したサブネットの中に us-east-1e があり、この AZ で t3.micro はサポートされない旨のエラーが発生しました。

※私の環境では us-east-1e でしたが、最初に述べたようにアカウントによって AZ ID と AZ Name の対応関係は異なります。以降は us-east-1e という名称を AZ ID = use1-az3 の話として置き換えて読み進めてください。

$ aws ec2 run-instances # with options
An error occurred (Unsupported) when calling the RunInstances operation: Your requested instance type (t3.micro) is not supported in your requested Availability Zone (us-east-1e). Please retry your request by not specifying an Availability Zone or choosing us-east-1a, us-east-1b, us-east-1c, us-east-1d, us-east-1f.

An error occurred (Unsupported) when calling the RunInstances operation: Your requested instance type (t3.micro) is not supported in your requested Availability Zone (us-east-1e). Please retry your request by not specifying an Availability Zone or choosing us-east-1a, us-east-1b, us-east-1c, us-east-1d, us-east-1f.

us-east-1e でのみ t3.micro が利用できないようです。このエラーを調べていみると、どうやら以下が原因であるようでした。

  • 私の AWS アカウントでは、AZ us-east-1e は AZ ID = use1-az3 に割り当てられている
  • AZ ID = use1-az3 では、t3.micro は利用できない

AZ によって AWS のデータセンターのキャパシティは異なり、サポートされているはずのインスタンスタイプであっても時折起動に失敗する事象があります。 比較的大きな、もしくは利用者の分布が薄いレアなインスタンスタイプを起動する用事のある方なら、遭遇したことがあるかもしれません。今回のエラーもその類かと思ったのですがどうもそうではなく、「そもそも AZ ごとに利用可能なインスタンスタイプは異なる」という話でした。

さらに調べてみると、EC2 DescribeInstanceTypeOfferings API を使うことで AZ ごとに利用可能なインスタンスタイプを取得できることがわかりました。

この結果を集計してみたところ、us-east-1 の AZ ごとに提供状況にばらつきがあることがわかりました。提供状況が全く同じになる AZ は(ぱっとみ)なさそうでした。

us-east-1 と我らが ap-northeast-1 で集計を取ってみました。

ソースコード

手元にデータを引っ張ってくるために使用したコードなどをこちらで公開しています。

https://github.com/hassaku63/check-aws-ec2-instance-type-offerings/tree/main

github.com

README で説明してないコードなどもありますしところどころ雑な実装になってると思いますが、ご容赦ください。

一応、README に書いてある内容をなぞっていただければ、最終的には以下のようなテーブルを持つ SQLite のデータベースファイルがお手元に作成できるはずです。

CREATE TABLE az (
            ZoneId TEXT NOT NULL PRIMARY KEY,
            ZoneName TEXT NOT NULL,
            RegionName TEXT NOT NULL,
            ZoneType TEXT NOT NULL,
            State TEXT NOT NULL
        );
CREATE TABLE instance_type_offerings (
            InstanceType TEXT NOT NULL,
            LocationType TEXT NOT NULL,
            Location TEXT NOT NULL,
            PRIMARY KEY (Location, InstanceType)
        );

az が AZ の ID -> Name の対応を取るためのテーブルで、instance_type_offerings が提供されているインスタンスタイプを保持するテーブルです。

基本的には instance_type_offerings を AZ ID 指定や InstanceType を LIKE で指定することでサポート状況が確認可能です。

ただし、これらのテーブルだけだと「提供されていないインスタンスタイプ」を含めた全体の状況が見えにくいので、その目的が達成しやすくなるようなビュー(以下)も作成しています。

CREATE VIEW exists_in_location_view AS
SELECT 
    it.InstanceType, 
    loc.Location, 
    CASE 
        WHEN it2.InstanceType IS NOT NULL THEN 1
        ELSE 0
    END as ExistsInLocation
FROM 
    (SELECT DISTINCT Location FROM instance_type_offerings WHERE LocationType = 'availability-zone-id') loc
CROSS JOIN 
    (SELECT DISTINCT InstanceType FROM instance_type_offerings WHERE LocationType = 'availability-zone-id') it
LEFT JOIN 
    instance_type_offerings it2 ON it.InstanceType = it2.InstanceType AND loc.Location = it2.Location
ORDER BY 
    loc.Location,
    it.InstanceType
/* exists_in_location_view(InstanceType,Location,ExistsInLocation) */;

AZ やタイプごとのサポート状況を広めに調べたい用事が目的なら exists_in_location_view をクエリすると良いでしょう。サンプルクエリは以下の要領です。

sqlite> .headers ON
sqlite> .separator "\t"
sqlite> SELECT Location, InstanceType, ExistsInLocation FROM temp.exists_in_location_view WHERE Location = 'use1-az3' and InstanceType LIKE 't3.%';
-- Location        InstanceType    ExistsInLocation
-- use1-az3        t3.2xlarge      0
-- use1-az3        t3.large        0
-- use1-az3        t3.medium       0
-- use1-az3        t3.micro        0
-- use1-az3        t3.nano 0
-- use1-az3        t3.small        0
-- use1-az3        t3.xlarge       0

 成果物

tsv を上記レポジトリの output/ で公開しています。

インスタンスタイプのサポート状況が極端に貧弱な AZ は use1-az3 だけでした。us-east-1 の他の AZ、および ap-northeast-1 では、AZ 間でそれほど顕著な違いはない印象です。

ご自身で直接確認したい方はこのディレクトリ配下の tsv を見てください。この記事では時間のない方のためにこちらで用意した簡単な可視化の結果をお見せします。

まずは、us-east-1 と ap-northeast-1 でそれぞれ作成した簡易ヒートマップを以下に示します。見ての通りめちゃくちゃ縦長で大変見づらいのが恐縮ですが、ご容赦ください。ファミリー単位で集約してもまだ 100 種類以上のバリエーションがあるためどうあっても縦長になってしまうなと諦めました。Seaborn を使って可視化を行いました。

us-east-1 での AZ ごとのインスタンスタイプファミリーの提供状況を示すヒートマップ

ap-northeast-1 での AZ ごとのインスタンスタイプファミリーの提供状況を示すヒートマップ

ヒートマップをぱっとみすると、us-east-1 では use1-az3 の提供状況が極端に悪いこと、ap-northeast-1 の中では apne1-az2 が比較的提供状況が悪そうに見えることがわかります。

具体的な数を確認するために、簡易的に AZ ごとのカバレッジを算出してみました。どちらも母数となるインスタンスタイプは 761 種類です。

AZ ID Coverage (%) / N=761
use1-az1 73.32
use1-az2 97.5
use1-az3 8.41
use1-az4 98.03
use1-az5 84.23
use1-az6 99.34
apne1-az1 80.42
apne1-az2 71.75
apne1-az4 84.36

use1-az3 だけが顕著にカバレッジが低いことがわかります。よって、現時点ではこれから us-east-1 を利用する場合はできるだけ use1-az3 を避けた方が良い、と言えそうです。use1-az1 も、az2, az4, az6 の3つと比べると低水準です。この集計結果には旧世代のインスタンスタイプも多数含まれていることもあり、大方の普段遣いには支障ないと思います。が、普段あまり利用しないインスタンスタイプを検討している場合は事前に確認しておくと良さそうです。

ap-northeast-1 では、apne1-az2 に凹みが見られるものの、AZ ごとのカバレッジに極端な差はありませんでした。その意味では、ap-northeast-1 は AZ ごとのサポート状況に関しては安定しておりそれほど AZ ごとの差を気にする必要はないと言えそうです。一方で、us-east-1 (use1-az3 以外) と比べると平均的にカバレッジが低い印象です。

個別のインスタンスタイプ・ファミリーに注目した考察は行っていませんが、例えば m7a, m7i, r7a, r7i といった、本日時点で比較的新しいファミリーは ap-northeast-1 では利用できず、us-east-1 の一部 AZ でのみ利用可能でした。

日本より先に本国でサービス提供が開始されるのはよくあることなので、そうした事情もこのカバレッジ傾向の理由のひとつでしょう。

Excel では

上記の可視化と同等なことを Excel でやる方法もご紹介しておきます。

output/ 以下の tsv を使用します。tsv は以下のような形式をしています。

InstanceTypeLocation の組み合わせに対して、ExistsInLocation の値が 1 であればそのインスタンスタイプはその AZ で利用可能であることを意味します。

InstanceType Location ExistsInLocation
a1.2xlarge use1-az1 0
a1.2xlarge use1-az2 1
a1.2xlarge use1-az3 0
a1.2xlarge use1-az4 1
a1.2xlarge use1-az5 0
a1.2xlarge use1-az6 1

InstanceType は 760 種類くらいのバリエーションがあるのでそのままだと可視化が難しいです。よって、インスタンスファミリーの単位でグループ化したものを用意します。

Excel でこの tsv を読み込み、インスタンスタイプのファミリーを導出する簡易的な処理を適用した列を追加します。

# Excel のセル値の一例。ここでは A2 がインスタンスタイプのセル
=LEFT(A2, FIND(".", A2, 1)-1)

追加した列を InstanceFamily とします。InstanceFamilyLocation でピボットテーブルを作成し、ExistsInLocation の値を集計します。

ここで得られたピボットテーブルを更に加工します。インスタンスファミリーごとに、そのファミリーの中で最もサポート状況が良い AZ の状況を基準として、その他の AZ のサポート状況の割合を出します。 つまり、 InstanceFamily の行ごとに、その行の中の最大値を基準 (=100%) とする正規化を行います。

ここまですると、インスタンスファミリーごとで各 AZ のサポート状況を(簡易的に)パーセンテージで表現できるようになります。テーブル内のセルの値域が 0 〜 1.0 となるので、このテーブル全体にカラースケールを適用します。

ここまでの手順を経由することで、簡易的なヒートマップができます。

(注: ここでご紹介した集計方法では、リージョン単位でサポートから外れているインスタンスタイプを厳密に考慮しきれていません。よって、カバレッジ等本記事で公開した集計結果も簡易的なものであり、正確な数字ではない可能性があることをご了承ください)

終わりに

普段我々はハードウェアリソースの調達を意識せずに AWS を利用できますが、今回の件は裏の物理的なデータセンターを意識する機会になり大変興味深く感じました。

また、今回の話は主にインフラ寄りのエンジニアにより需要のある話だと思いますが、アプリケーションから少し離れたレイヤーであっても、ちょっとした(そして踏み抜く前に気づきたい)仕様の確認のためにちょっとしたコードが書けると自分でやれることの幅が広がっていいよね〜、というのを改めて感じました。やっぱ The Bezos (API) Mandate の思想は最高です(?)

やってることは簡単な集計ですが、このへんの話を一連のそれっぽいコードにまとめようと思うと結構な時間を食ってしまったのでまだまだ精進が必要だなと思いました。自分はどちらかと言えばアプリケーション寄りの人間(であるはず)なので、このくらいはサクッとできなきゃなぁ...と反省しました。とはいえ普段さほど触る機会のない領域のコーディングは楽しかったです。

橋本 拓弥(記事一覧)

プロセスエンジニアリング部

業務改善ネタ多め & 開発寄りなコーポレートエンジニアです。普段は Serverless Framework, Python, Salesforce あたりと遊んでいます