0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudFormationでSG参照を書くとき`!Ref`ではなく`!GetAtt ... .GroupId`を使う理由

0
Posted at

背景

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化の分かりやすいメリットです。

→ CloudFormationでEC2 MySQLのDBサーバをIaC化するハンズオン(ブログ)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?