【小ネタ】CloudFormationでNAT GWをRouteTableに割り当てると失敗する【CloudFormation】


はじめに

VPCおよびSubnet/RouteTable等をCloudFormationで作成するにあたり、NAT Gatewayの利用が上手くいきませんでした。
結構誰でも見落としてハマりがちなポイントのように思えましたので、記録しておきます。

事象

CloudFormationのStack作成中、NAT GatewayをRouteTableに割り当てた際に失敗する。

具体的には「AWS::EC2::Route」Resourceの作成中に動きが止まり、5分後(恐らくStack作成時のタイムアウト)に下記のように、「Route did not stabilize in expected time」というメッセージが出力され、StackがRollbackします。

原因

templateの記述間違いです。
Internet GatewayをRouteTableに割り当てる場合と、NAT Gatewayを割り当てる場合とで、指定するProperty名が違います。

公式のナレッジセンターにも情報がありました。

CloudFormation のルートが安定しない

詳細

正しい設定

Internet Gateway

まず、Internet Gatewayをデフォルトルート(0.0.0.0/0宛)として割り当てる場合の定義を示します。
以下のResourceはすでに定義済みであるものとします。

  • VPC
  • InternetGateway
  • InternetGatewayAttachment

ここで、「AWS::EC2::Route」であるDefaultPublicRouteに指定するPropertyは「GatewayId」です。

Resources:
# 途中省略
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

NAT Gateway

次に、NAT Gatewayをデフォルトルート(0.0.0.0/0宛)として割り当てる場合の定義を示します。
以下のResourceはすでに定義済みであるものとします。

  • NatGateway1

ここで、「AWS::EC2::Route」であるDefaultPrivateRouteに指定するPropertyは「NatGatewayId」です。

Resources:
# 途中省略
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Condition: enableNatGw
    Properties:
      VpcId: !Ref VPC

  DefaultPrivateRoute:
    Type: AWS::EC2::Route
    Condition: enableNatGw
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway1

間違った設定

うっかり下記のような設定をしてしまいがちなので注意しましょう。
「AWS::EC2::Route」でNAT Gatewayを指定する場合は、「GatewayId」ではなく「NatGatewayId」が正しいです。

Resources:
# 途中省略
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Condition: enableNatGw
    Properties:
      VpcId: !Ref VPC

  DefaultPrivateRoute:
    Type: AWS::EC2::Route
    Condition: enableNatGw
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref NatGateway1 # ←間違い

公式ドキュメント

AWS::EC2::Route - AWS CloudFormation
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html#cfn-ec2-route-natgatewayid

GatwayId

GatewayIdを指定する場合は、Internet GatewayかVirtual Private Gateway(VPN接続の時に利用する仮想ルータのようなもの)のみです。

GatewayId
The ID of an internet gateway or virtual private gateway that is attached to your VPC. For example: igw-eaad4883.

For route entries that specify a gateway, you must specify a dependency on the gateway attachment resource. For more information, see DependsOn Attribute.

Required: Conditional. You must specify only one of the following properties: EgressOnlyInternetGatewayId, GatewayId, InstanceId, NatGatewayId, NetworkInterfaceId, or VpcPeeringConnectionId.

Type: String

Update requires: No interruption

NatGatwayId

NAT Gatewayを利用する場合は、NatGatewayIdを指定します。

NatGatewayId
The ID of a NAT gateway. For example, nat-0a12bc456789de0fg.

Required: Conditional. You must specify only one of the following properties: EgressOnlyInternetGatewayId, GatewayId, InstanceId, NatGatewayId, NetworkInterfaceId, or VpcPeeringConnectionId.

Type: String

Update requires: No interruption