Using Image Builder to create an AMI for WordPress

Using Image Builder to create an AMI for WordPress.

Using Image Builder to create an AMI for WordPress

The following pages discuss the Image Builder.

あわせて読みたい
Introduction to EC2 Image Builder using CloudFormation 【Introduction to EC2 Image Builder using CloudFormation】 This page covers the EC2 Image Builder. Image Builder significantly reduces the effort of keeping ...

In this page, we will create an AMI for WordPress as a specific example of using Image Builder.

Environment

Diagram of using Image Builder to create an AMI for WordPress.

The basic structure is the same as the page introduced at the beginning of this document.

There are three changes.

The first point is to create a private creation and place the RDS DB instance there. This DB instance is of type MySQL. This DB instance will act as a WordPress DB server.

The second point is the location of the EC2 instance to be launched by Image Builder. The purpose of this instance is for AMI creation and is used temporarily. In the opening page, this instance was created in the default VPC. In this case, we will access the aforementioned DB instance when building the AMI, so we will place it in the same VPC as the instance.

The third point is to use Route53. This will allow you to access your WordPress site with your own domain. In this case, we will use the domain awstut.net, which we obtained with Route53. Create an A record in Route53. This record associates the domain with the Elastic IP of the WordPress server.

CloudFormation template files

The above configuration is built with CloudFormation. The CloudFormation templates are placed at the following URL

https://github.com/awstut-an-r/awstut-fa/tree/main/144

Explanation of key points of template files

This page focuses on how to create an AMI for WordPress using Image Builder.

For basic information about Image Builder, please review the following pages.

あわせて読みたい
Introduction to EC2 Image Builder using CloudFormation 【Introduction to EC2 Image Builder using CloudFormation】 This page covers the EC2 Image Builder. Image Builder significantly reduces the effort of keeping ...

Image Builder

Resources:
  Component:
    Type: AWS::ImageBuilder::Component
    Properties:
      Data: !Sub |
        schemaVersion: 1.0
        phases:
          - name: build
            steps:
              - name: InstallWordPress
                action: ExecuteBash
                inputs:
                  commands:
                    - yum update -y
                    - yum install -y httpd
                    - amazon-linux-extras enable -y php7.4

                    - yum install -y php php-gd php-mysqlnd php-xmlrpc -y
                    - yum install -y mariadb

                    - systemctl start httpd
                    - systemctl enable httpd

                    - cd /var/www/html

                    - curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
                    - chmod +x wp-cli.phar
                    - mv wp-cli.phar /usr/local/bin/wp
                    - wp core download --locale=ja
                    - wp core config --dbname="${DBName}" --dbuser="${DBMasterUsername}" --dbpass="${DBMasterUserPassword}" --dbhost="${DBInstanceEndpointAddress}"
                    - wp core install --url="http://${DomainName}" --title="${WordPressTitle}" --admin_user="${WordPressAdminUser}" --admin_password="${WordPressAdminPassword}" --admin_email="${WordPressAdminEmail}"
      Name: !Sub "${Prefix}-Component"
      Platform: !Ref ImageBuilderPlatform
      SupportedOsVersions:
        - !Ref ImageBuilderSupportedOsVersion
      Version: !Ref ImageBuilderVersion

  ImageRecipe:
    Type: AWS::ImageBuilder::ImageRecipe
    Properties:
      Components:
        - ComponentArn: !Ref Component
      Name: !Sub "${Prefix}-ImageRecipe"
      ParentImage: !Ref ImageBuilderParentImage
      Version: !Ref ImageBuilderVersion

  InfrastructureConfiguration:
    Type: AWS::ImageBuilder::InfrastructureConfiguration
    Properties:
      InstanceProfileName: !Ref ImageBuilderRoleProfile
      InstanceTypes:
        - !Ref InstanceType
      Name: !Sub "${Prefix}-InfrastructureConfiguration"
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      SnsTopicArn: !Ref Topic
      SubnetId: !Ref PublicSubnet2

  DistributionConfiguration:
    Type: AWS::ImageBuilder::DistributionConfiguration
    Properties:
      Distributions:
        - Region: !Ref AWS::Region
          AmiDistributionConfiguration: {}
      Name: !Sub "${Prefix}-DistributionConfiguration"

  ImagePipeline:
    Type: AWS::ImageBuilder::ImagePipeline
    Properties:
      DistributionConfigurationArn: !Ref DistributionConfiguration
      ImageRecipeArn: !Ref ImageRecipe
      InfrastructureConfigurationArn: !Ref InfrastructureConfiguration
      Name: !Sub "${Prefix}-ImagePipeline"
      Status: ENABLED

  ImageBuilderRoleProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref ImageBuilderRole

  ImageBuilderRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - ec2.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder
Code language: YAML (yaml)

There are two key resources for creating an AMI for WordPress.

The first is a component. This resource defines the WordPress installation and initial configuration procedures. Specifically, we first install and activate the packages for running WordPress (Apache, PHP).

Then use WP-CLI to configure WordPress.

https://wp-cli.org/ja/

Specifically, the following will be implemented

  • Installing WP-CLI
  • Download WordPress itself
  • Setup of wp-config.php
  • WordPress Installation

The second is the infrastructure configuration. The SubnetId property is important. The component states that during the AMI build, WordPress is to be installed as well. This means that the RDS instance, the DB server, must be accessible. This means that the EC2 instance for Image Builder must be placed on the subnet within the VPC where the DB instance is running.

In addition, this EC2 instance must have access to the Internet. This instance will download the WP-CLI and WordPress itself, as well as access SSM and S3 for the Image Builder to work properly.

Place the instance on a public subnet (PublicSubnet2) for the instance to communicate to the Internet.

Check the details of this subnet.

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCidrBlock

  IGW:
    Type: AWS::EC2::InternetGateway

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

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone2}"
      CidrBlock: !Ref CidrIp2
      MapPublicIpOnLaunch: true
      VpcId: !Ref VPC

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC

  RouteToInternet:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW

  PublicSubnetRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet2
      RouteTableId: !Ref PublicRouteTable
Code language: YAML (yaml)

This subnet has a default route to the Internet Gateway. And by enabling the MapPublicIpOnLaunch property, you can have the public address automatically granted when the instance is launched.

EC2 Instance

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Sub "{{resolve:ssm:${ParameterAmi}}}"
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - !Ref InstanceSecurityGroup
          SubnetId: !Ref PublicSubnet1

  EIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      InstanceId: !Ref Instance
Code language: YAML (yaml)

There are two points.

The first is the ImageId property. Stores the ID of the AMI built by the Image Builder in the SSM Parameter Store. Specify this value to this property using a dynamic reference in CloudFormation. For more information, see the page mentioned at the beginning of this article.

The second is the Elastic IP. This instance can be accessed with a custom domain using Route53 as described below. So the global address to be assigned to this instance is fixed using Elastic IP.

(Reference) RDS

Resources:
  DBInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Delete
    Properties:
      AllocatedStorage: !Ref DBAllocatedStorage
      DBInstanceClass: !Ref DBInstanceClass
      DBInstanceIdentifier: dbinstance
      DBName: !Ref DBName
      DBSubnetGroupName: !Ref DBSubnetGroup
      Engine: !Ref DBEngine
      EngineVersion: !Ref DBEngineVersion
      MasterUsername: !Ref DBMasterUsername
      MasterUserPassword: !Ref DBMasterUserPassword
      VPCSecurityGroups:
        - !Ref DBSecurityGroup

  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupName: dbsubnetgroup
      DBSubnetGroupDescription: dbsubnetgroup.
      SubnetIds:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
Code language: YAML (yaml)

Create one RDS DB instance. No special configuration is performed.

Set up as follows

  • User name: testuser
  • Password: Passw0rd
  • DB name: wordpress

(Reference) Route53

Resources:
  DnsRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref HostedZoneId
      Name: !Ref DomainName
      ResourceRecords:
        - !Ref EIP
      TTL: !Ref TTL
      Type: A
Code language: YAML (yaml)

Create an A record in Route53. Associate the custom domain with the EIP of the EC2 instance.

Architecting

Use CloudFormation to build this environment and check its actual behavior.

Create CloudFormation stacks and check the resources in the stacks

Create CloudFormation stacks. For information on how to create stacks and check each stack, please see the following page.

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After reviewing the resources in each stack, information on the main resources created in this case is as follows

  • Component: fa-144-Component
  • Pipeline: fa-144-ImagePipeline
  • EC2 instance: i-01c377157641d532d
  • RDS instance endpoint: dbinstance.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com

Check the created resource from the AWS Management Console.

Components.

Detail of Image Builder 1.

The component is created as specified in CloudFormation. Various parameters are passed to the WP CLI. Various DB information (user name, password, etc.) and site information (domain name, title, etc.) are specified.

Check the pipeline.

Detail of Image Builder 3.

Looking at the Workflow, the pipeline has been executed and completed successfully. This means that this pipeline was automatically started by a Lambda function tied to a CloudFormation custom resource.

Detail of Image Builder 2.

Looking at the Output, an AMI has been created. The ID of the AMI generated this time was “ami-0014da8524101ba45”.

Check the EC2 instance.

Diagram of EC2 1.

The instance is successfully created. I see the AMI “ami-0014da8524101ba45”. That is, an AMI built by Image Builder is specified.

Looking at the Elastic IP Address, “52.195.251.203” is set.

Check Route53.

Detail of Route53 1.

The domain awstut.net is associated with the Elastic IP mentioned earlier.

Operation Check

Now that you are ready, access your WordPress site.

Diagram of EC2 2.

The WordPress page is now displayed. This shows that the EC2 instance is up and running successfully using the AMI built by Image Builder.

Log in to the administration page.

Diagram of EC2 3.

Enter the user name and password specified in the Image Builder.

Diagram of EC2 4.

You have successfully logged in. If you look at the settings page, you will see that the site title, URL, and email address are set. These are also the values specified in the Image Builder.

Summary

As a specific example of using Image Builder, we created an AMI for WordPress. We launched an EC2 instance from this AMI and confirmed that the WordPress site works.