背景
パブリックサブネット(APサーバ)とプライベートサブネット(DBサーバ)に分離した2層構成をCloudFormationで自動構築しました。コンソール版で体験した「S3 VPC Endpointがないとプライベートサブネットのdnf installが失敗する」という問題を、CloudFormationではどう解決しているかに焦点を当てます。
1. DependsOnでリソースの作成順序を明示する
DBInstance:
Type: AWS::EC2::Instance
DependsOn:
- S3VPCEndpoint
- PrivateSubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet
UserData:
Fn::Base64: |
#!/bin/bash
dnf install -y mariadb105-server mariadb105
DBサーバのUserDataは起動直後にdnf installを実行しますが、この時点でS3 VPC Gateway Endpointとプライベートルートテーブルへの関連付けが完了している必要があります。DependsOnにこの2つのリソースを明示することで、CloudFormationは「S3VPCEndpointとルート関連付けが完了してからDBInstanceを作成する」という順序を保証します。これがないと、S3向けルートの反映前にUserDataが走り、パッケージインストールが失敗する可能性があります。
2. SubnetIdでEC2の配置サブネットを明示する
APInstance:
SubnetId: !Ref PublicSubnet # パブリックサブネットに配置
DBInstance:
SubnetId: !Ref PrivateSubnet # プライベートサブネットに配置
コンソールでは「ネットワーク設定」画面でサブネットを選択する操作でしたが、CloudFormationではSubnetIdプロパティに!Refでサブネットのリソースを渡すだけです。APサーバとDBサーバでそれぞれ異なるサブネットを指定することで、パブリック/プライベートの配置がコードとして明示されます。
3. VpcIdを指定したSGでないと!GetAttが名前を返すことがある
APSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC # カスタムVPCを指定(必須)
DBSecurityGroup:
SecurityGroupIngress:
- SourceSecurityGroupId: !GetAtt APSecurityGroup.GroupId # !Refではなく!GetAtt
VpcIdを明示していないセキュリティグループに対して!Refすると、SGの名前が返ってくる場合があります。しかしSourceSecurityGroupIdはSGのIDを期待するプロパティのため、!GetAtt APSecurityGroup.GroupIdで確実にIDを取得する必要があります。
4. S3 VPC Gateway EndpointはRouteTableIdsを配列で複数渡せる
S3VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Gateway
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
RouteTableIds:
- !Ref PrivateRouteTable
今回はプライベートルートテーブルのみに紐付けていますが、RouteTableIdsは配列なので複数のルートテーブルに同時にS3向けルートを追加することもできます。無料のGatewayタイプのエンドポイントなので、コスト面を気にせず必要なルートテーブルすべてに紐付けられます。
5. スタック名は必ず英字始まりにする
エラー: stackName failed to satisfy regular expression pattern
原因: --stack-name の先頭が数字だった
対処: 英字から始まる名前に変更する
CloudFormationのスタック名には正規表現の制約があり、数字始まりの名前だとバリデーションエラーになります。地味に見落としやすいポイントです。
まとめ
DependsOnによるリソース作成順序の制御と、SubnetIdによるパブリック/プライベート配置の明示が、このハンズオンでのCloudFormation活用のポイントでした。コンソール版で「S3 VPC Endpoint作成→EC2起動」という操作順序を人間が意識する必要があった部分を、CloudFormationはDependsOnという1行で機械的に保証してくれます。