Open135

久々に AWS の設定を行う

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

このスクラップについて

このスクラップでは久々に AWS で EC2 インスタンスを使って WordPress を構築する過程を記録していく。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

AWS Organizations を使うか否か

今回は使わない。

理由は色々とあるが将来的にアカウントごと移譲する可能性があるため。

リザーブドインスタンスをシェアできるなどメリットもあるが落とし穴もありそうなので新規にアカウントを作成していく。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

メールアドレスの作成

新規アカウント用にメールアドレスを作成する。

エイリアスを使うとお金がかからない。

名前には顧客やプロジェクト名を使えば良いだろう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

アカウント作成

下記 URL にアクセスする。

https://portal.aws.amazon.com/billing/signup#/start


新しい AWS アカウントを作成するボタンを押す


作成したメールアドレスと適当なアカウント名を入力する

メールで認証コードが届くので入力する、数字 6 桁で有効期限は 10 分。


成功するとルートユーザーパスワードの設定に進む

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

パスワード

パスワード生成器を使って作成する。

https://passwordsgenerator.net/

この辺りから認証情報のメモを作成していった方が良さそう。

このパスワードは好きな記号を含めても良さそう。

長さは 16 くらいで良いかなと思ったけど 22 がデフォルトなのでそのままにしておこう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

サポートプラン


無料のベーシックサポートを選択する。

いつかエンタープライズサポートプランを使ってみたい。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

アカウント作成が完了


長い道のりだった。

あとはログインすれば Web コンソールが表示される。


ここからが本番だ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

何をやるか箇条書きする

  • EC2 インスタンスを起動 → 完了
  • セキュリティ・グループの設定 → 完了
  • Elastic IP を作成 → 完了
  • SSH アクセスできるようにする → 完了
  • PHP や WordPress をインストールする → 完了
  • MariaDB をインストールして DB 作成 → 完了
  • Amazon SES メールアドレス検証 + SMTP 設定 → 完了
  • WordPress SMTP 設定 → 完了
  • EC2 メール送信の申請 → 構築後に本稼働リクエスト
  • IAM ロール設定 → 完了
  • S3 バックアップ → 完了
  • リザーブドインスタンス購入
  • CloudWatch アラーム → 完了
  • 毎朝再起動 → 完了
  • FTP 接続 → 完了
  • php.ini 設定 → 完了

PHP のバージョンなどについては下記がよくまとまっていた。

https://ja.wordpress.org/about/requirements/

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

とりあえず EC2 起動


ページ左の「インスタンス」をクリックする。


ページ上の「インスタンスを起動」ボタンをクリックする。


フォームに入力していく。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

名前などをどうするか

とりあえず「WordPress」としておこう。

OS イメージは「Amazon Linux」にしよう。

インスタンスタイプは「t3.small」にする、これは後から変更できないこともないけど大変みたいなのでよく確認する。

キーペアはサインアップ直後はないので新しいキーペアを作成する。


ED25519 の方がセキュアな感じがするのでそうしとこう。

ダウンロードしたら .ssh に入れてパーミッションを変更する。

コマンド
cp ~/Downloads/secret.pem ~/.ssh
chmod 400 ~/.ssh/secret.pem
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

セキュリティグループ

SSH, HTTP, HTTPS くらいを許可すれば良いだろうと思ったら簡単にできるようだ、すごいな。


すべてにチェックを入れる。

SSH は固定 IP を持っているのであれば指定しておきたいところ。

ちなみに既存のセキュリティグループは全てのトラフィックを受け入れるので設定しない方が良さそう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ストレージの設定


サイズを 100 GiB、終了時に削除を「いいえ」にする。

アドバンストとシンプルがあり、アドバンストにすると細かい設定が可能。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

インスタンス起動

最後に「インスタンスを起動」ボタンを押す。


ようやくインスタンスを起動できる。

その下のコマンドを確認を押すと控えの JSON データが手に入るので便利。

RunInstances
{
  "MaxCount": 1,
  "MinCount": 1,
  "ImageId": "ami-0a2e10c1b874595a1",
  "InstanceType": "t2.micro",
  "KeyName": "xxxx",
  "EbsOptimized": false,
  "BlockDeviceMappings": [
    {
      "DeviceName": "/dev/xvda",
      "Ebs": {
        "Encrypted": false,
        "DeleteOnTermination": false,
        "Iops": 3000,
        "SnapshotId": "snap-0296c4bd17a888d11",
        "VolumeSize": 100,
        "VolumeType": "gp3",
        "Throughput": 125
      }
    }
  ],
  "NetworkInterfaces": [
    {
      "AssociatePublicIpAddress": true,
      "DeviceIndex": 0,
      "Groups": [
        "<groupId of the new security group created below>"
      ]
    }
  ],
  "TagSpecifications": [
    {
      "ResourceType": "instance",
      "Tags": [
        {
          "Key": "Name",
          "Value": "WordPress"
        }
      ]
    }
  ],
  "PrivateDnsNameOptions": {
    "HostnameType": "ip-name",
    "EnableResourceNameDnsARecord": true,
    "EnableResourceNameDnsAAAARecord": false
  }
}
CreateSecurityGroup
{
  "GroupName": "launch-wizard-1",
  "Description": "launch-wizard-1 created 2023-09-15T08:39:14.400Z",
  "VpcId": "vpc-0acb0bc7e7d21ae65"
}
AuthorizeSecurityGroupIngress
{
  "GroupId": "<groupId of the security group created above>",
  "IpPermissions": [
    {
      "IpProtocol": "tcp",
      "FromPort": 22,
      "ToPort": 22,
      "IpRanges": [
        {
          "CidrIp": "0.0.0.0/0"
        }
      ]
    },
    {
      "IpProtocol": "tcp",
      "FromPort": 443,
      "ToPort": 443,
      "IpRanges": [
        {
          "CidrIp": "0.0.0.0/0"
        }
      ]
    },
    {
      "IpProtocol": "tcp",
      "FromPort": 80,
      "ToPort": 80,
      "IpRanges": [
        {
          "CidrIp": "0.0.0.0/0"
        }
      ]
    }
  ]
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Elastic IP

再起動で IP アドレスが変わると面倒なので固定しておこう。


Elatic IP 一覧ページでは右上の「Elastic IP アドレスを割り当てる」ボタンをクリックする。

今更だけどデフォルトリージョンが東京で良かった、今度する時はしっかり確認しよう。


特に設定は変える必要はない。


ページの最後の方にある「割り当て」ボタンを押す。


無事に IPv4 アドレスを取得することができた。


取得したら関連付けを忘れない。


マスクするところが多くて大変だ。

関連付けが終わると Elastic IP アドレスでインスタンスにアクセスできるようになる。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

SSH 設定

~/.ssh/config(追記例)
Host xxxx
  User ec2-user
  HostName 1.2.3.4
  Port 22
  IdentityFile ~/.ssh/secret.pem

設定したら下記コマンドで確認してみる。

コマンド
ssh xxxx

初回は下記のメッセージが表示されるので yes と入力する。

The authenticity of host '52.197.109.189 (52.197.109.189)' can't be established.
ED25519 key fingerprint is SHA256:lvs1Wt0J+QHdKJzo/PSwMTL0q2+bMTpHwdoV+PIfxQ8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

無事にログインできると素敵なアスキーアートが表示される。

ログインメッセージ
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ここまでの作業時間

今のところ順調だ。

40 分かかった、37 分と足すと 77 分、結構だな。

手順が決まってればここまで 20 分くらいで終わるだろう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

HTTP サーバー設定

スクリーンショットに疲れたのでしばらくサーバー設定をしよう。

まずは HTTP サーバーをインストールする。

コマンド
# HTTP サーバーをインストールします。
sudo yum install -y httpd
# サーバーを起動します。
sudo systemctl start httpd
# 自動起動の設定を確認します。
sudo systemctl is-enabled httpd
# 自動起動を有効にします。
sudo systemctl enable httpd
# もう一度、自動起動の設定を確認します。
sudo systemctl is-enabled httpd
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

MySQL サーバー

今は MariaDB か。

Amazon Linux 2 の情報が出てきたが amazon-linux-extras コマンドを使えない。

そんな時は下記のコマンドを使うと探すことができた。

コマンド
sudo yum list | grep mariadb

下記がインストールコマンドになる。

コマンド
sudo yum install -y mariadb105-server
sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo mysql_secure_installation

mysql_secure_installation では基本 yes で良さそう。

mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none): 
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] 
Enabled successfully!
Reloading privilege tables..
 ... Success!


You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n]  
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] 
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] 
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] 
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] 
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

設定したパスワードで mysql -u root -p でログインできれば OK です。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

PHP インストール

バージョンは 8.1 か 8.2 が選べるようだ。

悩ましいがまずは最新バージョンの 8.2 にしておこう。

コマンド
sudo yum install -y php8.2 php8.2-gd php8.2-mbstring php8.2-mysqlnd php8.2-pdo
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ユーザー名とグループ名

HTTP サーバーのユーザー名はグループ名はいずれも apache であることが /etc/httpd/conf/httpd.conf を読んでわかった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

AllowOverride

/etc/httpd/conf/httpd.conf を編集する。

Directory "/var/www/html" の AllowOverride を All にする。

コマンドは下記の通り。

コマンド
sudoedit /etc/httpd/conf/httpd.conf
# or
sudo vi /etc/httpd/conf/httpd.conf

多分これだけで OK のはず。

コマンド
sudo systemctl start httpd
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

WordPress のインストール

英語版と日本語版があるけど素直に日本語版をインストールしておこう。

https://ja.wordpress.org/download/

コマンド
# ホームディレクトリに戻ります。
cd
# zip ファイルをダウンロードします。
curl -O https://ja.wordpress.org/latest-ja.zip
# zip ファイルを展開します。
unzip latest-ja.zip
# ディレクトリを移動します。
sudo mv wordpress /var/www/html/
# パーミッションを設定します。
sudo chown -R apache:apache /var/www/html/wordpress

/var/www/ か /var/www/html/ か悩ましいけど後者にしておこう。

これで IP アドレス + /wordpress にアクセスするとアクセスできる。


この前に色々とやることがある。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

httpd 設定

/wordpress ではなく / でアクセスできるようにしたい。

そのためには /etc/httpd/conf/httpd.conf を編集する。

DocumentRoot を "/var/www/html/wordpress" にすれば良い。

設定を変更したらリロードを忘れない。

コマンド
sudo systemctl reload httpd


これで IP アドレスだけで設定画面が表示されるようになった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

データベース作成

コマンド
mysql -u root -p
# パスワードを入力する。
SQL
create database wordpress_db charset utf8mb4;
create user wordpress_user@localhost identified by 'xxxx';
grant all privileges on wordpress_db.* to wordpress_user@localhost;

xxxx の部分にはパスワードを生成して入力する。

https://passwordsgenerator.net/

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

WordPress セットアップ


今ほど作成したデータベース情報を入力していく。

ホスト名や接頭辞はそのままで良いだろう。


心の準備ができたら「インストール実行」ボタンを押す。

検索エンジンでの表示(をしない)にはとりあえずチェックを入れておこう。


無事に完了できて良かった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

まずはメールアドレスの認証

検証済み ID をクリックする。


本稼働アクセスのリクエストも必要そうだな。


ID の作成ボタンをクリックする。


ID タイプとして E メールアドレスを選択する。

検証メールが届くので URL にアクセスする。


検証に成功した場合のページ

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

本稼働アクセスのリクエスト

アカウントダッシュボードで「本稼働アクセスのリクエスト」ボタンをクリックする。


再掲


リクエストページ

メールタイプはお問い合わせフォームなどの確認メールの場合はトランザクションで良いだろう。

ウェブサイトの URL は悩ましいがとりあえず http:// + EC2 インスタンスの IP アドレスにしておこう。

ユースケースの説明は下記のようにしておこう。

Web サイトに設置したお問い合わせフォームから確認メールを送信するために Amazon SES を利用します。

連絡する際の希望言語は Japanese にしてこう。

最後に同意にチェックを入れたら「リクエストの送信」ボタンをクリックする。


リクエストの送信完了

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

SMTP 設定


SMTP 設定ページから始めていく。

「SMTP 認証情報の作成ボタン」をクリックする。


特に内容は変更せずにそのまま作成する。


認証情報は再表示できないのでしっかり控えておく。


ホスト名などはどうするのかと思ったらしっかり表示されて親切だ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

WordPress 側の SMTP 設定


ここからは WordPress での作業になる。


新規追加ボタンを押してから SMTP で検索する。


WP Mail SMTP の今すぐインストール → 有効化


ウィザードが表示された。


その他の SMTP を選ぶ。


先ほど控えた SMTP 情報を入力していく。

送信元メールアドレスの強制使用については悩ましいけど ON のままにしておいた方が良さそう。


とりあえずデフォルトのままで次へ進む。


申し訳ないがメールアドレスは消して、その代わり協力はしよう。


このページはスキップする。


テストメールが送信できなかったようだ。

メールボックスを見たら問題なくメールは来ていた。


SPF 設定などで成功判定にはらならなかったようだ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ここまで 22 分くらい

合計 185 分になった。

次は IAM ロールを作成して EC2 インスタンスに設定しよう。

そしたら wp-content と mysqldump をバックアップできるようにしよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

S3 バケット作成


「バケットを作成」ボタンを押す。


バケット名を入力して後はデフォルトのままで大丈夫。


無事にバケットが作成された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

EC2 からバケットにオブジェクトを保存

まだロールを設定していないのでできないことを確認する。

コマンド
# アップロードのテスト用ファイルを作成します。
echo hello > test.txt
# バケットへのアップロードを試みます。
aws s3 cp test.txt s3://{BUCKET_NAME}/test.txt

upload failed: ./test.txt to s3://{BUCKET_NAME}/test.txt Unable to locate credentials

無事にアップロードが失敗した。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ロール作成


インスタンス ID をクリックする。


IAM ロールを変更をクリックする。


「新しい IAM ロールを作成」をクリックする。


「ロールを作成」ボタンを押す。


タイプは「AWS のサービス」のままでユースケースで「EC2」を選ぶ。


許可を追加では AmazonS3FullAccess にチェックを入れる。


ロール名に例えば「S3FullAccessRole」と入力して作成する。


ロール変更ページに戻って更新ボタンを使うと選択できるようになる。


無事にロールが設定された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

この状態で再度アップロード

コマンド
aws s3 cp test.txt s3://{BUCKET_NAME}/test.txt

upload: ./test.txt to s3://{BUCKET_NAME}/test.txt

今度は成功した。


アップロードは S3 バケット詳細ページからも確認できる。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

バックアップスクリプトを作成する

コマンド
touch ~/s3-backup.sh
chmod 755 ~/s3-backup.sh
touch ~/.my.cnf
chmod 600 ~/.my.cnf
~/s3-backup.sh
# アップロード先のバケット名です。
BUCKET_NAME=xxxx
# バックアップ時点の日時です。
DATE=`date --iso-8601=seconds`

# WordPress ディレクトリの zip ファイルを作成します。
cd /var/www/html && zip ~/wordpress.zip -r wordpress && cd
# S3 バケットにアップロードします。
aws s3 cp ~/wordpress.zip s3://${BUCKET_NAME}/${DATE}/wordpress.zip
# ファイルを削除します。
rm -f ~/wordpress.zip

# データベースの内容をダンプします。
mysqldump -u wordpress_user wordpress_db > ~/wordpress_db.sql
# S3 バケットにアップロードします。
aws s3 cp ~/wordpress_db.sql s3://${BUCKET_NAME}/${DATE}/wordpress_db.sql
# ファイルを削除します。
rm -f ~/wordpress_db.sql
~/.my.cnf
[mysqldump]
password="xxxx"
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

CRON 設定

/etc/crontab に下記を追記する。

/etc/crontab(追記)
0 18 * * * ec2-user /home/ec2-user/s3-backup.sh

UTC 18:00 なので JST 3:00 にバックアップを実行する。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

CRON がインストールされていない

https://dev.classmethod.jp/articles/diff-al-2023-and-al-2-packages-and-services/

びっくりだ。

コマンド
# crond インストール
sudo yum install cronie
# 起動状態の確認(停止している)
sudo systemctl status crond
# crond 起動
sudo systemctl start crond
# 起動状態の確認(起動している)
sudo systemctl status crond
# システム開始時の起動(有効になっている)
sudo systemctl is-enabled crond
# 有効になっていない場合は有効にする。
sudo systemctl enable crond
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

S3 ライフサイクルポリシーの設定

バックアップファイルは作成から 2 週間で削除するようにする。


「ライフサイクルルールを作成する」ボタンを押す。


内容を入力していく。

アクションがわかりにくいが「オブジェクトの現行バージョンを有効期限切れにする」で良いようだ。


無事に設定された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

自動再起動

とりあえず cron で設定してみよう。

/etc/crontab(追記)
0 20 * * * root /usr/sbin/reboot

後日 last コマンドで調べてみよう。

コマンド
last reboot
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

SNS トピック作成


Amazon SNS ページを開く。


トピックページからの方がわかりやすいかも知れない。


「トピックの作成」ボタンを押すとこのページが表示される。

メール通知の場合はタイプに「スタンダード」を指定する。

今回は名前は「StatusCheckFailed」にして表示名は「ステータスチェック」にする。


無事に作成された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

サブスクリプション作成


「サブスクリプションの作成」ボタンを押す。


プロトコルとして E メールを選択する。

サブスクリプションを作成すると確認メールが届くので Confirm subscription をクリックして受信を許可する。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

メッセージ発行のテスト


トピック詳細ページにある「メッセージの発行」ボタンを押す。


適当な件名と本文を入力してから「メッセージの発行」ボタンを押す。

成功するとメールが届く。

これで SNS トピックとサブスクリプションは作成完了。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

CloudWatch アラーム作成


まずは CloudWatch ページへ移動する。


すべてのアラームを表示してから「アラームの作成」ボタンを押す。


メトリクスの選択画面

設定内容は下記の通り。

  • メトリクス:WordPress インスタンスの StatusCheckFailed
  • 統計:5 分間の最大値
  • しきい値の種類:静的
  • 条件:0 より大きい


通知先として先ほど作成した SNS トピックを選択する。


アラーム名は「StatusCheckFailedAlarm」などにする。

確認画面が表示されたら内容を確認してから「アラームの作成」ボタンを押す。


無事にアラームが作成された。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

再起動とバックアップの確認

昨日の設定はしっかり動いているだろうか?

コマンド
last reboot
コンソール出力
reboot   system boot  6.1.49-70.116.am Tue Sep 19 20:00   still running
reboot   system boot  6.1.49-70.116.am Fri Sep 15 09:03 - 20:00 (4+10:56)

大丈夫なようだ。


バックアップについてもしっかり保存されている。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

PHP 設定

アップロードサイズについては下記 3 点を変更する必要がある。

  • post_max_size
  • upload_max_filesize
  • memory_limit

また必須ではないが最大処理時間も確認しておいた方が良い。

  • max_input_time
  • max_execution_time

タイムゾーンは Asia/Tokyo にする。

  • date.timezone
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

設定変更

sudo vi /etc/php.ini などを実行する。

  • post_max_size = 128M
  • upload_max_filesize = 100M
  • memory_limit = 256M
  • max_input_time = 300 (秒)
  • max_execution_time = 300 (秒)
  • date.timezone = "Asia/Tokyo"

変更した下記を実行して反映する。

コマンド
sudo systemctl restart php-fpm
sudo systemctl restart httpd

php-fpm の再起動が必要なことを知らなくて小一時間ハマってしまった。

https://tanojinfrom30.com/2021/03/21/upload-max-filesize/

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

サイトヘルスが便利


メディアの新規追加ページも便利だけどサイトヘルスの方が便利


一応メディアの新規追加ページも確認しておく。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

セキュリティグループの変更

21/TCP と 60001-60010/TCP を解放する。


EC2 のセキュリティーグループ一覧ページ


「インバウンドのルールを編集」ボタンを押す。


ルールを 2 つ追加する。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

vsftpd の設定

ソースは安定のクラメソさん。

https://dev.classmethod.jp/articles/vsftpd_on_centos7/

/etc/vsftpd/vsftpd.conf(追記)
userlist_deny=NO
pasv_enable=YES
pasv_min_port=60001
pasv_max_port=60010

FTP 用のユーザーを作成する。

コマンド
sudo useradd ftp-user
sudo passwd ftp-user

FTP ホワイトリストに追加する。

/etc/vsftpd/user_list(書き換え)
ftp-user

サーバーを起動する。

コマンド
sudo systemctl start vsftpd
sudo systemctl enable vsftpd

FileZilla などを使ってアクセスできれば OK.

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

パーミッションをどうしよう

今のままだと /var/www/html/wordpress にダウンロードはできるけどアップロードはできない。

ftp-user を apache グループに参加させ、g+w をすれば良いかな?

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

グループ参加

コマンド
# ftp-user を apache グループに追加します。
sudo gpasswd -a ftp-user apache
# ftp-user が apache グループに追加されたかを確認します。
groups ftp-user
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

パーミッション設定

コマンド
sudo chmod -R g+w /var/www/html/wordpress

とりあえず、これで読み書きはできるようになった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ロードバランサーの作成


ALB の「作成」ボタンを押す。

名前は変更できないのでよく考えた方が良さそう。

WordPressALB にしようかな。

ネットワークマッピングでは全てのアベイラビリティゾーンにチェックを入れておく。

リスナーとルーティングでは HTTP と HTTPS を設定する。

ターゲットグループはないので作成する必要がありそうだ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ターゲットグループの作成


色々と設定があるな。

ターゲットグループ名は WordPressALB80 にしようかな。

それ以外はそのままにして作成しよう。

プロトコルごとに必要そうなので WordPressALB443 も作成しよう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ACM リクエスト

セキュリティポリシーの関係で ACM 証明書をまず作成する必要がありそうだ。


証明書をリクエストボタンを押す。

証明書タイプはパブリック証明書。

ドメイン名は完全修飾ドメイン名(FQDN)、例えば www.loremipsum.co.jp。

それ以外はデフォルトのままで OK。

作成後に詳細ページから DNS 設定内容を取得できるので DNS 設定担当者に渡す。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ACM 設定完了まで待つ

証明書が無いとロードバランサーは作成できないようだ。

仕方がないので設定してもらうまで待とう。

確認はこんな感じでできそうだ。

コマンド
nslookup -type=CNAME www.loremipsum.co.jp
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

phpMyAdmin をインストールしてみる

コマンド
# 依存関係をインストールします。
sudo dnf install php-mbstring php-xml -y
# Web サーバーを起動して反映します。
sudo systemctl restart httpd
sudo systemctl restart php-fpm

ここまでは手順通りだが既にパッケージはインストールされていたので必要なかった。

下記は少し手順を変えた。

コマンド
# ホームディレクトリに移動します。
cd
# phpMyAdmin をダウンロードします。
wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz
# tar ファイルを展開します。
tar -xzf phpMyAdmin-latest-all-languages.tar.gz
# tar ファイルを削除します。
rm -f phpMyAdmin-latest-all-languages.tar.gz
# ディレクトリ名をランダムに決めます。
DIRNAME=`openssl rand -hex 16`
# ファイルを移動します。
sudo mv phpMyAdmin-5.2.1-all-languages /var/www/html/wordpress/${DIRNAME}
# 所有者を変更します。
sudo chown apache:apache -R /var/www/html/wordpress/${DIRNAME}
# ディレクトリ名を確認します。
echo ${DIRNAME}


入れるだけで表示されてしまった、すごいな。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

phpMyAdmin に Basic 認証

気休めかも知れないが下記などを参考にして Basic 認証を設定しておこう。

https://global-hack.com/blog/archives/108

コマンド
# phpMyAdmin のディレクトリに移動します。
cd /var/www/html/wordpress/${DIRNAME}
# .htaccess ファイルを作成して下記の内容を入力します。
sudo touch .htaccess
# .htpasswd ファイルを作成します。
sudo htpasswd -c .htpasswd pma_user
.htaccess
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /var/www/html/wordpress/(DIRNAME をコピーします)/.htpasswd
Require valid-user


ログイン画面が表示されるようになった。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

11/9 (木) はここから

ようやく証明書が作成されて作業を再開できるようになったので一気に終わりまで進めていこう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

メールや証明書の検証

ドメインやメールを自分で管理していない場合はクライアントにメールのリンククリックや DNS 設定を行なってもらう必要があり、作業自体は 1 分くらいで終わるはずなのだがとても時間がかかる。

今回も 1 週間以上を要したようだ。

今度計画する時はこれらを踏まえて制作計画を立てる方が良いかもしれない。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

ロードバランサが作成された

ただ名前がそのまま DNS 名に含まれるので、大文字が入っていると何かと不都合なので小文字にして作り直そう。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

エラーメッセージの確認


ターゲットグループの詳細ページ

Health checks failed with these codes: [301]

301 は Moved Permanently、リダイレクトを示す。

SSH でログインしたら原因がわかった。

コマンド
curl -v http://localhost
実行結果
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/8.2.1
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Date: Thu, 09 Nov 2023 02:34:28 GMT
< Server: Apache/2.4.56 (Amazon Linux)
< Expires: Thu, 09 Nov 2023 03:34:28 GMT
< Cache-Control: max-age=3600
< X-Redirect-By: WordPress
< Set-Cookie: _mw-wp-form-token=57fba3fc142a426c13c79ac4dafac23ab5215185afab2c00c0c9bd4fe35ade24; path=/; HttpOnly
< Location: http://52.197.109.189/
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< 

おそらく WordPress は HTTP リクエストのホスト部を見て設定されたホスト名と異なる場合はリダイレクトするようなしくみになっているのだろう。

だからステータスチェックの設定を変えて 301 を OK とするようにすれば大丈夫そうだ。


ステータスチェックの設定ページ、200 の部分を 301 に変更する。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Healthy に変わった


ターゲットグループの詳細ページ

しかしまだアクセスできない、セキュリティグループだろうか?

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

当たりだった

セキュリティグループで HTTP と HTTPS を許可する必要がある。


セキュリティーグループの詳細ページ

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

WordPress の転送について

ちなみに WordPress の方でサイトアドレスを http://12.34.56.78 のようにしていると ALB の DNS 名にアクセスしても設定されたサイトアドレスに転送されるので注意。

サイトアドレスには本番の DNS 名を設定する必要がある。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

動作確認

DNS で CNAME を設定する前にローカルで hosts ファイルを編集して確認してみる。

Mac の場合は /private/etc/hosts を編集すれば良いようだ。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

問題に対処できた

wp-config.php の冒頭に下記のコードを追加したら解決した。

wp-config.php(追加分)
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
        $_ENV['HTTPS'] = 'on';
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

トラブル発生

メモリ不足で MariaDB のプロセスが Out-of-memory (OOM) Killer にキルされる。

この現象を調べるのに 2 時間くらいかかってしまった。

対策として下記を実行しよう。

  • スワップを設ける。
  • MariaDB のメモリ消費量を抑制する。
  • できれば MariaDB のプロセスを OOM Killer のキル対象から外す。
  • プロセス監視を設定する。
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

スワップの作成

Amazon Linux ではスワップ領域が無い、この点は下記のコマンドを実行すると確認できる。

コマンド
free

スワップを作成するには下記のコマンドを実行する。

コマンド
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
/etc/fstab(末尾に追記)
/swapfile swap swap defaults 0 0

スワップが作成されたことは sudo swapon -s または free で確認できる。

完全な動作確認にはリブートした方が良い。

この辺りを参考にした。

https://repost.aws/ja/knowledge-center/ec2-memory-swap-file

https://qiita.com/nakamto/items/5e78e9caceeff6b9e2b4

https://engineer-blog.ajike.co.jp/ec2-swap/

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

MariaDB のメモリ使用量

こちらの記事が一番わかりやすい感じがする。

https://qiita.com/kyrieleison/items/9f303dd046e2fb82fea3

SQL
select
  @@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length as global_buffer_size,
  @@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size as thread_buffer_size,
  @@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length
  + (@@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size) * @@global.max_connections as total_memory_size;
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

PHP FPM プロセス数調整

最終的に PHP FPM のプロセス数を調整してみた。

/etc/php-fpm.d/www.conf
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI. The below defaults are based on a server without much resources. Don't
; forget to tweak pm.* to fit your needs.
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
pm.max_children = 8

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 2

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 2

; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 6
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

書き換え

コマンド
sudo systemctl edit mariadb.service
/etc/systemd/system/mariadb.service.d/override.conf
[Service]
OOMScoreAdjust=-1000

設定内容を末尾に書くと書き込みが失敗するので注意。

反映させるには下記を実行。

コマンド
systemctl restart mariadb.service

プロセス ID を調べたらさらに下記を実行。

cat /proc/1234/oom_score
cat /proc/1234/oom_adj
cat /proc/1234/oom_score_adj

ちなみに下記を実行すると oom_score_adj がゼロではないプロセスを一覧できる。

for dir in /proc/[0-9]*; do   
  if [ "`cat $dir/oom_score_adj`" != 0 ]; then   
    echo "`cat $dir/comm` : `cat $dir/oom_score_adj`"   
  fi   
done 
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

CloudWatch Agent のインストール

高速セットアップを使ってみた。


CloudWatch エージェントのインストールにのみチェックを入れた。

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

パラメータ作成

パラメータストアで下記を作成。

名前は CloudWatch-Alarm-Process-Check とした。

{
    "metrics": {
        "metrics_collected": {
            "procstat": [
                {
                    "pattern": "httpd",
                    "measurement": [
                        "pid_count"
                    ],
                    "metrics_collection_interval": 60
                },
                {
                    "pattern": "mariadbd",
                    "measurement": [
                        "pid_count"
                    ],
                    "metrics_collection_interval": 60
                }
            ]
        }
    }
}
薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

Run Command

  • コマンドドキュメント: AmazonCloudWatch-ManageAgent
  • Action: Configure (append)
  • Optional Configuration Location: CloudWatch-Alarm-Process-Check

ターゲットで EC2 を選ぶ。

EC2 が表示されない場合は再起動してみる。

設定ファイルは下記に格納されるようだ。

/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ssm_CloudWatch-Alarm-Process-Check

薄田達哉 / tatsuyasusukida薄田達哉 / tatsuyasusukida

アラーム作成

ImageId, InstanceId, InstanceType, pattern, pid_finder のメトリクスを使って 1 分間の平均値が 0 になったらインスタンスを再起動するアラームを作成する。