2
0

More than 1 year has passed since last update.

AWS CloudFormationを使用したVPC環境作成

Posted at

はじめに

最近、自身のAWS環境でネットワークのスタディーをするために、主要なネットワーク関連のサービス(S3ゲートウェイ・エンドポイント、PrivateLink、トランジット・ゲートウェイ、ゲートウェイ・ロードバランサー)の環境構築・実機検証をやっていました。その際、事前準備としてVPC環境作成(サブネットや、インターネットゲートウェイ、セキュリティー・グループ作成など)が必要となりますが、毎度毎度同じセットアップをすることになり手間もかかります。そこで、本来試したいネットワーク関連サービスの検証に時間を割けるようにすべく、事前準備部分のVPC環境作成をCloudFormationのコードを書いて自動作成できるようにしてみました。本記事では、筆者が作成したCloudFormationのサンプルコードをご紹介します。
なお、CloudFormationの詳細については、AWS CloudFormationドキュメントを参照ください。

作成するVPC環境

今回作成する構成は下記の通りです。

  • AWSのリージョン:東京リージョン(ap-northeast-1)を使用
  • 以下のCIDRアドレス範囲を持つVPCを作成
    • VPC (10.0.0.0/16)
  • AZ(ap-northeast-1a)に、以下のCIDRアドレス範囲をもつサブネットを作成
    • パブリック・サブネット (10.0.1.0/24)
    • プライベート・サブネット (10.0.2.0/24)
  • AZ(ap-northeast-1c)に、以下のCIDRアドレス範囲をもつサブネットを作成
    • パブリック・サブネット (10.0.3.0/24)
    • プライベート・サブネット (10.0.4.0/24)
  • インターネットゲートウェイ
  • ルートテーブル
    • パブリック・サブネットに対するルートテーブルには、下記の宛先とターゲットを別途追記指定
      • 宛先:0.0.0.0/0、ターゲット:インターネットゲートウェイ
  • セキュリティー・グループ
    • パブリック・サブネットとプライベート・サブネットそれぞれに対してグループを用意
      • パブリック・サブネット用
        • 外部からのSSH、HTTP通信を許可
      • プライベート・サブネット用
        • パブリック・サブネットからのSSH通信とPINGを許可

CloudFormationサンプルコード

今回作成したサンプルコードは下記のようなYAMLファイルです。

CreateNetWork_Stack.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample Script for Creating NetWork Stack (VPC,Public Subnet,Private Subnet,Internet Gateway,Route Table,Security Group)
Parameters:
  AzName01:
    Description: Set 1st az-name
    Type: String
    Default: ap-northeast-1a
    AllowedValues:
      - ap-northeast-1a
      - ap-northeast-1c
      - ap-northeast-1d
  AzName02:
    Description: Set 2nd az-name
    Type: String
    Default: ap-northeast-1c
    AllowedValues:
      - ap-northeast-1a
      - ap-northeast-1c
      - ap-northeast-1d
  VPCCidrBlock:
    Description: VPC Cidr Block
    Type: String
    Default: 10.0.0.0/16
  PublicSubnetCidrBlock01:
    Description: Public Subnet Cidr Block for 1st az-name
    Type: String
    Default: 10.0.1.0/24
  PrivateSubnetCidrBlock01:
    Description: Private Subnet Cidr Block for 1st az-name
    Type: String
    Default: 10.0.2.0/24
  PublicSubnetCidrBlock02:
    Description: Public Subnet Cidr Block for 2nd az-name
    Type: String
    Default: 10.0.3.0/24
  PrivateSubnetCidrBlock02:
    Description: Private Subnet Cidr Block for 2nd az-name
    Type: String
    Default: 10.0.4.0/24
    
Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties: 
      CidrBlock: !Ref VPCCidrBlock
      EnableDnsHostnames: 'true'
      EnableDnsSupport: 'true'
      Tags: 
        - Key: Name
          Value: My-vpc
  MyPublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PublicSubnetCidrBlock01
      AvailabilityZone: !Ref AzName01
      Tags:
        - Key: Name
          Value: My-Public-Subnet-01
    DependsOn: MyVPC
  MyPrivateSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PrivateSubnetCidrBlock01
      AvailabilityZone: !Ref AzName01
      Tags:
        - Key: Name
          Value: My-Private-Subnet-01
    DependsOn: MyVPC
  MyPublicSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PublicSubnetCidrBlock02
      AvailabilityZone: !Ref AzName02
      Tags:
        - Key: Name
          Value: My-Public-Subnet-02
    DependsOn: MyVPC
  MyPrivateSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PrivateSubnetCidrBlock02
      AvailabilityZone: !Ref AzName02
      Tags:
        - Key: Name
          Value: My-Private-Subnet-02
    DependsOn: MyVPC
  MyIGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: My-internet-gateway
    DependsOn: MyVPC
  MyIGWAttachToVPC:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref MyIGW 
  MyPublicRtbl01:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
        - Key: Name
          Value: My-Public-Rtbl-01
    DependsOn: MyIGW
  MyPublicRoute01:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: MyPublicRtbl01
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref MyIGW
  MyPublicSubnetRouteTblAssociation01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPublicRtbl01
      SubnetId: !Ref MyPublicSubnet01
  MyPrivateRtbl01:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
        - Key: Name
          Value: My-Private-Rtbl-01
  MyPrivateSubnetRouteTblAssociation01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPrivateRtbl01
      SubnetId: !Ref MyPrivateSubnet01
  MyPublicRtbl02:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
        - Key: Name
          Value: My-Public-Rtbl-02
    DependsOn: MyIGW
  MyPublicRoute02:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId:
        Ref: MyPublicRtbl02
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref MyIGW
  MyPublicSubnetRouteTblAssociation02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPublicRtbl02
      SubnetId: !Ref MyPublicSubnet02
  MyPrivateRtbl02:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
        - Key: Name
          Value: My-Private-Rtbl-02
  MyPrivateSubnetRouteTblAssociation02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPrivateRtbl02
      SubnetId: !Ref MyPrivateSubnet02
  MyPublicSecGrp01:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow http to client host
      VpcId: !Ref MyVPC
      SecurityGroupIngress: 
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
      Tags:
        - Key: Name
          Value: My-Public-Security-Group-01
  MyPrivateSecGrp01:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow Ingress trafic from Public Subnet
      VpcId: !Ref MyVPC
      SecurityGroupIngress: 
        - SourceSecurityGroupId: !Ref MyPublicSecGrp01
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - SourceSecurityGroupId: !Ref MyPublicSecGrp01
          IpProtocol: icmp
          FromPort: 8
          ToPort: -1
      Tags:
        - Key: Name
          Value: My-Private-Security-Group-01
  MyPublicSecGrp02:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow http to client host
      VpcId: !Ref MyVPC
      SecurityGroupIngress: 
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIp: 0.0.0.0/0
          IpProtocol: tcp
          FromPort: 80
          ToPort: 80
      Tags:
        - Key: Name
          Value: My-Public-Security-Group-02
  MyPrivateSecGrp02:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow Ingress trafic from Public Subnet
      VpcId: !Ref MyVPC
      SecurityGroupIngress: 
        - SourceSecurityGroupId: !Ref MyPublicSecGrp02
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - SourceSecurityGroupId: !Ref MyPublicSecGrp02
          IpProtocol: icmp
          FromPort: 8
          ToPort: -1
      Tags:
        - Key: Name
          Value: My-Private-Security-Group-02

Outputs:
  MyStackPublicSubnetID01:
    Description: The ID of My Public Subnet for AzName01
    Value: !Ref MyPublicSubnet01
    Export:
      Name: !Sub "${AWS::StackName}--PublicSubnetId01"
  MyStackPrivateSubnetID01:
    Description: The ID of My Private Subnet for AzName01
    Value: !Ref MyPrivateSubnet01
    Export:
      Name: !Sub "${AWS::StackName}--PrivateSubnetId01"
  MyStackPublicSubnetSecurityGroupID01:
    Description: The ID of My Public Subnet Security Group for AzName01
    Value: !Ref MyPublicSecGrp01
    Export:
      Name: !Sub "${AWS::StackName}--PublicSubnetSecGrpId01"
  MyStackPrivateSubnetSecurityGroupID01:
    Description: The ID of My Private Subnet Security Group for AzName01
    Value: !Ref MyPrivateSecGrp01
    Export:
      Name: !Sub "${AWS::StackName}--PrivateSubnetSecGrpId01"
  MyStackPublicSubnetID02:
    Description: The ID of My Public Subnet for AzName02
    Value: !Ref MyPublicSubnet02
    Export:
      Name: !Sub "${AWS::StackName}--PublicSubnetId02"
  MyStackPrivateSubnetID02:
    Description: The ID of My Private Subnet for AzName02
    Value: !Ref MyPrivateSubnet02
    Export:
      Name: !Sub "${AWS::StackName}--PrivateSubnetId02"
  MyStackPublicSubnetSecurityGroupID02:
    Description: The ID of My Public Subnet Security Group for AzName02
    Value: !Ref MyPublicSecGrp02
    Export:
      Name: !Sub "${AWS::StackName}--PublicSubnetSecGrpId02"
  MyStackPrivateSubnetSecurityGroupID02:
    Description: The ID of My Private Subnet Security Group for AzName02
    Value: !Ref MyPrivateSecGrp02
    Export:
      Name: !Sub "${AWS::StackName}--PrivateSubnetSecGrpId02"

今回のサンプルコードの主なポイントは下記の部分になります。

  • Parametersセクション
    • 作成する環境に応じて、AZやCIDRアドレス範囲を指定可能にしました。ただし、東京リージョンにあるもののみが利用可能です。
  • Resourcesセクション
    • 作成するリソース(VPC、サブネット、インターネットゲートウェイ等)の構成を定義します。
    • CloudFormationはリソースを並行して作成されるため、例えばサブネットやインターネットゲートウェイは必ずVPCの作成完了後に作成を開始する等の考慮が必要になります。その為、そのようなリソースの作成においては、DependsOn属性を指定する必要があります。
  • Outputsセクション
    • 各サブネットのIDとセキュリティー・グループのID情報を出力します。これらの情報は、別に作成しているEC2プロビジョニング用のCloudFormationのコード実行時に必要になります。(ネストスタックのスタディーがやりたく、敢えて本記事で紹介しているサンプルコードでは、EC2インスタンスのプロビジョニング部分はスコープ外としています。)

作成したサンプルコードの実行

AWSのマネジメントコンソールにログオンし、CloudFormationの「スタックの作成」の画面において、最初に今回のサンプルコードをアップロードします。その後、「スタックの詳細を指定」の画面において、スタック名等を入力していきます。(以下はサンプルです。)

  • スタック名を入力
    p1.jpg

  • パラメータ確認
    下記のようにAZの名前や、パブリック・サブネット、プライベート・サブネット等のCIDRアドレス範囲等が表示されますので、確認します。アドレス範囲等はここで指定が可能です。
    p2.jpg
    p3.jpg
    確認が終了したら画面右下の「次へ」ボタンを押下げします。その後に遷移した先の画面では特に何もせずに「次へ」ボタンを押下げします。

  • レビュー画面の確認
    下記のようなパラメータ一覧が表示されますので、問題なければ右下の「送信」ボタンを押下げして、CloudFormationのコードを実行します。
    p7.jpg

  • コードの実行
    下記画面のようにスタックの作成が開始されます。スタックのステータスが最終的に「CREATE_COMPLETE」になればOKです。
    p9.jpg
    スタックの作成完了後のイメージは下記の通りです。
    p10.jpg

  • 「出力」タブの確認
    サンプルコードのOutputsセクションに指定した、サブネットIDやセキュリティー・グループID等の一覧が表示されます。
    p11.jpg
    p12.jpg

おわりに

今回は、CloudFormationを使用して、VPC環境を自動作成するサンプルコードを紹介しました。このVPC環境上にEC2をプロビジョニングするサンプルコードについては、また別の記事で紹介予定です。

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