AWS CloudFormationでNATインスタンスを含む構成を構築しました。
CloudFormationを使うと複数のリソースをコマンド1つで構築・破棄できて大変便利です。
AWS CloudFormationとは
公式から分かりやすい図が公開されています。
YAMLかJSONで記述したテンプレートから、VPCやインスタンス等の様々なリソースをまとめて作成できます。
AWS CloudFormation (設定管理とオーケストレーション) | AWS
- YAMLかJSONにテンプレートを記述する
- テンプレートをS3にアップロードする
- テンプレートを実行する
- スタックと呼ばれるリソースの集合がテンプレート通りに作られる
- スタックを削除すればスタック内の全リソースが削除される
目指す構成
以前、マネージメントコンソールから構築したものと同じ構成です。
- 踏み台サーバー1台
- NATインスタンス1台
- 開発用サーバー1台
手順
※ テンプレートファイルの設定を全て書くと長くなるので詳細は割愛します。
[1] デザイナーでテンプレート作成
CloudFormationを使うのは初めてということで、序盤はデザイナーを使ってテンプレートを作成しました。
デザイナーを使うと図面を作るような感覚でテンプレートを作成できます。
慣れたらデザイナーを使わずに済みますが、初めはデザイナーを使うと簡単かつ慣れたので使ってよかったです。
[1-1] デザイナー画面を開く
[テンプレートのデザイン]を押すと、以下のような画面が開きます。
[1-2] 部品を置く
左のメニューから部品を探しドラッグ&ドロップすると、置いた部品のテンプレートが自動で記述されます。
JSONとYAML形式のうち「YAML形式」を今回は使います。
ラジオボタンの選択でJSONとYAMLの変換はいつでも行えます。
まずは、VPC, Subnet, RouteTable, InternetGatewayを配置しました。
[1-3] 部品をつなげる
部品同士の関連を記述していきます。
このインターネットゲートウェイはこのVPCに属している、このサブネットはこのルートテーブルと関連付けしている、等です。
部品外枠のマルをドラッグして、繋げたい部品にドロップします。
以下は、インターネットゲートウェイとVPCをつなぐ例です。
"VPCGatewayAttachment"という要素がテンプレートに追加されました。
[1-4] テンプレートの書き方
Resources直下の名称(下記ではNatVpc)は論理IDで、テンプレート内でユニークな必要があります。
他の部品との依存関係の記述などで使用されています。
半角英数字ならば、自由に変更できます。
デザイナーで変更すると、依存関係等の部分も自動で変更してくれます。
Propertiesに何を書けばよいかは、各部品の説明ページを見ると、ある程度分かります。
部品を右クリックしてハテナマークを選択すると、その部品の説明ページに飛びます。
VPCには、CIDRブロックと名称を追記しました。
[1-5] 保存
左上のファイルメニューの[保存]を選択します。
ローカルとS3、どちらのも保存できます。
S3に保存すると、自動でバケットが作成されバケット内にテンプレートが保存されます。
[2] お試しでスタック作成
インスタンスやストレージはありませんが、この状態でスタックを作成してみます。
万が一失敗したりセキュリティが甘くても、惨事にならずに済むので、ひとまずこの状態で作成して問題がないか確認していきます。
[2-1] 作成
[新しいスタックの作成]を選択します。
テンプレートの選択画面で先程保存したテンプレートのURLを入力します。
以降は特別な入力はなく作成まで行います。
[2-2] 作成結果の確認
スタックを作成すると、テンプレートに記述したリソースが順次作られていきます。
失敗すると以下のように失敗の理由が表示されます。
失敗までに作成したリソースはロールバックされ削除されます。
成功すると、状況欄に"CREATE_COMPLETE"が表示されます。
マネージメントコンソールから確認すると、テンプレート通りに作成されていました。
[3] デザイナー使用を諦める
ルートテーブルの設定やネットワークACL、セキュリティグループの追加していきますが、ここからはテンプレートファイルを直接編集しました。
デザイナーで追加しようとしましが、図面がゴチャゴチャして大変なことになりました。
[4] テンプレートを直接編集する
公式のリファレンスをみながら編集していきました。
数値や名称は例ですので、状況に応じて変更可能です。
[4-1] インターネットゲートウェイ
"InternetGateway", "VPCGatewayAttachment"を追加します。
ゲートウェイを追加するだけでなくアタッチメントも追加が必要です。
他の項目でも同様に、部品と部品をつなぐ部品が存在します。
NatIGW:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Name
Value: nat-igw
NatIGW2NatVpc:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
InternetGatewayId: !Ref NatIGW
VpcId: !Ref NatVpc
"!Ref"の後ろに論理IDを記述して別の部品を参照します。
VPCとインターネットゲートウェイを参照しています。
[4-2] サブネット
サブネットにCIDRと名称を追加します。
EntranceSubnet:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref NatVpc
CidrBlock: 10.0.0.0/24
Tags:
- Key: Name
Value: entrance-sb
[4-3] ルートテーブル
ルートテーブルに名称を追加します。
EntranceRT:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref NatVpc
Tags:
- Key: Name
Value: entrance-rt
"SubnetRouteTableAssociation"で、ルートテーブルとサブネットを接続します。
EntranceRT2EntranceSubnet:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref EntranceSubnet
RouteTableId: !Ref EntranceRT
"Route"を使用して、ルートテーブルとインターネットゲートウェイを接続します。
EntranceRoute:
Type: 'AWS::EC2::Route'
Properties:
GatewayId: !Ref NatIGW
RouteTableId: !Ref EntranceRT
DestinationCidrBlock: 0.0.0.0/0
[4-4] ネットワークACL
ネットワークACLを作成します。
PublicNetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref NatVpc
Tags:
- Key: Name
Value: public-nacl
次に、ネットワークACLのルール(InBound, OutBound)を作成します。
以下は、SSHのInboundと、ICMPのOutboundの例です。
InSshAclPublic:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 100
Protocol: 6
PortRange:
From: 22
To: 22
CidrBlock: 0.0.0.0/0
Egress: false
RuleAction: allow
OutIcmpAclPublic:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 110
Protocol: 1
Icmp:
Code: -1
Type: -1
CidrBlock: 0.0.0.0/0
Egress: true
RuleAction: allow
ネットワークACLとサブネットを関連付けます。
PublicNetworkAcl2EntranceSubnet:
Type: "AWS::EC2::SubnetNetworkAclAssociation"
Properties:
NetworkAclId: !Ref PublicNetworkAcl
SubnetId: !Ref EntranceSubnet
[4-5] セキュリティグループ
セキュリテイグループを作成します。
ネットワークACLとは異なり、セキュリティグループのプロパティにルールを記述します。
SpringboardSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupName: 'Springboard Security Group'
GroupDescription: 'Springboard Security Group.'
VpcId: !Ref NatVpc
Tags:
- Key: Name
Value: springboard-sg
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/16
- IpProtocol: icmp
FromPort: -1
ToPort: -1
CidrIp: 0.0.0.0/0
[4-6] インスタンス
最後にインスタンスを作成します。
SpringboardInstance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0d7ed3ddb85b521a6 # Amazon Linux 2 AMI (HVM), SSD Volume Type
InstanceType: t3.nano
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- Ref: SpringboardSecurityGroup
SubnetId:
Ref: EntranceSubnet
PrivateIpAddress: 10.0.0.10/24
CreditSpecification:
CPUCredits: standard
KeyName: springboard-keypair
Tags:
- Key: Application
Value: String
- Key: Name
Value: springboard-inst
※ キーペアは予め作成しておく必要があります。
作成済みのキーペア名を"KeyName"に設定します。
[5] パラメータの追加
テンプレートファイルに"Parameters"を追加します。
これまで設定してきたのは"Resources"です。
"Parameters"はデフォルト値有りの引数のように使うことができ、スタック作成時に指定することが可能です。
テンプレートファイル内で"!Ref"を使って参照できます。
以下では、インスタンスのIPアドレス、インスタンスタイプ、キーペア名を定義しています。
書き方は公式のサンプルを参考にしました。
SpringboardInstanceIpAddress:
Description: 'Springboard Instance IP Address.'
Type: String
Default: '10.1.0.10'
SpringboardInstanceType:
Description : 'Springboard Instance Type'
Type: String
Default: t3.nano
ConstraintDescription : 'must be a valid EC2 instance type.'
SpringboardKeyName:
Description : 'Name of an existing EC2 KeyPair to enable SSH access to the instance'
Type: AWS::EC2::KeyPair::KeyName
Default: springboard-keypair
ConstraintDescription : 'Can contain only ASCII characters.'
[6] スタックの作成・削除
[6-1]スタックの作成
2と同様の手順で作成します。
2とは異なり、5で追加したパラメータが設定できるようになっています。

[6-2]スタックの削除
マネージメントコンソールより削除します。
削除すると、スタック内の全てのリソースが削除されます。

終わりに
これでNAT構成の構築・破棄がいつでも簡単に行えるようになりました。
これだけでも十分に便利ですが、まだまだ使っていない機能が沢山あるので、どんどん使っていこうと思います。
以下、今回やらなかったこと。
- Availability Zoneの設定
- IAMの設定
- テンプレートファイルの分割
- 組み込み関数の使用
- ChangeSetの使用
- CLIから操作する
参考資料
AWS CloudFormation (設定管理とオーケストレーション) | AWS
AWS Black Belt Online Seminar 2016 AWS CloudFormation
【CloudFormation入門1】5分と6行で始めるAWS CloudFormationテンプレートによるインフラ構築
How to create a functional VPC using CloudFormation