目次

Introduction

前回の続きです。特に説明することはないので続きやっていきます。

今回作成するもの

完成系

AWSリソース

CFn相関図

HandsOn

VPC

何はともあれ、Webサーバーで動くアプリケーションを構築したい場合VPCを作成しないことには始まりません。

.pre-commit-config.yaml
cloudformation
 L iam-user.yaml
   iam-role.yaml
   cloudtrail.yaml
   vpc.yaml(new)
AWSTemplateFormatVersion: "2010-09-09"
Description: "stackName: {ENV}-vpc. AWS::EC2::VPC AWS::EC2::InternetGateway AWS::EC2::VPCGatewayAttachment"

Parameters:
  Env:
    Type: String
    Description: Project environment
    AllowedValues: [dev, prd]
  Project:
    Type: String
    Description: Project Name
    Default: example

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-vpc

  IGW:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-igw

  AttachIGW:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref IGW

Outputs:
  VPCId:
    Description: Output Export AWS::EC2::VPC.Ref VPCId
    Value: !Ref VPC
    Export:
      Name: !Sub ${Env}-${Project}-vpc-id
  IGWId:
    Description: Output Export  AWS::EC2::InternetGateway IGWId
    Value: !Ref IGW
    Export:
      Name: !Sub ${Env}-${Project}-igw-id

今回CFnの流す際のパラメータのEnvはdevにします。スタック名は、Descriptionに沿ってdev-vpcとします。繰り返しになりますが、ここはプロジェクトや状況に応じてお好きに

Subnet

.pre-commit-config.yaml
cloudformation
 L iam-user.yaml
   iam-role.yaml
   cloudtrail.yaml
   vpc.yaml
   subnet.yaml(new)
AWSTemplateFormatVersion: "2010-09-09"
Description: "stackName: {ENV}-subnet. AWS::EC2::Subnet AWS::EC2::RouteTable AWS::EC2::Route AWS::EC2::SubnetRouteTableAssociation AWS::EC2::EIP AWS::EC2::NatGateway"

Parameters:
  Env:
    Type: String
    Description: Project environment
    AllowedValues: [dev, prd]
  Project:
    Type: String
    Description: Project Name
    Default: example

Resources:
# Subnet
  PublicSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 10.0.1.0/24
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-public-1a
  PublicSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      CidrBlock: 10.0.2.0/24
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-public-1c

  PrivateSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 10.0.128.0/24
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-private-1a
  PrivateSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      CidrBlock: 10.0.129.0/24
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-private-1c

# RouteTable
  PublicSubnetRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-public-rt
  PublicSubnetRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicSubnetRT
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Fn::ImportValue: !Sub ${Env}-${Project}-igw-id
  PublicSubnet1aRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1a
      RouteTableId: !Ref PublicSubnetRT
  PublicSubnet1cRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1c
      RouteTableId: !Ref PublicSubnetRT

  PrivateSubnetRT:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-private-rt
  PrivateSubnetRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateSubnetRT
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGW
  PrivateSubnet1aRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1a
      RouteTableId: !Ref PrivateSubnetRT
  PrivateSubnet1cRTAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1c
      RouteTableId: !Ref PrivateSubnetRT

# NatGateway
  NatEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-nat-eip

  NatGW:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatEIP.AllocationId
      SubnetId: !GetAtt PublicSubnet1a.SubnetId
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-natgw

ロードバランサーを設置するためのPublicSubnetとEC2インスタンスを置くためのPrivateSubnetを作成します。今回は、データベースは作成しないため、IsolatedSubnetは作成しません。 各サブネットの詳しい説明は、Amazon VPC のサブネットと通信関係を図にしてみたをご覧ください。
また、サブネットの他にNatGatewayを今回作成しています。その理由としては後に作成するECSで動くEC2にセッションマネージャーでアクセスする際、NatGatewayを利用してEC2にログインできるようにするためにです。
詳しくは→セッションマネージャーを使用してプライベートサブネットのLinux用EC2にアクセス(NAT Gateway編)
ImportValueにSubで${Env}を使用しているため、vpc.yamlでParametersのEnvをdevにしていた場合は、subnet.yamlでもdevにしてください。そうしないとImportもとがなくエラーになります。

SecuriyGroup

ネットワークとは少し異なりますが、この記事では仮想ファイアーフォールであるSecurityGroupも作成します。

.pre-commit-config.yaml
cloudformation
 L iam-user.yaml
   iam-role.yaml
   cloudtrail.yaml
   vpc.yaml
   subnet.yaml
   sg.yaml(new)
AWSTemplateFormatVersion: "2010-09-09"
Description: "stackName: {ENV}-sg. AWS::EC2::SecurityGroup"

Parameters:
  Env:
    Type: String
    Description: Project environment
    AllowedValues: [dev, prd]
  Project:
    Type: String
    Description: Project Name
    Default: example

Resources:
  AppLBSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${Env}-${Project}-app-lb-sg
      GroupDescription: !Sub ${Env}-${Project}-app-lb-sg
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-app-lb-sg

  PrivateInstanceSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${Env}-${Project}-private-instance-sg
      GroupDescription: !Sub ${Env}-${Project}-private-instance-sg
      VpcId:
        Fn::ImportValue: !Sub ${Env}-${Project}-vpc-id
      SecurityGroupIngress: # ec2 /proc/sys/net/ipv4/ip_local_port_range
        - IpProtocol: tcp
          FromPort: 32768
          ToPort: 60999
          SourceSecurityGroupId: !Ref AppLBSG
      Tags:
        - Key: Name
          Value: !Sub ${Env}-${Project}-private-instance-sg

スタック名は、dev-sg。
ここでのポイントは、以下です

  • httpsしか受け付けないwebサーバーにするため、443ポートのみ許可するようにロードバランザーを置くPublicSubnet用のSecurityGroupを作成
  • ECSのEC2に自動割り当てされるポートのPrivateSubnet用SecurityGroup作成。自動で割り当てられるポートの範囲は、タスク定義パラメータのhostPortの箇所にも記載されていますが、EC2へログインしてcat /proc/sys/net/ipv4/ip_local_port_rangeしても確認できます。

終わりに

VPC、Subnetのネットワーク部分とSecurityGroupの仮想ファイアーフォールを作成しました。次は、ドメインの登録部分を書いていこうかなと思っています。

参考