2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AWS CloudFormationでNAT構成を構築

Posted at

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

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?