皆様こんにちは。
今回はCLIを利用して高可用性アーキテクトの構築をしていきます。
この記事ではCLIよりEC2の作成を行います。
このブログはCLIによるEC2の作成をする上での知識を記事としてまとめ再確認し、皆様と共有するため作成します。

1.高可用性アーキテクト構築目次

目次はこちら

2.EC2とは

Amazon Elastic Compute Cloud (Amazon EC2) は、Amazon Web Service (AWS) クラウドでスケーラブルなコンピューティングキャパシティーを提供します。Amazon EC2 の使用により、ハードウェアに事前投資する必要がなくなり、アプリケーションをより速く開発およびデプロイできます。
引用:Amazon EC2 とは

今回は高可用性アーキテクトを構築していくうえで必要なサーバとしてEC2をマルチAZ配置で利用します。
類似サービスとして「Amazon Lightsail」のインスタンスなどがあげられます。

3.フロー図

file

マルチAZ配置で冗長化し、以下のフローで可用性を高めます。

  1. 障害が発生し、片方のインスタンスが利用不可になります。
  2. ALBを利用し処理をもう一つのインスタンスに肩代わりします。

4.EC2作成

EC2を作成する前に構築時に使用するSSHキーペアとユーザーデータ、EBSの設定ファイルを自前に設定します。

4-1.SSHキーペア作成

Amazon EC2 インスタンスへの接続時の身分証明に使用するSSHキーペアを作成します。

4-1-1.SSHキーペアとは

キーペアには、プライベートキーと公開キーを含んでおり、 Amazon EC2 インスタンスへの接続時の身分証明に使用する、セキュリティ認証情報のセットを構成しています。パブリックキーは、Amazon EC2 によりお客様のインスタンス内に保管されます。またプライベートキーは、お客様自身が保管します。Linux インスタンスの場合、プライベートキーにより、インスタンスへの安全な SSH 接続を可能にしています。
引用:Amazon EC2 のキーペアと Linux インスタンス

4-1-2キーペア作成

まずSSHキーペアを作成するために、[aws ec2 create-key-pair]コマンドを使用します。

使用するオプション 設定値 説明
--key-name umemoto_kadai_1 キーネームを入力
--query ‘KeyMaterial’ キーの内容を抽出
--output text \ out-file -encoding ascii -filepath C:\key\umemoto_kadai_1.pem 指定のパスにキーを作成

入力

aws ec2 create-key-pair `
    --key-name umemoto_kadai_1 `
    --query 'KeyMaterial' `
    --output text | out-file -encoding ascii -filepath C:\key\umemoto_kadai_1.pem

出力なし

指定のパスに作成できていたら問題ないです。

4-2.ユーザーデータ作成

ユーザーデータを利用し、あらかじめ設定したコマンドを起動時に自動的に実行させます。

4-2-1.ユーザーデータとは

WordPressサーバー構築に使用するコマンドをまとめたユーザーデータを以下のように作成します。
WordPressは高可用性アーキテクトの検証のため導入します。
ユーザーデータを利用することにより、あらかじめ設定したコマンドを起動時に自動的に実行させることができます。(ユーザーデータについての概要はこちらを参照ください。)

4-2-2.ユーザーデータ設定

ファイル名:user-data.txt
#!/bin/bash
sudo yum install httpd -y
sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2
sudo yum install -y amazon-efs-utils
sudo mount -t efs -o tls fs-xxxxx:/ /var/www/html/
echo 'fs-xxxxx:/ /var/www/html efs tls,_netdev 0 0' | sudo tee -a /etc/fstab
cd /tmp/
sudo wget https://wordpress.org/latest.zip
unzip latest.zip
sudo mv wordpress/* /var/www/html/
sudo rm -rf wordpress/ latest.zip
sudo chown -R apache /var/www
sudo chgrp -R apache /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;
sudo systemctl enable httpd.service
sudo systemctl start httpd.service
wget https://s3.ap-northeast-3.amazonaws.com/amazoncloudwatch-agent-ap-northeast-3/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
sudo rpm -U ./amazon-cloudwatch-agent.rpm
  • 2行目#! /bin/bashは、
    「#!」で始まるジバンと呼ばれる文字列は、このシェルスクリプトはbashを利用して解釈/実行されるという宣言をしています。

  • 3行目sudo yum install httpd -yは、
    appache httpdのインストールコマンドです。

    • -yは全ての問い合わせに「yes」で応答するオプションです。
  • 4行目sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2は、
    Amazon Linux 2のExtras Libraryとよばれるパッケージ群(トピックといいます)からLamp環境に必要なものをまとめてインストールしています。

  • 5行目 sudo yum install -y amazon-efs-utilsは、
    EFSマウントヘルパーのインストールです。

    • -yは全ての問い合わせに「yes」で応答するオプションです。
  • 6行目sudo mount -t efs -o tls fs-xxxxx:/ /var/www/html/は、
    EFSのマウントコマンドです。fs-xxxxxは自分のefsIDを設定します。

    • -o tlsはtlsを利用して暗号化するコマンドです。
  • 7行目echo 'fs-xxxxx:/ /var/www/html efs tls,_netdev 0 0' | sudo tee -a /etc/fstabについて、
    インスタンスの再起動時に、EFSを自動マウントするためのコマンドです。なので、fs-xxxxxを自分のefsIDに書き換える必要があります。

    • 「/etc/fstab」ファイルは、マウントするファイルシステムの情報を記述するファイルです。なので、fs-xxxxx:/ /var/www/html efs tls,_netdev 0 0を書き込む事で起動時に自動マウント設定を行えます。
    • sudo echo で直接書き込もうとするとリダイレクト処理が挟まって一般ユーザー権限になり、Permission deniedエラーが発生します。
  • 9,10行目sudo wget https://wordpress.org/latest.zip,unzip latest.zipについて、
    Wordpressをダウンロードし、解凍しています。

  • 11行目sudo mv wordpress/ * /var/www/html/について、
    apacheの公開領域(/var/www/html/)にwordpressファイルを移動させています。

  • 12行目sudo rm -rf wordpress/ latest.zipについて、
    解凍する前のものを削除しています。

  • 13~17行目は権限回りの付与です。
    こちらを設定しないとWordpressインストールプロセス中にconfig.phpファイルを自動で作成することができません。

  • 18行目sudo systemctl enable httpd.serviceについて、
    apacheの自動起動を有効にするコマンドです。

  • 19行目sudo systemctl start httpd.serviceについて、
    apacheの起動コマンドです。

  • 20,21行目wget https:/ /s3.ap-southeast-1.amazonaws.com/amazoncloudwatch-agent-ap-southeast-1/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm sudo rpm -U ./amazon-cloudwatch-agent.rpm
    CloudWatchAgentをダウンロードし、解凍しています。

4-3.EBS設定

今度はEBSの設定ファイルをJSON形式で作成していきます。

4-3-1.EBSとは

Amazon Elastic Block Store (Amazon EBS) は、EC2 インスタンスで使用するためのブロックレベルのストレージボリュームを提供します。EBS ボリュームの動作は、未初期化のブロックデバイスに似ています。これらのボリュームは、デバイスとしてインスタンスにマウントできます。
引用:Amazon Elastic Block Store (Amazon EBS)

4-3-2.EBS設定ファイル

ファイル名:device-setting.json
[
  {
    "DeviceName": "/dev/xvda",
    "Ebs": {
      "DeleteOnTermination": true,
      "VolumeType": "gp3",
      "VolumeSize": 8,
      "Encrypted": true,
      "KmsKeyId": "xxxxx-xxxx-xxxx-xxxx-xxxxx"
    }
  }
]
項目 設定値 説明
DeviceName /dev/xvda ルートデバイス名の入力
DeleteOnTermination true EC2終了時に削除
VolumeType gp3 ボリュームタイプ
VolumeSize 8 ボリュームサイズ(GiB)
Encrypted true 暗号化の有効化
KmsKeyId xxxxx-xxxx-xxxx-xxxx-xxxxx 作成したKMSのid

4-4.EC2インスタンスの作成

ここまで出来たら、いよいよEC2の作成をします。
作成をするために、[aws ec2 run-instances]コマンドを使用します。

使用するオプション 設定値 説明
--image-id ami-0cbec04a61be382d9 使用するAMIのIDを入力
--block-device-mappings file://C:\ec2\device-setting.json 先ほど作成したEBS設定ファイルを指定
--count 1 使用するEI アクセラレータ数を指定
--instance-type t2.micro 使用するインスタンスタイプを指定
--key-name umemoto_kadai_1 先ほど作成したキーネームを入力
--security-group-ids sg-xxxxx 前回作成したEC2用のSGのIDを入力
--subnet-id subnet-xxxxx,subnet-xxxxx 使用する二つのパブリックサブネットを入力
--private-ip-address 10.0.1.10,10.0.2.20 前回の構成図に設定したIPを入力
--iam-instance-profile Name=umemoto-wordpress-profile 前回作成したインスタンスプロファイルの名前を入力
--capacity-reservation-specification CapacityReservationPreference=none キャパシティの予約をオフに
--user-data file://C:\ec2\user-data.txt 先ほど作成したユーザーデータのパスを入力
--tag-specifications "ResourceType=instance, Tags=
[{Key=Name,Value=umemoto-wordpress-1}]"
"ResourceType=volume, Tags=
[{Key=Name,Value=umemoto-wordpress-1}]",
"ResourceType=instance, Tags=
[{Key=Name,Value=umemoto-wordpress-2}]"
"ResourceType=volume, Tags=
[{Key=Name,Value=umemoto-wordpress-2}]"
タグを設定

入力(構成図でcidr 10.0.1.10のインスタンスの場合)

aws ec2 run-instances `
    --image-id ami-0cbec04a61be382d9 `
    --block-device-mappings file://C:\ec2\device-setting.json `
    --count 1 --instance-type t2.micro `
    --key-name umemoto_kadai_1 `
    --security-group-ids sg-xxxxx `
    --subnet-id subnet-xxxxx `
    --private-ip-address 10.0.1.10 `
    --iam-instance-profile Name=umemoto-wordpress-profile `
    --capacity-reservation-specification CapacityReservationPreference=none `
    --user-data file://C:\ec2\user-data.txt `
    --tag-specifications "ResourceType=instance, Tags=[{Key=Name,Value=umemoto-wordpress-1}]" 
    "ResourceType=volume, Tags=[{Key=Name,Value=umemoto-wordpress-1}]"

出力

{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-0cbec04a61be382d9",
            "InstanceId": "i-xxxxx",
            "InstanceType": "t2.micro",
            "KeyName": "umemoto_kadai_1",
            "LaunchTime": "2022-05-10T06:12:07+00:00",
            "Monitoring": {
                "State": "disabled"
            },
            "Placement": {
                "AvailabilityZone": "ap-northeast-2a",
                "GroupName": "",
                "Tenancy": "default"
            },
            "PrivateDnsName": "ip-10-0-1-10.ap-northeast-2.compute.internal",
            "PrivateIpAddress": "10.0.1.10",
            "ProductCodes": [],
            "PublicDnsName": "",
            "State": {
                "Code": 0,
                "Name": "pending"
            },
            "StateTransitionReason": "",
            "SubnetId": "subnet-xxxxx",
            "VpcId": "vpc-xxxxx",
            "Architecture": "x86_64",
            "BlockDeviceMappings": [],
            "ClientToken": "xxxxx-xxxx-xxxx-xxxx-xxxxx",
            "EbsOptimized": false,
            "EnaSupport": true,
            "Hypervisor": "xen",
            "IamInstanceProfile": {
                "Arn": "arn:aws:iam::xxxxx:instance-profile/umemoto-wordpress-profile",
                "Id": "xxxxx"
            },
            "NetworkInterfaces": [
                {
                    "Attachment": {
                        "AttachTime": "2022-05-10T06:12:07+00:00",
                        "AttachmentId": "eni-attach-xxxxx",
                        "DeleteOnTermination": true,
                        "DeviceIndex": 0,
                        "Status": "attaching",
                        "NetworkCardIndex": 0
                    },
                    "Description": "",
                    "Groups": [
                        {
                            "GroupName": "umemoto_SG_EC2",
                            "GroupId": "sg-xxxxx"
                        }
                    ],
                    "Ipv6Addresses": [],
                    "MacAddress": "02:43:c9:fd:01:ae",
                    "NetworkInterfaceId": "eni-xxxxx",
                    "OwnerId": "xxxxx",
                    "PrivateDnsName": "ip-10-0-1-10.ap-northeast-2.compute.internal",
                    "PrivateIpAddress": "10.0.1.10",
                    "PrivateIpAddresses": [
                        {
                            "Primary": true,
                            "PrivateDnsName": "ip-10-0-1-10.ap-northeast-2.compute.internal",
                            "PrivateIpAddress": "10.0.1.10"
                        }
                    ],
                    "SourceDestCheck": true,
                    "Status": "in-use",
                    "SubnetId": "subnet-xxxxx",
                    "VpcId": "vpc-xxxxx",
                    "InterfaceType": "interface"
                }
            ],
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "SecurityGroups": [
                {
                    "GroupName": "umemoto_SG_EC2",
                    "GroupId": "sg-xxxxx"
                }
            ],
            "SourceDestCheck": true,
            "StateReason": {
                "Code": "pending",
                "Message": "pending"
            },
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "umemoto-wordpress-1"
                }
            ],
            "VirtualizationType": "hvm",
            "CpuOptions": {
                "CoreCount": 1,
                "ThreadsPerCore": 1
            },
            "CapacityReservationSpecification": {
                "CapacityReservationPreference": "none"
            },
            "MetadataOptions": {
                "State": "pending",
                "HttpTokens": "optional",
                "HttpPutResponseHopLimit": 1,
                "HttpEndpoint": "enabled",
                "HttpProtocolIpv6": "disabled",
                "InstanceMetadataTags": "disabled"
            },
            "EnclaveOptions": {
                "Enabled": false
            },
            "PrivateDnsNameOptions": {
                "HostnameType": "ip-name",
                "EnableResourceNameDnsARecord": false,
                "EnableResourceNameDnsAAAARecord": false
            },
            "MaintenanceOptions": {
                "AutoRecovery": "default"
            }
        }
    ],
    "OwnerId": "xxxxx",
    "ReservationId": "r-xxxxx"
}

二つ目のインスタンスも上記と同様の手順で作成します。

これでEC2の作成の説明を終わります。

5.検証

5-1.EC2検証

EC2の作成ができましたら実際にSSHで接続しhttpdが起動できているかと、Wordpressがダウンロードできているかの確認を行います。

①SSHで接続出来たら以下のコマンドでhttpdの起動を確認します。

systemctl status httpd.service

出力

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/httpd.service.d
           mqphp-fpm.conf
   Active: active (running) since Mon 2022-05-23 09:11:02 UTC; 7min ago
     Docs: man:httpd.service(8)
 Main PID: 3253 (httpd)
   Status: "Total requests: 24; Idle/Busy workers 55/44;Requests/sec: 0.0547; Bytes served/sec:  31 B/sec"
   CGroup: /system.slice/httpd.service
           tq3253 /usr/sbin/httpd -DFOREGROUND
           tq3270 /usr/sbin/httpd -DFOREGROUND
           tq3271 /usr/sbin/httpd -DFOREGROUND
           tq3272 /usr/sbin/httpd -DFOREGROUND
           tq3273 /usr/sbin/httpd -DFOREGROUND
           tq3274 /usr/sbin/httpd -DFOREGROUND
           tq3346 /usr/sbin/httpd -DFOREGROUND
           tq3355 /usr/sbin/httpd -DFOREGROUND
           tq3403 /usr/sbin/httpd -DFOREGROUND
           mq3413 /usr/sbin/httpd -DFOREGROUND

May 23 09:11:02 ip-10-0-1-10.ap-northeast-2.compute.internal systemd[1]: Starting The Apache HTTP Server...
May 23 09:11:02 ip-10-0-1-10.ap-northeast-2.compute.internal systemd[1]: Started The Apache HTTP Server.

起動を確認できました。

②次に以下のコマンドを使用してwordpressのダウンロードを確認します。

cd /var/www/html
ls -m

出力

index.php, license.txt, readme.html, wp-activate.php, wp-admin, wp-blog-header.php, wp-comments-post.php, wp-config.php, wp-config-sample.php, wp-content,
wp-cron.php, wp-includes, wp-links-opml.php, wp-load.php, wp-login.php, wp-mail.php, wp-settings.php, wp-signup.php, wp-trackback.php, xmlrpc.php

必要なものがダウンロードされていることを確認できました。

5-2.EFS検証

作成したEFSが機能してるかの検証をしていきます。
プライベートIP10.0.1.10のインスタンスでテストファイルを作成して、プライベートIP10.0.2.20のインスタンで確認できるかのテストをします。

①まず両方のインスタンスがEFSにマウントしたディレクトリに移動したいため、以下のコマンドを利用します。

cd /var/www/html

②プライベートIP10.0.1.10のインスタンスでテストファイルを以下のコマンドで作成します。

sudo touch test.txt

③最後にプライベートIP10.0.2.20のインスタンスで以下のコマンドを利用してファイルを確認します。

ls test.txt

file
確認できました。

5-3.RDS検証

作成したEC2が前回作成したRDSに接続できるかのテストをしましょう。

①SSHでEC2に接続したら以下のコマンドでRDSに接続します。

mysql -h エンドポイント -P 3306 -u ユーザー名 -p データベース名

出力

Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 30
Server version: 8.0.20 Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [umemotords]>

これでRDSに接続できました。

6.感想

EC2の作成コマンドはオプションが多く大変でしたがオプション含め一つのコマンドでEC2を作成できるのは楽しいと感じました。

7.参照

AWS CLI Command Reference
https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html#cli-aws-ec2

Last modified: 2022-05-27

Author