目的
題名にあるように、NATゲートウェイとVPCエンドポイント(インターフェイス型)をCloudformationの更新で手軽に作成・削除できるようにします。
背景
学習用の自己アカウントの場合、NATゲートウェイや、VPCエンドポイントは頻繁には使用しないけど、プライベートサブネットからの通信を試したい時とかだけに使用したいことってあると思います。
ですが、これらは作成してあるだけでお金が発生してしまうので、都度手動で作成・削除をする必要があります。
NATゲートウェイのルートテーブルの設定だったり、必要なエンドポイントが複数あったりすると、地味にめんどくさいです。
そこで、CloudformationのConditionsを使用して、使用したい時だけ作成できないかなと思い試しました。
実装
テンプレート
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
VpcCidr:
Type: String
VpcId:
Type: String
PublicSubnetAId:
Type: String
PrivateVpceSubnetAId:
Type: String
PrivateRouteTableAId:
Type: String
#Option
NATGatewayA:
Description: "Whether to use NAT Gateway"
Type: String
Default: "do not use"
AllowedValues:
- "use"
- "do not use"
SessionManager:
Description: "whether to use a session manager"
Type: String
Default: "do not use"
AllowedValues:
- "use"
- "do not use"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
-
Parameters:
- VpcCidr
- VpcId
- PublicSubnetAId
- PrivateVpceSubnetAId
- PrivateRouteTableAId
-
Label:
default: "Option"
Parameters:
- NATGatewayA
- SessionManager
Conditions:
IsNatGtwA: !Equals ["use", !Ref NATGatewayA]
IsSessionManager: !Equals ["use", !Ref SessionManager]
Resources:
# ------------------------------------------------------------#
# NatGateway
# ------------------------------------------------------------#
NatGatewayA:
Type: AWS::EC2::NatGateway
Condition: IsNatGtwA
Properties:
AllocationId: !GetAtt NatGatewayEIPA.AllocationId
SubnetId: !Ref PublicSubnetAId
# NATゲートウェイ用のEIP
NatGatewayEIPA:
Type: AWS::EC2::EIP
Condition: IsNatGtwA
Properties:
Domain: vpc
# ------------------------------------------------------------#
# Routing
# ------------------------------------------------------------#
# Private RouteA Create
PrivateRouteA:
Type: "AWS::EC2::Route"
Condition: IsNatGtwA
Properties:
RouteTableId: !Ref PrivateRouteTableAId
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGatewayA
# ------------------------------------------------------------#
# SG
# ------------------------------------------------------------#
# VPCエンドポイント用のSG
VpceSg:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "VpcEndpoint-SG"
GroupName: "VpcEndpoint-Sg"
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
FromPort: -1
ToPort: -1
IpProtocol: "-1"
SecurityGroupIngress:
- CidrIp: !Ref VpcCidr
Description: "VPC CIDR"
FromPort: 443
ToPort: 443
IpProtocol: "tcp"
VpcId: !Ref VpcId
# ------------------------------------------------------------#
# VPC EndPoint
# ------------------------------------------------------------#
# セッションマネージャに必要なVPCエンドポイント(monitoring)
VpcEndPointMonitoring:
Type: AWS::EC2::VPCEndpoint
Condition: IsSessionManager
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref VpceSg
ServiceName: !Sub "com.amazonaws.${AWS::Region}.monitoring"
SubnetIds:
- !Ref PrivateVpceSubnetAId
VpcEndpointType: "Interface"
VpcId: !Ref VpcId
# セッションマネージャに必要なVPCエンドポイント(ssm)
VpcEndPointSsm:
Type: AWS::EC2::VPCEndpoint
Condition: IsSessionManager
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref VpceSg
ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"
SubnetIds:
- !Ref PrivateVpceSubnetAId
VpcEndpointType: "Interface"
VpcId: !Ref VpcId
# セッションマネージャに必要なVPCエンドポイント(ssmmessages)
VpcEndPointSsmMessege:
Type: AWS::EC2::VPCEndpoint
Condition: IsSessionManager
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref VpceSg
ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssmmessages"
SubnetIds:
- !Ref PrivateVpceSubnetAId
VpcEndpointType: "Interface"
VpcId: !Ref VpcId
# セッションマネージャに必要なVPCエンドポイント(ec2messages)
VpcEndPointEc2Messege:
Type: AWS::EC2::VPCEndpoint
Condition: IsSessionManager
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref VpceSg
ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2messages"
SubnetIds:
- !Ref PrivateVpceSubnetAId
VpcEndpointType: "Interface"
VpcId: !Ref VpcId
# セッションマネージャに必要なVPCエンドポイント(ec2)
VpcEndPointEc2:
Type: AWS::EC2::VPCEndpoint
Condition: IsSessionManager
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref VpceSg
ServiceName: !Sub "com.amazonaws.${AWS::Region}.ec2"
SubnetIds:
- !Ref PrivateVpceSubnetAId
VpcEndpointType: "Interface"
VpcId: !Ref VpcId
説明
- Parameters
コメント(Option)以下でNatゲートウェイおよびセッションマネージャの使用有無を選択できるようにしています。 - Conditions
それぞれのパラメータの値を判定する条件を定義しています。- 「use」と等しかった場合、true
- 「use」以外(「do not use」)だった場合、false
- Resources
- NatGatewayA,NatGatewayEIPAのConditionでConditionsで定義した条件を指定しています。
IsNatGtwAの結果がtrueだった場合のみこれらのリソースは作成されます。 - VPCエンドポイントの方も指定している条件が違うのみでやっていることは同じです。
こちらでは条件にIsSessionManagerを指定しています。
- NatGatewayA,NatGatewayEIPAのConditionでConditionsで定義した条件を指定しています。
作成・削除
オプションをデフォルトの状態でスタックを作成します。
そうするとVPCエンドポイント用のSGのみ作成された状態になります。
②オプションを指定して作成
更新>現在のテンプレートの使用>オプションの値を変更
更新が完了するとNATゲートウェイとセッションマネージャに必要なVPCエンドポイントが作成されます。
③不要になったら削除
手順は作成の時と同じで、オプションの値を「do not use」に変更して、更新するだけです。
最後に
今回のようにプライベートサブネットにあるEC2にセッションマネージャを使用して接続したい場合、4つのVPCエンドポイントが必要になります。そんな時は更新一発で作成してくれるのはとても楽です。
自分と同じように、毎回作成・削除がめんどくさいなと感じている人の参考となれば幸いです。