WordPressのカスタマイズやテーマファイル、プラグインの作り方などデータベース構造から詳しく解説します。

〈2015年版〉AWSでWordPress用の冗長構成を構築する(ELB,EC2,S3,CloudFront,RDS)

はじめに

AWSでWordPressの運用をするにあたって、アクセス数増加に備えた冗長構成を構築しました。
(構築した概要はこちら)
Untitled
とりあえずここまでやっておけば、あとは負荷に応じてインスタンスサイズを変更したり、サーバーを追加するだけなのでラクちんです。
構築を行ううえでハマったポイントと、参考にした記事をご紹介します。

ステップ1:EC2+RDSでWordPressをインストール

まずはじめにEC2にApache、PHPをインストールしWebサーバーを作成します。
これはAmazonの公式リファレンスを参考にすれば比較的容易に作成出来ます。
<参考>AWS チュートリアル
こちらではMySQLのインストールも解説されていますが、今回はWebサーバーとして利用するのでインストールの必要はありません。
また、RDSでDBサーバーを構築し、wp-config.phpに編集を行う事でWebサーバーとRDSを接続、WordPressのインストールを行います。
<参考>EC2+RDSでWordPressをインストールする方法
基本的にはDBのホスト名としてRDSのエンドポイントを入力すれば、問題なく設定する事が出来ます。

ステップ2:ELBで冗長化

次に、EC2のコンソール画面からLoadBarancerメニューをクリックしてロードバランサーを作成します。
ロードバランサーとEC2との接続はプライベートDNSを使用して行われますが、これらは同じセキュリティグループに所属している必要があります。
ロードバランサーの設定で気をつけなければならないことは、AZの挙動の違いと、ヘルスチェック失敗時の挙動です。
同一AZ内のEC2での分散を行う際には負荷の軽い方に自動的に割り振られ、AZをまたいだEC2での分散は均等に分散されます。
また、一度ヘルスチェックに失敗しインスタンスのステータスが〈OutOfService〉となると、ELBは該当のEC2を切り離してしまいます。
そのため、サーバーを再起動などして状態が回復したあともそのままではELBからリクエストが転送されません!
これをもとにもどすためには、一度ELBから該当インスタンスを外して、再度登録する必要があります。
<参考>Amazon Web Services クラウドデザインパターン 実装ガイド 改訂版

ステップ3:S3を仮想マウント→力技で解決

WordPressでは投稿画像などのメディアデータはディスクに保存され、該当ファイルのパスがDBへと保存されます。
そのため、Webサーバーの冗長化を行う際にはどのWebサーバーからアクセスしてもメディアファイルにアクセス出来るよう、メディアファイルを共有ストレージへと保存する必要があります
メディアファイルの保存先としてS3を活用し、s3fsというアプリケーションを用いてs3のバケットを/wp-content/uploadsへと仮想マウントします。
しかし!S3はパーミッションの管理が複雑で、s3fsの設定もパーミッションを間違えるとハマってしまいます。
<参考>Amazon Web Services クラウドデザインパターン 実装ガイド 改訂版
<参考>s3fsを使ってEC2からS3をマウントしたときにうまくいかなくて調べた事まとめ
ポイントはアクセスキーはユーザーやロール、グループとヒモづいているのでまずユーザーを作成してからアクセスキーを作成する。
そしてそのユーザーにはS3FullAccess権限を付与する。
EC2へssh接続後

ID ユーザー名

コマンドを入力して該当ユーザーのuid,gidをメモする。
マウント実行時には、

sudo /usr/local/bin/s3fs bucketname /share -o rw,allow_other,uid=222,gid=500

のようにallow_other、uid,gidオプションを必ず設定することです。
これを設定しないと、書き込みをしたのに403サーバーエラーで表示ができなかったりしてしまいます。
(僕はどうしても読み込みアクセスのパーミッション問題を解決出来ず、/wp-content/uploads以下はS3のパブリックDNSへとリダイレクトすることで対処しました….)
S3にはCNAMEでドメインを設定する事が出来るので、サブドメインをRoute53で割り当てておくと便利です。
また、既存のEC2でのLAMP環境から移行する場合には、既存のEBSをコピー、コピーしたEBSをアタッチしてcpコマンドでuploads以下を仮想マウントしているディレクトリへとコピーするか、s3cmdで差分アップロードをする事ができます。(sync –skip-existingコマンドで差分反映)
<参考>s3fsを使ってEC2からS3をマウントしたときにうまくいかなくて調べた事まとめ
※ちなみに10GB程度のファイルをEC2からS3へアップロードするのに12時間前後かかりました。

ステップ4:RDSとリードレプリカ、HyperDBプラグイン

次にRDSでDBサーバーを構成します。既存のDBが無い場合は、CREATE DATABASEで適当なデータベースを作成するだけです。
既に他のEC2で運用している場合はdumpファイルを作成して、RDSへと流し込みます。

#dumpファイルの作成
mysqldump -u ユーザー名 -p DB名 > /tmp/backup.sql 
#dumpファイルの流し込み
mysql -u ユーザー名 -p —database=DB名 —host=RDSエンドポイント </tmp/backup.sql

その後コンソール画面からCreate Read Replicaを選択してリードレプリカを作成します。
こちらには書き込みを行わないので、マスターDBよりもインスタンスサイズを小さくしてもいいかもしれません。
リードレプリカから読み込みを行うWebサーバーでは、書き込みはマスターDB、読み込みはリードレプリカのように処理を分けなければなりません。
これにはWordPressの純正プラグインであるHyperDBを使用します。
<参考>HyperDB でお手軽に WP の MySQL サーバを複数分散
WordPressインストール時のホスト(すなわちwp_optionsへと格納されるホスト)をマスターDB、読み込み用のDBとしてリードレプリカのエンドポイントを設定します。

ステップ5:CloudFrontでキャッシュ、セッション管理

ここまでくれば一応完成で、ユーザー側は問題なく動作します。
しかしwp-adminにアクセスしている時もロードバランサーを経由してアクセスする事になるので、管理画面での遷移中にもう一方のサーバーへと飛ばされ、そちらにはログインデータが無いため再度ログインしなければならない、というような手間が発生します。
通常のロードバランサーであればURLごとにサーバーを振り分けられるのですが、ELBはURLごとの振り分けに対応しておらず、代わりにCloudFrontで対応します。
CloudFrontでキャッシュサーバーを構築し、さらに/wp-admin/*は全て一方のEC2にアクセスするよう設定を行います。
このとき、リクエストタイプでPOSTも許容するクエリパラメーターを許可するcookieを許可するといった点が重要です。
また、User-AgentによるPC/SPのテーマファイル振り分けを行っている場合は注意が必要です。
CloudFrontを経由したリクエストは全てUser-AgentがCloud-Frontとなってしまうため、カスタムヘッダーとしてUser-Agentを許可するよう設定するか、CloudFrontのCloudFront-ls-Mobile-Viewerを許可し、アプリケーションを書き換えてこのヘッダーがtrueの時はSP用のテーマファイルを表示するように設定を行います。

ステップ6:CloudWatchでAutoScalingを設定

最後に、高負荷時に自動でインスタンスを追加して負荷分散を行えるよう、AutoScalingを設定します。
僕の構成したシステムでは、同時アクセスの増加によってWebサーバーのメモリが問題となるケースが多いので、Webサーバーのメモリ使用率を監視し、90%を超えると自動でインスタンスを追加するよう設定しています。
<参考>CloudWatchのカスタムメトリクスでFreeMemoryMBytes、UsedMemoryPercent、LoadAverage、Stealを取得
<参考>Amazon EC2でオートスケーリングを行う方法

さいごに


今回の構築を行う上で非常にお世話になったのがこちらの本です。ELBの導入、S3の仮想マウント、RDSのレプリケーションなどつまずきそうなポイントが全てキャプチャつきで丁寧に解説されているほか、各オプションの詳細な説明などもありAWSでインフラを構築する際に是非手元においておきたい一冊です。

関連記事

ページ上部へ戻る