💻

【AWSハンズオン】AWSでスケーラブルなWEBサイトを構築する

2024/06/10に公開

https://pages.awscloud.com/rs/112-TZM-766/images/Hands-On-for-Beginners_2022_Scalable_0819_v1.png

目標

  • EC2, ELB, RDSを使用する
  • ウェブサービス規模に合わせて、柔軟にシステム拡張する
  • CLoudFormationでソースコード化

前提条件

  • ハンズオン用の新しいAWSアカウントを用意する
  • AdministratorAccess を持つIAMユーザー

今回作成したのリソースのIaC

CloudFormationで生成されたコード(YAML)
---
Metadata:
  TemplateId: "arn:aws:cloudformation:ap-northeast-1:975050180086:generatedTemplate/f0ee5e3d-3dfd-4491-b22c-226d5bf5cbe9"
Parameters:
  RDSDBSubnetGroup00dbsubneteg0100JPV1eSubnetIdsPLU9f:
    NoEcho: "true"
    Type: "CommaDelimitedList"
    Description: "The EC2 Subnet IDs for the DB subnet group."
Resources:
  EC2SubnetRouteTableAssociation00rtbassoc08001bc623df9901e00tbeyY:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb066f12bf0d551dc1a00vY9x7"
      SubnetId:
        Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
  EC2Route00rtb066f12bf0d551dc1a00p3lw7:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Route"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb066f12bf0d551dc1a00vY9x7"
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId:
        Ref: "EC2InternetGateway00igw0278210f906044a7400f3Rff"
      VpcEndpointId: "igw-0278210f906044a74"
  EC2NetworkAcl00acl00eb3611e9564542500Mhtws:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkAcl"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      Tags: []
  EC2SecurityGroup00sg09cae9034f4c8620400e13Rv:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SecurityGroup"
    DeletionPolicy: "Retain"
    Properties:
      GroupDescription: "db-user01"
      GroupName: "db-user01"
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      SecurityGroupIngress:
      - IpProtocol: "tcp"
        FromPort: 3306
        SourceSecurityGroupId: "sg-025dda26fe02ebf78"
        ToPort: 3306
        SourceSecurityGroupOwnerId: "975050180086"
      SecurityGroupEgress:
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "-1"
        FromPort: -1
        ToPort: -1
  EC2VolumeAttachment00vol051b7f45546f2628700eoj3x:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::VolumeAttachment"
    DeletionPolicy: "Retain"
    Properties:
      InstanceId: "i-0a7b24f9bcb93c723"
      VolumeId: "vol-051b7f45546f26287"
      Device: "/dev/xvda"
  EC2RouteTable00rtb066f12bf0d551dc1a00vY9x7:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::RouteTable"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      Tags:
      - Value: "project-eg1-rtb-public"
        Key: "Name"
  EC2NetworkInterface00eni0f22d2e4b1c9691a5008hsdS:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: ""
      PrivateIpAddress: "10.0.0.250"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.0.250"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-025dda26fe02ebf78"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2VPC00vpc050d0e7e9e4cfb65f004iTrI:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::VPC"
    DeletionPolicy: "Retain"
    Properties:
      CidrBlock: "10.0.0.0/16"
      EnableDnsSupport: true
      InstanceTenancy: "default"
      EnableDnsHostnames: true
      Tags:
      - Value: "project-eg1-vpc"
        Key: "Name"
  EC2SubnetNetworkAclAssociation00aclassoc0011b3581cfe8b98300nupXo:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    DeletionPolicy: "Retain"
    Properties:
      NetworkAclId:
        Ref: "EC2NetworkAcl00acl00eb3611e9564542500Mhtws"
      SubnetId:
        Ref: "EC2Subnet00subnet0f65727d2f08bb9ed00q6ETp"
  RDSDBSubnetGroup00dbsubneteg0100JPV1e:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::RDS::DBSubnetGroup"
    DeletionPolicy: "Retain"
    Properties:
      SubnetIds:
        Ref: "RDSDBSubnetGroup00dbsubneteg0100JPV1eSubnetIdsPLU9f"
      DBSubnetGroupDescription: "db-subnet-eg01"
      DBSubnetGroupName: "db-subnet-eg01"
  EC2Instance00i0ac76abcc9676047c00Db5os:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Instance"
    DeletionPolicy: "Retain"
    Properties:
      Tenancy: "default"
      SecurityGroups:
      - "web-eg01"
      PrivateIpAddress: "10.0.1.209"
      InstanceInitiatedShutdownBehavior: "stop"
      CpuOptions:
        ThreadsPerCore: 1
        CoreCount: 1
      BlockDeviceMappings:
      - Ebs:
          SnapshotId: "snap-0ac7a2a93d0648960"
          VolumeType: "gp2"
          Iops: 100
          VolumeSize: 8
          Encrypted: false
          DeleteOnTermination: true
        DeviceName: "/dev/xvda"
      AvailabilityZone: "ap-northeast-1c"
      PrivateDnsNameOptions:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      SubnetId:
        Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
      SecurityGroupIds:
      - "sg-025dda26fe02ebf78"
      EbsOptimized: false
      DisableApiTermination: false
      SourceDestCheck: true
      Volumes:
      - VolumeId: "vol-00137c92da80cf1ae"
        Device: "/dev/xvda"
      PlacementGroupName: ""
      VpcId: "vpc-050d0e7e9e4cfb65f"
      State:
        Code: "16"
        Name: "running"
      NetworkInterfaces:
      - PrivateIpAddresses:
        - PrivateIpAddress: "10.0.1.209"
          Primary: true
        SecondaryPrivateIpAddressCount: 0
        DeviceIndex: "0"
        GroupSet:
        - Ref: "EC2SecurityGroup00sg025dda26fe02ebf7800TvmTn"
        Ipv6Addresses: []
        SubnetId:
          Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
        AssociatePublicIpAddress: true
        NetworkInterfaceId:
          Ref: "EC2NetworkInterface00eni0617688fff03f3b2f00MPU23"
        DeleteOnTermination: true
      ImageId: "ami-0adb57ece3fccbca2"
      InstanceType: "t2.micro"
      Monitoring: false
      Tags:
      - Value: "webserver#2-eg01"
        Key: "Name"
      CreditSpecification:
        CPUCredits: "standard"
  RDSDBInstance00rdseg0100m5eJw:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::RDS::DBInstance"
    DeletionPolicy: "Retain"
    Properties:
      StorageEncrypted: true
      AssociatedRoles: []
      CertificateDetails: {}
      ProcessorFeatures: []
      StorageThroughput: 0
      PreferredBackupWindow: "18:38-19:08"
      MonitoringInterval: 0
      DBParameterGroupName: "default.mysql8.0"
      Endpoint: {}
      NetworkType: "IPV4"
      DedicatedLogVolume: false
      CopyTagsToSnapshot: true
      MultiAZ: true
      Engine: "mysql"
      Tags: []
      LicenseModel: "general-public-license"
      EngineVersion: "8.0.35"
      StorageType: "gp2"
      KmsKeyId:
        Fn::GetAtt:
        - "KMSKey00db63a7fdf9744d1f9e226ffad93f6b9800BGFUz"
        - "Arn"
      DBInstanceClass: "db.t3.micro"
      AvailabilityZone: "ap-northeast-1a"
      OptionGroupName: "default:mysql-8-0"
      PreferredMaintenanceWindow: "sun:15:00-sun:15:30"
      EnablePerformanceInsights: false
      AutoMinorVersionUpgrade: true
      DBSubnetGroupName:
        Ref: "RDSDBSubnetGroup00dbsubneteg0100JPV1e"
      DeletionProtection: false
      DBInstanceIdentifier: "rds-eg01"
      AllocatedStorage: "20"
      CACertificateIdentifier: "rds-ca-rsa2048-g1"
      ManageMasterUserPassword: false
      MasterUserSecret: {}
      VPCSecurityGroups:
      - Fn::GetAtt:
        - "EC2SecurityGroup00sg09cae9034f4c8620400e13Rv"
        - "GroupId"
      DBSecurityGroups: []
      MasterUsername: "admin"
      DBName: "Wordpress"
      EnableIAMDatabaseAuthentication: false
      MaxAllocatedStorage: 1000
      BackupRetentionPeriod: 0
      PubliclyAccessible: false
      EnableCloudwatchLogsExports: []
  EC2SubnetNetworkAclAssociation00aclassoc0067af7ea3d8ca22400c9qGG:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    DeletionPolicy: "Retain"
    Properties:
      NetworkAclId:
        Ref: "EC2NetworkAcl00acl00eb3611e9564542500Mhtws"
      SubnetId:
        Ref: "EC2Subnet00subnet0eae5af9f6788716b00XIx3c"
  EC2NetworkInterface00eni0fbea3406f44ea03e00jrE5J:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: "RDSNetworkInterface"
      PrivateIpAddress: "10.0.2.139"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.2.139"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-09cae9034f4c86204"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet0eae5af9f6788716b00XIx3c"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2SubnetRouteTableAssociation00rtbassoc0a1454101738920fd00dKTo8:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb066f12bf0d551dc1a00vY9x7"
      SubnetId:
        Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
  KMSKey00db63a7fdf9744d1f9e226ffad93f6b9800BGFUz:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::KMS::Key"
    DeletionPolicy: "Retain"
    Properties:
      Origin: "AWS_KMS"
      MultiRegion: false
      Description: "Default key that protects my RDS database volumes when no other\
        \ key is defined"
      KeyPolicy:
        Version: "2012-10-17"
        Statement:
        - Condition:
            StringEquals:
              kms:CallerAccount: "975050180086"
              kms:ViaService: "rds.ap-northeast-1.amazonaws.com"
          Resource: "*"
          Action:
          - "kms:Encrypt"
          - "kms:Decrypt"
          - "kms:ReEncrypt*"
          - "kms:GenerateDataKey*"
          - "kms:CreateGrant"
          - "kms:ListGrants"
          - "kms:DescribeKey"
          Effect: "Allow"
          Principal:
            AWS: "*"
          Sid: "Allow access through RDS for all principals in the account that are\
            \ authorized to use RDS"
        - Resource: "*"
          Action:
          - "kms:Describe*"
          - "kms:Get*"
          - "kms:List*"
          - "kms:RevokeGrant"
          Effect: "Allow"
          Principal:
            AWS: "arn:aws:iam::975050180086:root"
          Sid: "Allow direct access to key metadata to the account"
        Id: "auto-rds-2"
      KeySpec: "SYMMETRIC_DEFAULT"
      Enabled: true
      EnableKeyRotation: false
      KeyUsage: "ENCRYPT_DECRYPT"
      Tags: []
  EC2SubnetNetworkAclAssociation00aclassoc0e499f72075071155001Ph67:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    DeletionPolicy: "Retain"
    Properties:
      NetworkAclId:
        Ref: "EC2NetworkAcl00acl00eb3611e9564542500Mhtws"
      SubnetId:
        Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
  EC2RouteTable00rtb09e26ed041c34f6b1003BpfG:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::RouteTable"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      Tags:
      - Value: "project-eg1-rtb-private1-ap-northeast-1a"
        Key: "Name"
  EC2VolumeAttachment00vol00137c92da80cf1ae00XA6Cg:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::VolumeAttachment"
    DeletionPolicy: "Retain"
    Properties:
      InstanceId: "i-0ac76abcc9676047c"
      VolumeId: "vol-00137c92da80cf1ae"
      Device: "/dev/xvda"
  EC2NetworkInterface00eni0f1eae239f7a7aca700GWn14:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: "ELB app/elb-eg01/952db96929c35303"
      PrivateIpAddress: "10.0.1.216"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.1.216"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-0d3bbc33a6e6d254a"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2SubnetRouteTableAssociation00rtbassoc0220a7aa5b8976ffe00qKG9M:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb09e26ed041c34f6b1003BpfG"
      SubnetId:
        Ref: "EC2Subnet00subnet0eae5af9f6788716b00XIx3c"
  EC2Subnet00subnet024e0b0fab4658e9c00d94Ch:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Subnet"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      MapPublicIpOnLaunch: false
      EnableDns64: false
      AvailabilityZoneId: "apne1-az1"
      PrivateDnsNameOptionsOnLaunch:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      CidrBlock: "10.0.1.0/24"
      Ipv6Native: false
      Tags:
      - Value: "project-public-1c"
        Key: "Name"
  EC2Instance00i0a7b24f9bcb93c72300lcuIO:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Instance"
    DeletionPolicy: "Retain"
    Properties:
      Tenancy: "default"
      SecurityGroups:
      - "web-eg01"
      PrivateIpAddress: "10.0.0.250"
      UserData: "IyEvYmluL2Jhc2gKCnl1bSAteSB1cGRhdGUKeXVtIC15IGluc3RhbGwgcGhwIGh0dHBkIG15c3FsCgpQSFBfVkVSU0lPTj1gcGhwIC12IHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9JyB8IGF3ayAtRiAiLiIgJ3twcmludCAkMX0nYAp3aGlsZSBbICAke1BIUF9WRVJTSU9OfSAtbmUgNyBdCmRvCmFtYXpvbi1saW51eC1leHRyYXMgaW5zdGFsbCBwaHA3LjQgLXkKUEhQX1ZFUlNJT049YHBocCAtdiB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfScgfCBhd2sgLUYgIi4iICd7cHJpbnQgJDF9J2AKZG9uZQoKeXVtIC15IGluc3RhbGwgcGhwLW1ic3RyaW5nIHBocC14bWwKCndnZXQgaHR0cDovL2phLndvcmRwcmVzcy5vcmcvbGF0ZXN0LWphLnRhci5neiAtUCAvdG1wLwp0YXIgenh2ZiAvdG1wL2xhdGVzdC1qYS50YXIuZ3ogLUMgL3RtcApjcCAtciAvdG1wL3dvcmRwcmVzcy8qIC92YXIvd3d3L2h0bWwvCmNob3duIGFwYWNoZTphcGFjaGUgLVIgL3Zhci93d3cvaHRtbAoKc3lzdGVtY3RsIGVuYWJsZSBodHRwZC5zZXJ2aWNlCnN5c3RlbWN0bCBzdGFydCBodHRwZC5zZXJ2aWNl"
      InstanceInitiatedShutdownBehavior: "stop"
      CpuOptions:
        ThreadsPerCore: 1
        CoreCount: 1
      BlockDeviceMappings:
      - Ebs:
          SnapshotId: "snap-039b08cb18650eeb5"
          VolumeType: "gp2"
          Iops: 100
          VolumeSize: 8
          Encrypted: false
          DeleteOnTermination: true
        DeviceName: "/dev/xvda"
      AvailabilityZone: "ap-northeast-1a"
      PrivateDnsNameOptions:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      SubnetId:
        Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
      SecurityGroupIds:
      - "sg-025dda26fe02ebf78"
      EbsOptimized: false
      DisableApiTermination: false
      SourceDestCheck: true
      Volumes:
      - VolumeId: "vol-051b7f45546f26287"
        Device: "/dev/xvda"
      PlacementGroupName: ""
      VpcId: "vpc-050d0e7e9e4cfb65f"
      State:
        Code: "16"
        Name: "running"
      NetworkInterfaces:
      - PrivateIpAddresses:
        - PrivateIpAddress: "10.0.0.250"
          Primary: true
        SecondaryPrivateIpAddressCount: 0
        DeviceIndex: "0"
        GroupSet:
        - Ref: "EC2SecurityGroup00sg025dda26fe02ebf7800TvmTn"
        Ipv6Addresses: []
        SubnetId:
          Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
        AssociatePublicIpAddress: true
        NetworkInterfaceId:
          Ref: "EC2NetworkInterface00eni0f22d2e4b1c9691a5008hsdS"
        DeleteOnTermination: true
      ImageId: "ami-01d078c099c7f1261"
      InstanceType: "t2.micro"
      Monitoring: false
      Tags:
      - Value: "webserver#1-eg01"
        Key: "Name"
      CreditSpecification:
        CPUCredits: "standard"
  ElasticLoadBalancingV2Listener00listenerappelbeg01952db96929c3530350ef503186a9beb700cg7Xs:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    DeletionPolicy: "Retain"
    Properties:
      Protocol: "HTTP"
      LoadBalancerArn:
        Ref: "ElasticLoadBalancingV2LoadBalancer00loadbalancerappelbeg01952db96929c3530300yjbEy"
      DefaultActions:
      - TargetGroupArn:
          Ref: "ElasticLoadBalancingV2TargetGroup00targetgrouptargeteg019dffdc249530bbb700Kvari"
        Type: "forward"
        ForwardConfig:
          TargetGroupStickinessConfig:
            Enabled: false
          TargetGroups:
          - TargetGroupArn:
              Ref: "ElasticLoadBalancingV2TargetGroup00targetgrouptargeteg019dffdc249530bbb700Kvari"
            Weight: 1
      Port: 80
  EC2Subnet00subnet09bb46ec4214fe4d600wHHaf:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Subnet"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      MapPublicIpOnLaunch: false
      EnableDns64: false
      AvailabilityZoneId: "apne1-az4"
      PrivateDnsNameOptionsOnLaunch:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      CidrBlock: "10.0.0.0/24"
      Ipv6Native: false
      Tags:
      - Value: "project-public-1a"
        Key: "Name"
  EC2SecurityGroup00sg0d3bbc33a6e6d254a00SFeDK:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SecurityGroup"
    DeletionPolicy: "Retain"
    Properties:
      GroupDescription: "elb-eg01"
      GroupName: "elb-eg01"
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      SecurityGroupIngress:
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "tcp"
        FromPort: 80
        ToPort: 80
      SecurityGroupEgress:
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "-1"
        FromPort: -1
        ToPort: -1
  EC2Subnet00subnet0f65727d2f08bb9ed00q6ETp:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Subnet"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      MapPublicIpOnLaunch: false
      EnableDns64: false
      AvailabilityZoneId: "apne1-az1"
      PrivateDnsNameOptionsOnLaunch:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      CidrBlock: "10.0.3.0/24"
      Ipv6Native: false
      Tags:
      - Value: "project-private-1c"
        Key: "Name"
  EC2SubnetRouteTableAssociation00rtbassoc01c207d43bc3621a500iQynG:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb01e94e28276a472a000x6Y1c"
      SubnetId:
        Ref: "EC2Subnet00subnet0f65727d2f08bb9ed00q6ETp"
  ElasticLoadBalancingV2LoadBalancer00loadbalancerappelbeg01952db96929c3530300yjbEy:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    DeletionPolicy: "Retain"
    Properties:
      IpAddressType: "ipv4"
      SecurityGroups:
      - "sg-0d3bbc33a6e6d254a"
      LoadBalancerAttributes:
      - Value: ""
        Key: "access_logs.s3.prefix"
      - Value: "append"
        Key: "routing.http.xff_header_processing.mode"
      - Value: "true"
        Key: "routing.http2.enabled"
      - Value: "false"
        Key: "waf.fail_open.enabled"
      - Value: ""
        Key: "connection_logs.s3.bucket"
      - Value: "false"
        Key: "access_logs.s3.enabled"
      - Value: "defensive"
        Key: "routing.http.desync_mitigation_mode"
      - Value: ""
        Key: "connection_logs.s3.prefix"
      - Value: "false"
        Key: "routing.http.x_amzn_tls_version_and_cipher_suite.enabled"
      - Value: "false"
        Key: "routing.http.preserve_host_header.enabled"
      - Value: "true"
        Key: "load_balancing.cross_zone.enabled"
      - Value: "false"
        Key: "routing.http.xff_client_port.enabled"
      - Value: ""
        Key: "access_logs.s3.bucket"
      - Value: "false"
        Key: "deletion_protection.enabled"
      - Value: "3600"
        Key: "client_keep_alive.seconds"
      - Value: "false"
        Key: "routing.http.drop_invalid_header_fields.enabled"
      - Value: "false"
        Key: "connection_logs.s3.enabled"
      - Value: "60"
        Key: "idle_timeout.timeout_seconds"
      Subnets:
      - Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
      - Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
      Type: "application"
      Scheme: "internet-facing"
      EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic: ""
      Tags: []
      Name: "elb-eg01"
      SubnetMappings:
      - SubnetId:
          Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
      - SubnetId:
          Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
  EC2InternetGateway00igw0278210f906044a7400f3Rff:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::InternetGateway"
    DeletionPolicy: "Retain"
    Properties:
      Tags:
      - Value: "project-eg1-igw"
        Key: "Name"
  EC2NetworkInterface00eni0617688fff03f3b2f00MPU23:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: ""
      PrivateIpAddress: "10.0.1.209"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.1.209"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-025dda26fe02ebf78"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet024e0b0fab4658e9c00d94Ch"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2Route00rtb09e26ed041c34f6b100Ijp1I:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Route"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb09e26ed041c34f6b1003BpfG"
      DestinationCidrBlock:
        Fn::GetAtt:
        - "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
        - "CidrBlock"
      GatewayId: "local"
      VpcEndpointId: "local"
  EC2NetworkInterface00eni066295e9b81cda28a00fnCyd:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: "ELB app/elb-eg01/952db96929c35303"
      PrivateIpAddress: "10.0.0.18"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.0.18"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-0d3bbc33a6e6d254a"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2SecurityGroup00sg025dda26fe02ebf7800TvmTn:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SecurityGroup"
    DeletionPolicy: "Retain"
    Properties:
      GroupDescription: "web-eg01"
      GroupName: "web-eg01"
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      SecurityGroupIngress:
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "tcp"
        FromPort: 80
        ToPort: 80
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "tcp"
        FromPort: 22
        ToPort: 22
      SecurityGroupEgress:
      - CidrIp: "0.0.0.0/0"
        IpProtocol: "-1"
        FromPort: -1
        ToPort: -1
  EC2RouteTable00rtb01e94e28276a472a000x6Y1c:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::RouteTable"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      Tags:
      - Value: "project-eg1-rtb-private2-ap-northeast-1c"
        Key: "Name"
  EC2Subnet00subnet0eae5af9f6788716b00XIx3c:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Subnet"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      MapPublicIpOnLaunch: false
      EnableDns64: false
      AvailabilityZoneId: "apne1-az4"
      PrivateDnsNameOptionsOnLaunch:
        EnableResourceNameDnsARecord: false
        HostnameType: "ip-name"
        EnableResourceNameDnsAAAARecord: false
      CidrBlock: "10.0.2.0/24"
      Ipv6Native: false
      Tags:
      - Value: "project-private-1a"
        Key: "Name"
  EC2NetworkInterface00eni0f8f3d633d9bce82e00xBOlj:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::NetworkInterface"
    DeletionPolicy: "Retain"
    Properties:
      Description: "RDSNetworkInterface"
      PrivateIpAddress: "10.0.3.70"
      PrivateIpAddresses:
      - PrivateIpAddress: "10.0.3.70"
        Primary: true
      SecondaryPrivateIpAddressCount: 0
      Ipv6PrefixCount: 0
      Ipv4Prefixes: []
      Ipv4PrefixCount: 0
      GroupSet:
      - "sg-09cae9034f4c86204"
      Ipv6Prefixes: []
      SubnetId:
        Ref: "EC2Subnet00subnet0f65727d2f08bb9ed00q6ETp"
      SourceDestCheck: true
      InterfaceType: "interface"
      Tags: []
  EC2Volume00vol00137c92da80cf1ae00DSChK:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Volume"
    DeletionPolicy: "Retain"
    Properties:
      MultiAttachEnabled: false
      SnapshotId: "snap-0ac7a2a93d0648960"
      VolumeType: "gp2"
      Encrypted: false
      Size: 8
      AutoEnableIO: true
      AvailabilityZone: "ap-northeast-1c"
      Iops: 100
      Tags: []
  EC2SubnetNetworkAclAssociation00aclassoc07f925844fb93a4da00Rd7pn:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::SubnetNetworkAclAssociation"
    DeletionPolicy: "Retain"
    Properties:
      NetworkAclId:
        Ref: "EC2NetworkAcl00acl00eb3611e9564542500Mhtws"
      SubnetId:
        Ref: "EC2Subnet00subnet09bb46ec4214fe4d600wHHaf"
  ElasticLoadBalancingV2TargetGroup00targetgrouptargeteg019dffdc249530bbb700Kvari:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    DeletionPolicy: "Retain"
    Properties:
      IpAddressType: "ipv4"
      HealthCheckIntervalSeconds: 30
      Matcher:
        HttpCode: "200"
      HealthCheckPath: "/wp-includes/images/blank.gif"
      Port: 80
      Targets:
      - Port: 80
        Id: "i-0ac76abcc9676047c"
      - Port: 80
        Id: "i-0a7b24f9bcb93c723"
      HealthCheckEnabled: true
      ProtocolVersion: "HTTP1"
      UnhealthyThresholdCount: 2
      HealthCheckTimeoutSeconds: 5
      Name: "target-eg01"
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
      HealthyThresholdCount: 5
      HealthCheckProtocol: "HTTP"
      TargetGroupAttributes:
      - Value: "lb_cookie"
        Key: "stickiness.type"
      - Value: "86400"
        Key: "stickiness.app_cookie.duration_seconds"
      - Value: "1"
        Key: "target_group_health.dns_failover.minimum_healthy_targets.count"
      - Value: "use_load_balancer_configuration"
        Key: "load_balancing.cross_zone.enabled"
      - Value: "86400"
        Key: "stickiness.lb_cookie.duration_seconds"
      - Value: "off"
        Key: "target_group_health.dns_failover.minimum_healthy_targets.percentage"
      - Value: "false"
        Key: "stickiness.enabled"
      - Value: "off"
        Key: "target_group_health.unhealthy_state_routing.minimum_healthy_targets.percentage"
      - Value: "0"
        Key: "slow_start.duration_seconds"
      - Value: "300"
        Key: "deregistration_delay.timeout_seconds"
      - Value: "1"
        Key: "target_group_health.unhealthy_state_routing.minimum_healthy_targets.count"
      - Value: "off"
        Key: "load_balancing.algorithm.anomaly_mitigation"
      - Value: ""
        Key: "stickiness.app_cookie.cookie_name"
      - Value: "round_robin"
        Key: "load_balancing.algorithm.type"
      TargetType: "instance"
      HealthCheckPort: "traffic-port"
      Protocol: "HTTP"
      Tags: []
  EC2RouteTable00rtb099ba37fa54d9c8f400BA7ki:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::RouteTable"
    DeletionPolicy: "Retain"
    Properties:
      VpcId:
        Ref: "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
  EC2Volume00vol051b7f45546f2628700PznJA:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Volume"
    DeletionPolicy: "Retain"
    Properties:
      MultiAttachEnabled: false
      SnapshotId: "snap-039b08cb18650eeb5"
      VolumeType: "gp2"
      Encrypted: false
      Size: 8
      AutoEnableIO: true
      AvailabilityZone: "ap-northeast-1a"
      Iops: 100
      Tags: []
  EC2Route00rtb01e94e28276a472a000enKM4:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::EC2::Route"
    DeletionPolicy: "Retain"
    Properties:
      RouteTableId:
        Ref: "EC2RouteTable00rtb01e94e28276a472a000x6Y1c"
      DestinationCidrBlock:
        Fn::GetAtt:
        - "EC2VPC00vpc050d0e7e9e4cfb65f004iTrI"
        - "CidrBlock"
      GatewayId: "local"
      VpcEndpointId: "local"
  RDSOptionGroup00defaultmysql8000XoWnp:
    UpdateReplacePolicy: "Retain"
    Type: "AWS::RDS::OptionGroup"
    DeletionPolicy: "Retain"
    Properties:
      OptionGroupDescription: "Default option group for mysql 8.0"
      OptionGroupName: "default:mysql-8-0"
      OptionConfigurations: []
      MajorEngineVersion: "8.0"
      EngineName: "mysql"
      Tags: []


実装手順

1.VPCを作成する

検索窓に「VPC」と入力し、VPCのコンソールに遷移
「VPCを作成」ボタンを押下

画像の通りにVPCの設定をする



今回の要件ではAZx2, サブネット(public+private)x2を想定している

項目 設定値
作成するリソース VPCなど
名前タグの自動生成 自動生成
IPv4 CIDR ブロック 10.0.0.0/16
IPv6 CIDR ブロック なし
アベイラビリティゾーン (AZ) の数 2
第1アベイラビリティーゾーン ap-northeast-1a
第2アベイラビリティーゾーン ap-northeast-1c
パブリックサブネットの数 2
プライベートサブネットの数 2
ap-northeast-1a のパブリックサブネット CIDR ブロック 10.0.0.0/24
ap-northeast-1c のパブリックサブネット CIDR ブロック 10.0.1.0/24
ap-northeast-1a のプライベートサブネット CIDR ブロック 10.0.2.0/24
ap-northeast-1c のプライベートサブネット CIDR ブロック 10.0.3.0/24
NAT ゲートウェイ ($) なし
VPC エンドポイント なし
  • 最下部の「VPCを作成」ボタンを押下
  • プログレス進行後、VPCが作成される
  • (任意)VPC、サブネットの名前変更

2.AmazonEC2を作成する

  • EC2 コンソールに移動し、「インスタンスを起動」を押下
項目 設定値
Amazon マシンイメージ(AMI) Amazon Linux2 AMI (HVM) Kernel 5.10, SSD Volume Type
インスタンスタイプ t2.micro
キーペア名 - 必須 キーペアなしで続行(推奨されません)

※キーペア名:SSHを設定するときに使用。今回は不要

ネットワーク設定


  • 「編集」ボタンを押す
  • VPC は 1.VPCを作成する で作成したものを使用する
  • パブリックサブネットは ap-northeast-1a のものを使う
  • セキュリティグループ名をつける
  • インバウンドセキュリティグループのルールを追加する
    • HTTPを追加
    • ソースに 0.0.0.0/0を追加

ストレージを設定

今回はスキップ

高度な詳細

ユーザーデータ - オプション にコマンドを貼り付ける

EC2インスタンス起動時にWordPressの自動インストールと起動を行うコマンド
https://pages.awscloud.com/rs/112-TZM-766/images/hfb_2022_wordpress_installation.txt

「インスタンスを起動」を押下し、インスタンスの起動を確認

パブリックIPアドレスをコピーし、先頭にhttp://をつけると、WordPressの画面にアクセスできる。

RDS DBインスタンス用のセキュリティグループを作成する

EC2>セキュリティグループにアクセスし、「セキュリティグループを作成」を押下する。

基本的な詳細

  • セキュリティグループ名・説明は任意の値
  • VPCは先ほど作成したもので設定

インバウンドルール

項目 設定値
タイプ MySQL Aurora
プロトコル TCP(自動)
ポート番号 3306(自動)
ソース EC2インスタンスのセキュリティグループ


他の項目はデフォルト
セキュリティグループを作成

3.Amazon RDSを作成する

RDS>サブネットグループへ移動し、「DBサブネットグループを作成」を押下

サブネットグループの詳細

  • 名前・説明は任意の値
  • VPCは先ほど作成したもので設定

サブネットを追加

  • AZはap-northeast-1aとap-northeast-1cを指定
  • サブネットはプライベートなので10.0.2.0/24と10.0.3.0/24を指定

RDS>データベースへ移動し、「データベースの作成」を押下

DBエンジンはMySQLを選択

テンプレートは無料利用枠を選択

認証情報管理を「セルフマネージド」に設定してパスワードを設定
※本番環境ではSecretManagerの使用を推奨

インスタンスの設定・ストレージはデフォルトのまま

「EC2コンピューティングリソースに接続しない」を選択する。
VPCとVPCセキュリティグループ、DBサブネットグループを作成したものに設定する

追加設定でDBの名前を設定する。

データベースを作成し、時間経過後に実行中となることを確認

RDSを選択し、RDSエンドポイントをコピーしメモに取る

4.負荷分散用のELBを作成する

ELBのセキュリティグループを作成する。
EC2>セキュリティグループに移動し、「セキュリティグループを作成」を押下する

基本的な詳細

  • セキュリティグループ名・説明は任意の値
  • VPCは先ほど作成したもので設定

インバウンドルール

  • HTTPを選択し、ソースにAnyWhereIPv4を選択する。0.0.0.0/0を設定する
  • アウトバウンドルールはデフォルトのまま

セキュリティグループを作成完了

EC2>ターゲットグループに移動する。「ターゲットグループの作成」を押下する

ターゲットグループ名とVPCを設定する


ヘルスチェックパスは以下のリンク内のパスを記入。(空白に注意)

https://pages.awscloud.com/rs/112-TZM-766/images/healthcheck_path.txt

使用可能なインスタンスにチェックを入れる。「保留中として以下を含める」を押下する。

ターゲットを確認の欄に保留中のインスタンスが含まれていることを確認し、ターゲットグループを作成

EC2>ロードバランサーに移動し、「ロードバランサーを作成」を押下

ALB(Application Load Balancer)を選択し、作成

VPCとパブリックサブネットを設定する

リスナーにHTTPを選択し、作成したターゲットグループを転送先にアタッチする

WAFやGlobal Acceleratorはここで適用できる(今回はパス)

ロードバランサーが作成され、状態がアクティブになっていることを確認する

ELBを選択する。DNS名をコピーし、メモに取る
(WordPressのホスト名に使用する)

5.WordPressを初期設定する

コピーしたDNS名の先頭に"http://"を付加して検索すると、WordPressの設定ページに飛ぶ

RDS>データベースから、DB識別子をクリックする

接続とセキュリティから、RDSのエンドポイントをコピーする

WordPress設定画面でコピーしたエンドポイントをデータベースのホスト名に貼り付ける
送信ボタンを押す

「インストール実行」ボタンを押す

必要事項を記入する。あとで管理画面でカスタマイズする場合はパスワードをコピーする

インストールに成功するので、ログインボタンを押す

サイトのタイトル(はじめてのAWS)をクリックする

サイトへのアクセスが確認できる

6.AMIの作成と作成したAMIから2つめのEC2インスタンス起動

AMIを作成する

EC2>インスタンスでインスタンスを選択する
アクション>イメージとテンプレート>イメージを作成をクリック

イメージ名を設定し、「イメージを作成する」ボタンを押下する

AMIが作成される。選択後、「AMIからインスタンスを起動」ボタンを押す

2つ目のインスタンスを起動する

名前を設定する。アプリケーションおよびOSイメージ、インスタンスタイプ、キーペアは一つ目のインスタンスと設定は同じ


ネットワーク設定を編集する
VPC,パブリックサブネット(AZはap-northeast-1c)、パブリックIP自動割り当てを設定する
セキュリティグループは既存のインスタンスのものを使用する

高度な詳細>ユーザーデータについては、AMI作成時にソースファイルが含まれているため記入の必要はない
インスタンスを起動する

2つ目のインスタンスが起動したことを確認する

2つ目のインスタンスをELBに紐づける

EC2>ターゲットグループより作成済みのターゲットグループの名前をクリックする

登録済みターゲットの「ターゲットを登録」ボタンを押す

2つ目のインスタンスを選択し、「保留中として以下を含める」ボタンを押す

2つ目のインスタンスが保留中になっていることを確認し、「保留中のターゲットを登録」ボタンを押す

登録済みターゲットに2つ目のインスタンスが登録されている

2つ目のインスタンスとELBが連携される

7.作成済みのRDS DBインスタンスをマルチAZ化する

RDS>データベースより、データベースにチェックを入れる。変更ボタンを押す

可用性と耐久性の欄で、「スタンバイインスタンスを作成する」にチェックを入れる

ページ最下部の「続行」ボタンを押す

変更のスケジュールの「すぐに適用」にチェックを入れる。「DBインスタンスを変更」ボタンを押す

DB設定の変更が始まる

時間経過後に、マルチAZがありになっていることを確認する

今後の課題

基本的なスケーラブルWebサイトを構築できた。
Webサイトの部分をCloudFront + S3を使用した静的サイトに変える、インスタンス-DB部分をDocker + Fargateに変えるなどアレンジを試してみたい。
CloudFormation でコード化する際にリソース選択するのが面倒だったので、リソースへのタグ付けを今後試そうと思った。

参考文献

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Scalable-2022-confirmation_386.html

Discussion