See: https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_NAT_Instance.html
NAT ゲートウェイだと楽なんだけど、あまり性能いらないのに高かったので NAT インスタンスを作成した。
NAT インスタンスでは "送信元/送信先チェック" を無効にしなきゃいけないんだけど、instance attribute の変更は CloudFormation でできないようなので、UserData で初回起動時にコマンド実行するようにした。
下記は Availability Zone ap-northeast-1a
に作成する例。
# セキュリティグループ
SecurityGroupNat:
Type: AWS::EC2::SecurityGroup
Properties:
SecurityGroupIngress:
- CidrIp: (サブネットのアドレス範囲)
Description: HTTP
FromPort: 80
IpProtocol: tcp
ToPort: 80
- CidrIp: (サブネットのアドレス範囲)
Description: HTTPS
FromPort: 443
IpProtocol: tcp
ToPort: 443
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
Description: HTTP
FromPort: 80
IpProtocol: tcp
ToPort: 80
- CidrIp: 0.0.0.0/0
Description: HTTPS
FromPort: 443
IpProtocol: tcp
ToPort: 443
VpcId: (VPC の ID)
# "送信元/送信先チェック" を無効にするコマンドを実行するための IAM プロファイル/ロール
NatInstanceProfile:
DependsOn:
- NatInstanceRole
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref NatInstanceRole
NatInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Policies:
-
PolicyDocument:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:ModifyInstanceAttribute",
"Resource": "*" # ModifyInstanceAttribute はリソースの制限はできないみたい...
}
]
}
PolicyName: allow-modify-instance-attribute
# NAT インスタンス
NatInstance:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: ap-northeast-1a
IamInstanceProfile: !Ref NatInstanceProfile
ImageId: ami-00d29e4cb217ae06b # マーケットプレイスで amzn-ami-vpc-nat で検索して選ぶ
InstanceType: t3.nano
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
DeviceIndex: "0"
GroupSet:
- !Ref SecurityGroupNat
SubnetId: (サブネットの ID)
# "送信元/送信先チェック" を無効にするコマンドを初回起動時に実行
UserData:
'Fn::Base64': |
#!/bin/bash
INSTANCEID=$(curl -s -m 60 http://169.254.169.254/latest/meta-data/instance-id)
aws --region ap-northeast-1 ec2 modify-instance-attribute --instance-id $INSTANCEID --source-dest-check "{\"Value\": false}"