スケーラブルな Web システム構築してみた

## 概要

WordPressを使ったブログサイトの構築を通じて、スケーラブルなWebシステム構築方法を学びました！

![スクリーンショット 2024-03-30 23.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3747730/2803ee6c-182e-1a05-bfe3-de802e1411a7.png)


https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Scalable-2022-reg-event.html?trk=aws_introduction_page

※構築内容はセミナーの内容と完全に一致していません

## CloudFormation
```yml
AWSTemplateFormatVersion: 2010-09-09
Resources: 
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags: 
        - Key: Name
          Value: InternetGateway
      
  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: ap-northeast-1a
  
  PublicSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: ap-northeast-1c
  
  PrivateSubnet1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: ap-northeast-1a
  
  PrivateSubnet1c:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      AvailabilityZone: ap-northeast-1c
  
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  
  PublicSubnet1aRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1a
      RouteTableId: !Ref PublicRouteTable
  
  PublicSubnet1cRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet1c
      RouteTableId: !Ref PublicRouteTable

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  
  PrivateSubnet1aRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1a
      RouteTableId: !Ref PrivateRouteTable
  
  PrivateSubnet1cRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1c
      RouteTableId: !Ref PrivateRouteTable
  
  Route:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Subnets: 
        - !Ref PublicSubnet1a
        - !Ref PublicSubnet1c
      IpAddressType: ipv4
      SecurityGroups: 
        - !Ref EC2SecurityGroup

  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !GetAtt LoadBalancer.LoadBalancerArn
      Port: 80
      Protocol: HTTP
      DefaultActions: 
        - Order: 1
          TargetGroupArn: !GetAtt TargetGroup.TargetGroupArn
          Type: forward
  
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 80
      Protocol: HTTP
      VpcId: !Ref VPC
      HealthCheckEnabled: true
      HealthCheckPath: /
      Targets: 
        - Id: !Ref Instance
          Port: 80
        - Id: !Ref Instance2
          Port: 80

  Instance:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: ap-northeast-1a
      LaunchTemplate: 
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref EC2SecurityGroup
          SubnetId: !Ref PublicSubnet1a
    
  Instance2:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: ap-northeast-1c
      LaunchTemplate: 
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref EC2SecurityGroup
          SubnetId: !Ref PublicSubnet1c

  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData: 
        ImageId: ami-0a211f4f633a3af5f
        InstanceType: t2.micro
        KeyName: keypair
        UserData: !Base64 |
          #!/bin/bash

          yum -y update
          yum -y install php httpd mysql

          PHP_VERSION=`php -v | head -n 1 | awk '{print $2}' | awk -F "." '{print $1}'`
          while [  ${PHP_VERSION} -ne 7 ]
          do
          amazon-linux-extras install php7.4 -y
          PHP_VERSION=`php -v | head -n 1 | awk '{print $2}' | awk -F "." '{print $1}'`
          done

          yum -y install php-mbstring php-xml

          wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
          tar zxvf /tmp/latest-ja.tar.gz -C /tmp
          cp -r /tmp/wordpress/* /var/www/html/
          chown apache:apache -R /var/www/html

          systemctl enable httpd.service
          systemctl start httpd.service
  
  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: DBSubnetGroup
      SubnetIds: 
        - !Ref PrivateSubnet1a
        - !Ref PrivateSubnet1c

  DBInstance:
    DependsOn: RDSSecurityGroup
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: 30
      DBInstanceClass: db.m5d.large
      DBInstanceIdentifier: databasey35i89om
      DBName: databasewi526x5l       
      DBSubnetGroupName: !Ref DBSubnetGroup
      Engine: mysql
      EngineVersion: 8.0
      MasterUsername: vbbmcc2t
      MasterUserPassword: rkw35hcq
      MultiAZ: true
      Port: 3306
      PubliclyAccessible: false
      VPCSecurityGroups: 
        - !Ref RDSSecurityGroup
  
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroup
      SecurityGroupIngress: 
        - CidrIp: 0.0.0.0/0
          FromPort: 80
          IpProtocol: tcp
          ToPort:  80
      VpcId: !Ref VPC
  
  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2SecurityGroup
      SecurityGroupIngress: 
        - FromPort: 3306
          IpProtocol: tcp
          ToPort:  3306
          SourceSecurityGroupId: !Ref EC2SecurityGroup
      VpcId: !Ref VPC

```

## 結果
デフォルトで以下のようなサイトを表示させることができました！
![スクリーンショット 2024-03-31 0.43.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3747730/f2b3924f-90c5-423f-6811-885f3a8a8244.png)

ユーザー名とパスワードを登録して管理者ページにも遷移できました！
![スクリーンショット 2024-03-31 0.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3747730/76b73879-043d-e2fa-1121-5d3ed79b5429.png)