AWS
CloudFormation

AWS CloudFormationでNAT構成を構築

AWS CloudFormationでNATインスタンスを含む構成を構築しました。

CloudFormationを使うと複数のリソースをコマンド1つで構築・破棄できて大変便利です。


AWS CloudFormationとは

公式から分かりやすい図が公開されています。

YAMLかJSONで記述したテンプレートから、VPCやインスタンス等の様々なリソースをまとめて作成できます。



AWS CloudFormation (設定管理とオーケストレーション) | AWS


  1. YAMLかJSONにテンプレートを記述する

  2. テンプレートをS3にアップロードする

  3. テンプレートを実行する

  4. スタックと呼ばれるリソースの集合がテンプレート通りに作られる

  5. スタックを削除すればスタック内の全リソースが削除される


目指す構成

以前、マネージメントコンソールから構築したものと同じ構成です。


  • 踏み台サーバー1台

  • NATインスタンス1台

  • 開発用サーバー1台

AWSでNATインスタンス構築


手順

※ テンプレートファイルの設定を全て書くと長くなるので詳細は割愛します。


[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] 作成結果の確認

スタックを作成すると、テンプレートに記述したリソースが順次作られていきます。

失敗すると以下のように失敗の理由が表示されます。

失敗までに作成したリソースはロールバックされ削除されます。

03.作成失敗.png

成功すると、状況欄に"CREATE_COMPLETE"が表示されます。

マネージメントコンソールから確認すると、テンプレート通りに作成されていました。


[3] デザイナー使用を諦める

ルートテーブルの設定やネットワークACL、セキュリティグループの追加していきますが、ここからはテンプレートファイルを直接編集しました。

デザイナーで追加しようとしましが、図面がゴチャゴチャして大変なことになりました。


[4] テンプレートを直接編集する

公式のリファレンスをみながら編集していきました。

数値や名称は例ですので、状況に応じて変更可能です。

Amazon EC2 リソースタイプのリファレンス


[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を作成します。


ネットワークACL

  PublicNetworkAcl:

Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref NatVpc
Tags:
- Key: Name
Value: public-nacl

次に、ネットワークACLのルール(InBound, OutBound)を作成します。

以下は、SSHのInboundと、ICMPのOutboundの例です。


ネットワークACLのルール(SSHのInbound)

  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


ネットワークACLのルール(ICMPのOutbound)

  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とサブネットを関連付けます。


ネットワーク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