[小ネタ]CloudFormationでも明示的な依存関係を指定する必要があった

AWS CloudFormation は、可能な限り並行してリソースを作成、更新、削除します。その際、並行して処理できるテンプレート内のリソースとオペレーションの実行順序を左右する依存関係とが自動的に判断されます。DependsOn を使用して依存関係を明示的に指定することで、デフォルトの並列処理をオーバーライドし、それらのリソースを決まった順序で処理するように CloudFormation に命令することができます。
2020.02.04

はじめに

こんにちは。大阪オフィスの林です。

CloudFormationでTransitGateway(以下、TGW)絡みの環境作っていたら依存関係で少しつまずいたので備忘でまとめておきたいと思います。

やりたかったこと

下記環境をデプロイする1つのCFnのテンプレートを作ろうとしていました。

  • VPC作成、サブネット作成
  • TGW作成、VPCとサブネットをアタッチ
  • RouteTable作成、指定のCIDR向けの通信のデフォルトGWをTGWとするルーティング設定
  • つまずき

    スタック作成しテンプレートを流したところルーティングの設定の部分でエラーになりました。
    The transitGateway ID 'tgw-0d9075669fdfa268e' does not exist. (Service: AmazonEC2; Status Code: 400; Error Code: InvalidTransitGatewayID.NotFound; Request ID: 65d30b58-4238-45b4-8df8-150981ac9ee9)

    状況の把握と切り分け

    状況を整理してみました。

  • TGWの作成は正常に完了している模様
  • TGWをGWとするルーティング設定で「そんなTGWのIDは無い」と怒られている
  • TGWをGWとするルーティング設定とTGWへのVPC&サブネットのアタッチが並行で作成開始している
  • TGWをGWとするルーティング設定を別スタックとしたところ正常終了した
  • 依存関係が怪しいと思いつつもCloudFormationってそのあたりの依存関係はよしなにやってくれるはずなんだけどなぁと色々調べていると過去の弊社阿部のブログが出てきましたΣ(・□・;)

    内容としてはニアリーですが遭遇したケースが違ったので記事としてまとめておきたいと思います。

    結論

    結論を申し上げると、ルーティング設定のリソースに「DependsOn属性」をつけてあげる必要がありました。公式はこちら
    公式のページにはDependsOn 属性が必要なときというトピックがあり、幾つか例が挙げられているので、ご自身の環境と照らし合わせて確認頂ければと思います。

    やってみた

    並列作成となっていた『TGWへのVPC&サブネットのアタッチ』と『ルーティング設定』に「DependsOn属性」をつけて依存関係(アタッチが終わった後にルーティング設定)を明示的に指定しました。

    (省略)
    
    # ------------------------------------------------------------#
    # TransitGateway
    # ------------------------------------------------------------#
      TransitGateway:
        Type: AWS::EC2::TransitGateway
        Properties: 
          Tags:
            - Key: Name
              Value: !Sub ${SystemName}-${EnvType}-my-tgw01
      TransitGatewayAttachment:
        Type: AWS::EC2::TransitGatewayAttachment
        Properties: 
          SubnetIds: 
            - !Ref devpub01
            - !Ref devpub02
          TransitGatewayId: !Ref TransitGateway
          VpcId: !Ref myvpc
    
    # ------------------------------------------------------------#
    # Routing
    # ------------------------------------------------------------#
      pubmyroutetable01routeTGW:
        Type: "AWS::EC2::Route"
        Properties:
          DestinationCidrBlock: 10.1.1.0/24
          TransitGatewayId: !Ref TransitGateway
          RouteTableId: !Ref pubmyroutetable01
        #これを追加  
        DependsOn: TransitGatewayAttachment
        
    (省略)
    

    まとめ

    CloudFormationは依存関係をすべてよしなにやってくれるという先入観からあまり意識していなかったのですが、非常に勉強になったつまずきでした!同じようにTGWとルーティング作成などCloudFormation内での依存関係でつまずいているかたの参考になれば幸いです。

    以上、大阪オフィスの林がお送りしました!