【初心者の目線でわかりやすい】AWS CloudFormation2~インフラを構築してみよう

AWS

2023.6.21

Topics

こんにちは。新入社員の「kisaragi」です。
この記事では、CloudFormationでAWSインフラを構築していきます。

▼ 今回の「初心者の目線でわかりやすいAWS CloudFormation」は2編で構成されています。
まだ1編をご覧になってない方は、1編からご覧ください。

1 編 :【初心者の目線でわかりやすい】AWS CloudFormation1~概念を学ぼう
2 編 :【初心者の目線でわかりやすい】AWS CloudFormation2~インフラを構築してみよう

環境

  • ap-northeast-1(東京)
  • VSCode

構成図・Template

これが今回構築するインフラの構成図です。
この構成図を基に、Templateを作成しましょう。

【Template】

AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on for AWS CloudFormation Beginner

#-----------------------------------
# Parameters
#-----------------------------------
Parameters: # Parameters Start
  AvailabilityZone1:
    Type: String
    Default: "ap-northeast-1a"
    Description: "az-1a"
  AvailabilityZone2:
    Type: String
    Default: "ap-northeast-1c"
    Description: "az-1c"
  ImageID:
    Type: String
    Default: "ami-08928044842b396f0"
    Description: "AMI"
  MyName:
    Type: String
    Default: "kisaragi"
    Description: "Please My Name"

Resources: # Resources Start
#-----------------------------------
# VPC
#-----------------------------------
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-vpc"
#-----------------------------------
# Subnet
#-----------------------------------
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PublicSubnet1"
  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PublicSubnet2"
  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PrivateSubnet1"
  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      VpcId: !Ref VPC
      CidrBlock: 10.0.4.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PrivateSubnet2"
#-----------------------------------
# RouteTable
#-----------------------------------
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Public-rtb"
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Private-rtb"
#-----------------------------------
# SubnetRouteTableAssociation
#-----------------------------------
  PublicSubnetAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable
  PrivateSubnetAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnetAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable
#-----------------------------------
# Security Group
#-----------------------------------
  SGALBWEB:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGALBWEB"
      GroupDescription: !Sub "${MyName}-SGALBWEB"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGALBWEB"
  SGEC2:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGEC2"
      GroupDescription: !Sub "${MyName}-SGEC2"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGEC2"
  SGDB:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGDB"
      GroupDescription: !Sub "${MyName}-SGDB"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGDB"
#-----------------------------------
# SG(Security Group) Rules
#-----------------------------------
  SGALBWEBIngress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGALBWEB
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  SGEC2Ingress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGEC2
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  SGEC2Ingress2:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGEC2
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
      CidrIp: 3.112.23.0/29 # EC2 Instance Connect
  SGDBIngress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGDB
      IpProtocol: tcp
      FromPort: 3306
      ToPort: 3306
      SourceSecurityGroupId: !Ref SGEC2
#-----------------------------------
# IAM
#-----------------------------------
  ServerRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/EC2InstanceConnect"
  ServerProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
        - Ref: ServerRole
      InstanceProfileName: !Sub "${MyName}-IAMRole"
#-----------------------------------
# EC2 Instance
#-----------------------------------
  Instance1:
    Type: "AWS::EC2::Instance"
    Properties:
      IamInstanceProfile: !Ref ServerProfile
      ImageId: !Ref ImageID
      InstanceType: t2.micro
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          DeleteOnTermination: true
          GroupSet:
            - !Ref SGEC2
          SubnetId: !Ref PublicSubnet1
      UserData: 
          Fn::Base64: |
             #!/bin/bash
             sudo amazon-linux-extras install nginx1
             sudo systemctl enable nginx
             sudo systemctl start nginx
             sudo yum -y install httpd mysql ncurses-compat-libs
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Instance1"
  Instance2:
    Type: "AWS::EC2::Instance"
    Properties:
      IamInstanceProfile: !Ref ServerProfile
      ImageId: !Ref ImageID
      InstanceType: t2.micro
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          DeleteOnTermination: true
          GroupSet:
            - !Ref SGEC2
          SubnetId: !Ref PublicSubnet2
      UserData: 
          Fn::Base64: |
             #!/bin/bash
             sudo amazon-linux-extras install nginx1
             sudo systemctl enable nginx
             sudo systemctl start nginx
             sudo yum -y install httpd mysql ncurses-compat-libs
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Instance2"
#-----------------------------------
# RDS
#-----------------------------------
  RDSSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupName: !Sub "${MyName}-RDS-SubnetGroup"
      DBSubnetGroupDescription: !Sub "${MyName}-RDS-SubnetGroup" 
      SubnetIds: 
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Tags: 
      - Key: "Name"
        Value: !Sub "${MyName}-RDS-SubnetGroup"
  RDSInstance: 
    Type: "AWS::RDS::DBInstance"
    Properties: 
      DBInstanceIdentifier: !Sub "${MyName}-RDS"
      Engine: MySQL
      EngineVersion: "8.0.32"
      DBInstanceClass: db.t4g.micro
      AllocatedStorage: "20"
      StorageType: gp2
      DBName: RDS
      DeletionProtection: false
      DeleteAutomatedBackups: true
      MasterUsername: "admin"
      MasterUserPassword: "password"
      PubliclyAccessible: false
      MultiAZ: true
      AutoMinorVersionUpgrade: false
      VPCSecurityGroups:
       - !GetAtt SGDB.GroupId
      CopyTagsToSnapshot: false
      BackupRetentionPeriod: 0
      DBSubnetGroupName: !Ref RDSSubnetGroup
      Tags: 
        - Key: "Name"
          Value: !Sub "${MyName}-RDS"
#-----------------------------------
# InternetGateway
#-----------------------------------
  InternetGateway: 
    Type: AWS::EC2::InternetGateway
    Properties: 
      Tags: 
        - Key: Name
          Value: !Sub "${MyName}-InternetGateway"
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC
  InternetGatewayToRouteTable:
    Type: "AWS::EC2::Route"
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PublicRouteTable
#-----------------------------------
# ALB
#-----------------------------------
  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: "application"
      Scheme: "internet-facing"
      Name: !Sub ${MyName}-alb
      IpAddressType: ipv4
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      SecurityGroups:
        - !Ref SGALBWEB
      Tags:
        - Key: Name
          Value: !Sub ${MyName}-alb
  ListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref ALBTargetGroup
      LoadBalancerArn: !Ref ALB
      Port: 80
      Protocol: HTTP
  ALBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub ${MyName}-tg
      Port: 80
      Protocol: HTTP
      Matcher:
        HttpCode: '200'
      VpcId: !Ref VPC
      TargetType: instance
      Targets:
        - Id: !Ref Instance1
        - Id: !Ref Instance2
      Tags:
        - Key: Name
          Value: !Sub ${MyName}-tg

えっ、難しいですって?全然大丈夫です! 😉

少しずつ構築していけば、思ったより簡単ですよ!
先ず、VPCの構成図だけを見ていきましょう!

先ほどの構成図より簡単になりましたね!
先ず、この「VPC」「サブネット」「InternetGateway」など、ネットワークを作成してみましょう。

【ハンズオン】ネットワークを作成してみよう!

【VPC作成】

Resources: # Resources Start
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-vpc" # kisaragi-vpc

* CidrBlockが10.0.0.0/16のVPCを作成します。

  • !Sub:Parametersで宣言しておいた値を返します。単体で変数名と文字列を結合する時使います。
                 ここでは、Parametersがkisaragiですから、kisaragi-vpcになります。

▼ VPCの作成方法やSub関数の詳細は以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::VPC
💡 AWS CloudFormation – 組み込み関数 Subとは?

【Subnet作成】

  PublicSubnet1: # PublicSubnet1を作成します。
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1 # AZ : ap-northeast-1a
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PublicSubnet1"
  PublicSubnet2: # PublicSubnet2を作成します。
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2 # AZ : ap-northeast-1c
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PublicSubnet2"
  PrivateSubnet1: # PrivateSubnet1を作成します。
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1 # AZ : ap-northeast-1a
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PrivateSubnet1"
  PrivateSubnet2: # PrivateSubnet2を作成します。
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2 # AZ : ap-northeast-1c
      VpcId: !Ref VPC
      CidrBlock: 10.0.4.0/24
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-PrivateSubnet2"

* 構成図のように、PulbicSubnet/PrivateSubnetを2つずつ、2つのAZに分けて構築します。

  • !Ref:指定のParameters または Resourcesの値を返します。
    ここでは、ResourcesのVPCのID値を返してもらいます。

▼ Subnetの作成方法やRef関数の詳細は以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::Subnet
💡 AWS CloudFormation – 組み込み関数 Refとは?

【ルートテーブルの作成】

  PublicRouteTable: # PublicRouteTableを作成します。
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Public-rtb"
  PrivateRouteTable: # PrivateRouteTableを作成します。
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Private-rtb"

* Public / Private ルートテーブルを作成します。

▼ RouteTableの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::RouteTable

【ルートテーブルの関連】

  PublicSubnetAssociation1: #PublicSubnet1をPublicRouteTableに関連します。
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetAssociation2: #PublicSubnet2をPublicRouteTableに関連します。
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable
  PrivateSubnetAssociation1: #PrivateSubnet1をPrivateRouteTableに関連します。
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable
  PrivateSubnetAssociation2: #PrivateSubnet1をPrivateRouteTableに関連します。
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable

* PublicSubnet / PrivateSubnetを各ルートテーブルに関連します。

▼ RouteTableの関連方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::SubnetRouteTableAssociation

【セキュリティグループの作成】

  SGALBWEB:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGALBWEB"
      GroupDescription: !Sub "${MyName}-SGALBWEB"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGALBWEB"
  SGEC2:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGEC2"
      GroupDescription: !Sub "${MyName}-SGEC2"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGEC2"
  SGDB:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !Ref VPC
      GroupName: !Sub "${MyName}-SGDB"
      GroupDescription: !Sub "${MyName}-SGDB"
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-SGDB"

* ALB・EC2・DBのセキュリティグループを作成します。

▼ SecurityGroupの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::SecurityGroup

【セキュリティグループルールの作成】

  SGALBWEBIngress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGALBWEB
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  SGEC2Ingress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGEC2
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
  SGEC2Ingress2:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGEC2
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
      CidrIp: 3.112.23.0/29 # AWS Tokyo Region → Amazon Linux2 (EC2 Instance Connect)
  SGDBIngress1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SGDB
      IpProtocol: tcp
      FromPort: 3306
      ToPort: 3306
      SourceSecurityGroupId: !Ref SGEC2

* セキュリティグループルールを作成します。
AWS東京リージョンから直接EC2に接続する為、3.112.23.0/29を追加しました。

▼ SecurityGroupRulesの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::SecurityGroupIngress

【InternetGateway作成】

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties: 
      Tags: 
        - Key: Name
          Value: !Sub "${MyName}-InternetGateway"
  InternetGatewayAttachment: # InternetGatewayをVPCに連動します。
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC
  InternetGatewayToRouteTable: # InternetGatewayをPublicRouteTableに連動します。
    Type: "AWS::EC2::Route"
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PublicRouteTable

* InternetGatewayを作成し、VPCとPublicRouteTableに連動します。

▼ InternetGatewayの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::InternetGateway
💡 AWS CloudFormation – AWS::EC2::VPCGatewayAttachment
💡 AWS CloudFormation – AWS::EC2::Route

【ハンズオン】AWSサービスを作成してみよう!

ネットワーク構築に成功しました!
これから、「IAM」「EC2」「RDS」「ALB」を構築してみましょう。

【構成図】

【IAMの作成】

  ServerRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns: # IAMロールのポリシーを設定します。
        - "arn:aws:iam::aws:policy/EC2InstanceConnect" # AWS → EC2接続の為
  ServerProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Path: "/"
      Roles:
        - Ref: ServerRole
      InstanceProfileName: !Sub "${MyName}-IAMRole"

* EC2に使うIAMロールやポリシーを作成します。

▼ IAMの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::IAM::Role
💡 AWS CloudFormation – AWS::IAM::InstanceProfile

【EC2作成】

  Instance1: # 1台目のEC2を作成します。
    Type: "AWS::EC2::Instance"
    Properties:
      IamInstanceProfile: !Ref ServerProfile # IAMロールをアタッチします。
      ImageId: !Ref ImageID # Parametersに宣言したEC2 ImageID
      InstanceType: t2.micro
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          DeleteOnTermination: true
          GroupSet:
            - !Ref SGEC2
          SubnetId: !Ref PublicSubnet1
      UserData: # インスタンスの起動時にLinuxコマンドを実行させます。
          Fn::Base64: |
             #!/bin/bash
             sudo amazon-linux-extras install nginx1
             sudo systemctl enable nginx
             sudo systemctl start nginx
             sudo yum -y install httpd mysql ncurses-compat-libs
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Instance1"
  Instance2: # 2台目のEC2を作成します。
    Type: "AWS::EC2::Instance"
    Properties:
      IamInstanceProfile: !Ref ServerProfile # IAMロールをアタッチします。
      ImageId: !Ref ImageID # Parametersで宣言したEC2のImageID
      InstanceType: t2.micro
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          DeleteOnTermination: true
          GroupSet:
            - !Ref SGEC2
          SubnetId: !Ref PublicSubnet2
      UserData: # インスタンスの起動時にLinuxコマンドを実行させます。
          Fn::Base64: |
             #!/bin/bash
             sudo amazon-linux-extras install nginx1
             sudo systemctl enable nginx
             sudo systemctl start nginx
             sudo yum -y install httpd mysql ncurses-compat-libs
      Tags:
        - Key: Name
          Value: !Sub "${MyName}-Instance2"

* EC2を作成します。
ALBとRDSの動作チェックの為、UserDataでNginxとMySQLをインストールするコマンドを入力しました。

  • UserData:インスタンスの起動時にLinuxコマンドを実行させます。
  • Fn::Base64:入力文字列の Base64 表現を返します。

▼ EC2の作成方法やUserData・に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::EC2::Instance
💡 AWS EC2 – 起動時に Linux インスタンスでコマンドを実行する
💡 AWS CloudFormation – Fn::Base64

【RDS作成】

  RDSSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupName: !Sub "${MyName}-RDS-SubnetGroup"
      DBSubnetGroupDescription: !Sub "${MyName}-RDS-SubnetGroup" 
      SubnetIds: 
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Tags: 
      - Key: "Name"
        Value: !Sub "${MyName}-RDS-SubnetGroup"
  RDSInstance:
    Type: "AWS::RDS::DBInstance"
    Properties: 
      DBInstanceIdentifier: !Sub "${MyName}-RDS"
      Engine: MySQL
      EngineVersion: "8.0.32"
      DBInstanceClass: db.t4g.micro
      AllocatedStorage: "20"
      StorageType: gp2
      DBName: RDS
      DeletionProtection: false
      DeleteAutomatedBackups: true
      MasterUsername: "admin"
      MasterUserPassword: "password"
      PubliclyAccessible: false
      MultiAZ: true
      AutoMinorVersionUpgrade: false
      VPCSecurityGroups:
       - !GetAtt SGDB.GroupId
      CopyTagsToSnapshot: false
      BackupRetentionPeriod: 0
      DBSubnetGroupName: !Ref RDSSubnetGroup
      Tags: 
        - Key: "Name"
          Value: !Sub "${MyName}-RDS"

* RDSのSubnetGroupを設定し、RDSを作成します。

  • !Getatt:TemplateのResourcesから指定した属性の値を返します。

▼ RDSの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::RDS::DBSubnetGroup
💡 AWS CloudFormation – AWS::RDS::DBInstance
💡 AWS CloudFormation – 組み込み関数 GetAttとは?

【ALB作成】

  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: "application"
      Scheme: "internet-facing"
      Name: !Sub ${MyName}-alb
      IpAddressType: ipv4
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      SecurityGroups:
        - !Ref SGALBWEB
      Tags:
        - Key: Name
          Value: !Sub ${MyName}-alb
  ListenerHTTP:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref ALBTargetGroup
      LoadBalancerArn: !Ref ALB
      Port: 80
      Protocol: HTTP
  ALBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub ${MyName}-tg
      Port: 80
      Protocol: HTTP
      Matcher:
        HttpCode: '200'
      VpcId: !Ref VPC
      TargetType: instance
      Targets:
        - Id: !Ref Instance1
        - Id: !Ref Instance2
      Tags:
        - Key: Name
          Value: !Sub ${MyName}-tg

* ALBとTargetGroupを作成し、連動します。

▼ ALBの作成方法に関しては以下をご覧ください。
💡 AWS CloudFormation – AWS::ElasticLoadBalancingV2::LoadBalancer
💡 AWS CloudFormation – AWS::ElasticLoadBalancingV2::Listener
💡 AWS CloudFormation – AWS::ElasticLoadBalancingV2::TargetGroup

【ハンズオン】スタックを作成してみよう!

1.作成した【Template】を「Visual Studio Code」にペーストします。

2.左上の「File」-「Save as」でYaml形式でファイル化します。

3.AWSの「CloudFormation」に移動します。

4.スタックの作成→新しいリソースを使用(標準)をクリックします。

5.Yamlファイルをアップロードします。

6.スタックの名前を記入します。

▲ ここで入力したParametersを確認できます。

 

7.その他はデフォルトのまま「次へ」「送信」ボタンをクリックします。

 

8.スタックがCREATE_COMPLETEになるまで待機します。

▲ スタックの「イベント」タブで現状を確認できます。

動作確認

【DB動作確認】

1.AWSコンソールからEC2に移動します。

2.インスタンスを選択し、接続をクリックします。

3.EC2 Instance Connectを確認の上、接続をクリックします。

4.下記のコマンドを入力します。

mysql -h RDSのエンドポイント -u admin -p

password:が出たら、passwordを入力します。

▲ DBが正常に動作しています。

【ALB動作確認】

1.AWSコンソールからEC2に移動します。

2.左のメニューにあるロードバランサーに移動します。

3.DNS nameをコピーし、接続します。

▲ ALBが正常に動作しています。

 

まとめ

今回はハンズオンでCloudFormation Templateを作成し、Stackまで作成しました。

最初の構成図だけ見ると、難しかったですね。
でも、ネットワーク・リソースを少しずつわけて作成してみたら思ったより簡単でした。

私の記事で、皆さんがAWS CloudFormationを少しでも気軽にはじめることができたら嬉しいです。
以上、「kisaragi」がお送りしました。

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

kisaragi

- 2024 Japan AWS Jr. Champions

2023年度新卒入社。出身は韓国です。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら