3AZ構成CloudFormationのデプロイに失敗したので対処してみた (!GetAZsが全AZを返さない)

3AZ構成CloudFormationのデプロイに失敗したので対処してみた (!GetAZsが全AZを返さない)

CloudFormation で 3AZ 構成をデプロイしようとした際、Fn::Select エラーが発生しました。原因は !GetAZs が一部の AZ を返さないこと。実はこの関数、デフォルトサブネットの状態によって挙動が変わる仕様でした。事象の詳細と解決策を紹介します。
2026.01.18

CloudFormation で 3AZ 構成の VPC を東京リージョン(ap-northeast-1)にデプロイしようとしたところ、以下のエラーが発生しました。

Template error: Fn::Select cannot select nonexistent value at index 2.

テンプレートでは !GetAZs で取得したAZリストの3番目(index 2)を参照していました。

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
  Subnet3:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [2, !GetAZs '']  # ← ここでエラー

東京リージョンであれば !GetAZs は通常3つのAZを返すはずが、実際には2つしか返していないようでした。この事象の原因調査を行う機会がありましたので紹介します。

EC2 API との比較

念のため、EC2 API (AWS CLI) で東京リージョンの利用可能なAZを確認しました。

$ aws ec2 describe-availability-zones --region ap-northeast-1 \
  --query 'AvailabilityZones[*].ZoneName' --output table
-------------------------------
|DescribeAvailabilityZones  |
+---------------------------+
|  ap-northeast-1a          |
|  ap-northeast-1c          |
|  ap-northeast-1d          |
+---------------------------+

API 経由では問題なく3つのAZ(1a, 1c, 1d)が返ってきています。
「EC2 API では3つ見えるのに、CloudFormation の !GetAZs では2つしか取得できない」という乖離が発生していました。

根本原因

調査の結果、デフォルトサブネットの状態が影響していることが分かりました。以下のコマンドで確認します。

$ aws ec2 describe-subnets \
  --filters "Name=default-for-az,Values=true" \
  --region ap-northeast-1 \
  --query 'Subnets[*].[AvailabilityZone,SubnetId]' \
  --output table
-----------------------------------------
|           DescribeSubnets            |
+------------------+-------------------+
|  ap-northeast-1a |  subnet-xxxxxxxx  |
|  ap-northeast-1c |  subnet-yyyyyyyy  |
+------------------+-------------------+
# ap-northeast-1d が欠落している

出力結果の通り、ap-northeast-1d のデフォルトサブネットが存在していませんでした。

このアカウントは2018年の ap-northeast-1d リリース前から利用しており、当時 1d 未サポートのAMIを利用する関係で、サブネットを除外していた可能性がありました。

参考: 東京リージョンに4つ目のアベイラビリティゾーン(ap-northeast-1d)ができました! | DevelopersIO

AWS CloudFormation 公式ドキュメントには、Fn::GetAZs の挙動について以下の記述があります。

The Fn::GetAZs function returns only Availability Zones that have a default subnet unless none of the Availability Zones has a default subnet; in that case, all Availability Zones are returned.

AWS CloudFormation - Fn::GetAZs

要約すると、!GetAZs の挙動は以下のようになります。

  1. デフォルトサブネットが1つでも存在する場合
    → デフォルトサブネットが存在する AZ のみを返す(今回のケース)
  2. デフォルトサブネットが1つも存在しない場合
    → そのリージョンのすべての AZ を返す

今回は「一部のAZ(1a, 1c)にだけデフォルトサブネットがある」状態だったため、1d がリストから漏れる状況が発生しました。

解決策

今回の問題が発生したAWSアカウントは検証環境でした。
ハンズオンや、EC2 Image Builder などで デフォルトVPCを利用する可能性があるため、デフォルトサブネットの追加で対処しました。

解決策1: デフォルトサブネットを作成する

欠落している AZ(今回は ap-northeast-1d)にデフォルトサブネットを作成します。

aws ec2 create-default-subnet --availability-zone ap-northeast-1d

これにより「全てのAZにデフォルトサブネットがある状態」となり、!GetAZs が3つのAZを返すようになります。既存のデフォルトVPCを維持したい場合はこちらが有効です。

解決策2: デフォルトVPCを削除する

デフォルトVPC自体を完全に削除します。

aws ec2 delete-vpc --vpc-id vpc-xxxxx

前述の仕様通り、「デフォルトサブネットが1つも存在しない場合」は全AZが返されるため、これでも !GetAZs は3つのAZを返すようになります。

まとめ

CloudFormation の !GetAZs は、単純に「リージョンの全AZ」を返すわけではなく、デフォルトVPCおよびデフォルトサブネットの存在により、挙動が変わります。EC2 API やVPCダッシュボードに表示されるAZが得られない場合、デフォルトサブネットの欠落を疑ってみてください。

また、開発・検証環境などを除き、特に本番運用環境においてはリスク要因となるデフォルトVPCについて、その削除も検討することをお勧めします。

https://dev.classmethod.jp/articles/should-not-use-the-default-vpc/

この記事をシェアする

FacebookHatena blogX

関連記事