背景
EC2間のSG参照(SG-to-SG)をCloudFormationでコード化する際、「なんとなく!Refで書いたらエラーになった」という、CloudFormation特有の仕様に起因するハマりどころがありました。
1. SG参照はSourceSecurityGroupIdプロパティで表現する
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !GetAtt ClientSecurityGroup.GroupId
Description: MySQL from client SG only
IPアドレス指定のCidrIpに対して、SG参照はSourceSecurityGroupIdという別のプロパティを使います。値には参照先セキュリティグループのID(sg-xxxxx)を指定します。
2. !RefだとSG名が返ってきてエラーになる場合がある
# ハマりやすい書き方
SourceSecurityGroupId: !Ref ClientSecurityGroup # ← VPCが明示されていないSGだと名前が返ることがある
# 確実な書き方
SourceSecurityGroupId: !GetAtt ClientSecurityGroup.GroupId # ← 常にIDを取得
VpcIdを明示していないセキュリティグループに対して!Refすると、CloudFormationの仕様上SGの名前が返ってくる場合があります。しかしSourceSecurityGroupIdはSGのIDを期待するプロパティのため、名前を渡すとエラーになります。!GetAtt ClientSecurityGroup.GroupIdを使えば、常に確実にIDを取得できます。この違いを知らないと、一見正しそうな!Refの書き方でハマります。
3. 参照先のSGは、テンプレート内での定義順序を気にしなくていい
Resources:
ClientSecurityGroup:
Type: AWS::EC2::SecurityGroup
# ...
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
SecurityGroupIngress:
- SourceSecurityGroupId: !GetAtt ClientSecurityGroup.GroupId
コンソールでは「参照される側(クライアントSG)を先に作成する」という手順の順序を意識する必要がありましたが、CloudFormationでは!GetAttによる参照が書かれていれば、CloudFormationが依存関係を自動解析して適切な順序でリソースを作成します。テンプレート内の記述順序自体は問題になりません。
4. 削除時の依存関係もCloudFormationが自動解決する
コンソール版: DBサーバSG → クライアントSGの順で手動削除が必須
CloudFormation版: delete-stack 1本で依存関係を自動解決
コンソールでは「参照している側(DBサーバSG)を先に削除しないと依存関係エラーになる」という順序を毎回意識する必要がありましたが、delete-stackはスタック内の全リソースの依存関係グラフを解析し、正しい順序で自動的に削除してくれます。
5. 2台のEC2を1つのテンプレートで並列管理する
DBInstance:
Type: AWS::EC2::Instance
Properties:
SecurityGroupIds: [!Ref DBSecurityGroup]
ClientInstance:
Type: AWS::EC2::Instance
Properties:
SecurityGroupIds: [!Ref ClientSecurityGroup]
DBサーバとクライアントという役割の異なる2台のEC2を、1つのtemplate.yaml内で別々のリソースとして定義し、それぞれに対応するSGを紐付けています。create-stackは依存関係のないリソース同士を並列に作成するため、コンソールで2回インスタンス起動操作を行うより短時間でデプロイが完了します。
まとめ
!GetAtt ClientSecurityGroup.GroupIdによるSG参照の確実な記述と、CloudFormationによる依存関係の自動解決(作成順序・削除順序の両方)が、このハンズオンの核心でした。コンソールでは意識が必要だった順序管理から解放される点が、IaC化の分かりやすいメリットです。