#概要
現在、EC2シングルインスタンスでWordPresをホストしていると仮定します。
これを可用性が高く、かつ運用フリーな構成に移行する方法を学びます。
WorPressはDBサーバ(MySQL)が必須ですので、ここで学ぶことはいわゆる一般的なLAMP(あるいは類似の)構成のWeb系アプリサーバに応用することができます。
##前提条件
- 本手順は、AMIMOTO AMI(Apache)の環境が前提となっていますので、他の環境では期待通りの動作をしない可能性があります
AMIMOTO AMIでWordPressを立ち上げる - レコードを変更可能なドメインをもっている方が望ましいですが、もっていない場合の手順も記載しています
- 本手順は、AWS Consoleの英語画面で説明しています。なぜなら、手順中のリンク先にAWS公式日本語ドキュメントが含まれていますが、英語画面で説明が記述されているためです。また、ネット上のナレッジなども英語画面で説明されていることが多く、AWS上級者に質問する際も日本語画面の用語では通じないことが多いです。AWS Consoleはデフォルトで日本語画面になりますので、画面左下の言語選択を[English]に変更して下さい
#シングルインスタンス構成の課題
現在はEC2シングルインスタンスであるため、下記のような課題を抱えています。
[課題1] バックアップの運用が大変(定期実行・実行確認・リストアの訓練など)
[課題2] サーバ障害が発生した場合、復旧までに時間がかかるし、夜間でも対応が必要な場合がある
[課題3] メンテナンス(OSのセキュリティパッチ適用など)時にサービス停止が発生する
[課題4] メンテナンスが原因で不具合が発生した場合に、ロールバックが容易ではない
[課題5] 性能不足となった場合、スケールアップだけでは限界がある
これらの課題をAWSのサービスを活用して解決してしまいましょう!
#課題に対するソリューション
##AWSアーキテクチャ図
##各課題に対するソリューション
[課題1] バックアップの運用が大変(定期実行・実行確認・リストアの訓練など)
・EC2内のMySQLをRDSに切り出すことで、DBのバックアップをRDSにオフロードできる
-RDSのバックアップ(過去7日分)+トランザクションログ(直近5分前まで)はRDSが自動的にS3に保存
-RDSのリストアはマウスオペレーションで日時指定するだけと非常に簡単
・メディアファイル(画像等)をS3に保存することでバックアップ不要となる(S3上のデータは3箇所に複製され、さらにバージョニングも可能なため)
・EC2のバックアップはメンテナンス時(コード変更・パッチ適用)のみでOK
[課題2] サーバ障害が発生した場合、復旧までに時間がかかるし、夜間でも対応が必要な場合がある
・ELB(ロードバランサー)で冗長化しているため、片方のインスタンスに障害が発生してもサービスを継続
-夜間に障害が発生しても対応は翌日でOK
・RDSをMulti AZ構成にしている場合は、RDSに障害が発生すると自動的にスレーブにフェイルオーバー
[課題3] メンテナンス(OSのセキュリティパッチ適用など)時にサービス停止が発生する
・EC2インスタンスを1台ずつELBから切り離してメンテナンスを行うことでサービス無停止を実現
[課題4] メンテナンスが原因で不具合が発生した場合に、ロールバックが容易ではない
・メンテナンス前にEC2のAMIを取得することで容易にロールバックが可能
-ロールバックした場合でもWordPressの記事データはRDSに、メディアファイルはS3に格納されているため先祖返りは起こらない
[課題5] 性能不足となった場合、スケールアップだけでは限界がある
・スケールアウト(EC2インスタンスを増やす)でリニアに処理能力を増強可能。ピークが過ぎたら元の構成に戻すことも簡単
-オートスケールも利用可能
・RDSはスケールアップで対応する
##料金
###各サービスの料金
https://aws.amazon.com/jp/pricing-list/
###無料利用枠
https://aws.amazon.com/jp/free/
###AWS Simple Monthly Calculator
各サービスを組み合わせた時の月額料金を試算できます
https://calculator.s3.amazonaws.com/index.html?lng=ja_JP#
#移行手順
※ コマンド等に含まれる「xxxxxx」は各ユーザー固有の値ですので、書き換えて入力して下さい
※ ハンズオン中にRDSのフェールオーバーテストは行わないため、今回はMulti-AZではなくシングル構成としますが、あとでMulti-AZに変更することもできます(ただし料金は2倍)
##[0]WordPressを立ち上げる
次のコンテンツを参考にしてAWS上にWordPressサーバを立ち上げてください。
AMIMOTO AMIでWordPressを立ち上げる
立ち上げが完了したら、記事を投稿してください。写真入りの記事が望ましいです。スマホからも投稿できます。
##[1]MySQLをRDSに切り出す
###[1-1]現行のMySQLの設定を調べる
- WordPressインスタンスにSSH接続する
※i-xxxxxxxx
は、AMIMOTO AMIインストール時に指定したインスタンスID。i-
まで入力してTabキーで補完してもよい
$ cd /var/www/vhosts/i-xxxxxxxx
$ cat local-config.php
緑線の囲みの部分がEC2内のMySQLへのアクセス情報。後で使うので控えておく
###[1-2]Security Groupの設定を行う
####Security Groupを作成する
- AWS ConsoleでEC2を開く
- 左ペインの[Instances]をクリックして、立ち上げ済みのWordPressインスタンスが存在することを確かめる
(存在しなければリージョンが間違っている可能性がある) - 左ペインの[Security Groups]をクリックする
- [Create Security Group]をクリックする
- Security group nameとDescriptionに[My-default-sg]を入力する
- [Create]をクリックする
- [Edit Inbound rules]をクリックする
- [Add Rule]をクリックする
- Type = [All traffic]を選択する
- Souceに[my]と入力すると[My-default-sg]が表示されるので選択する
- [Save rules]をクリックする
=本設定の意味=
今回作成した「My-default-sg」がアタッチされている各種インスタンス(EC2、ELB、RDSなど)どうしは、無制限に通信が可能となります。
外部からの通信は別のSecurity groupで制御することでファイアウォールのルールがシンプルに記述できます。
####WordPressインスタンスに作成したセキュリティグループを当てる
- 左ペインの[Instances]をクリックする
- WordPressインスタンスを選択し右クリックする
- [Networking] -> [Change Security Groups]の順に選択する
- [My-default-sg]にチェックを入れて[Asign Security Groups]をクリックする
###[1-3]RDSを立ち上げる
- AWS ConsoleでRDSを開く
- 左ペインの[Databases]をクリックする
- [Create database]をクリックする
- [Standard Create]が選択されていることを確認する
- [MySQL]を選択し[Select]をクリックする
- [Free tier]をクリックする
- 下表の通り入力する
項目名 | 選択/入力内容 |
---|---|
DB Instance Identifier | (任意のインスタンス名) |
Master Username | (先ほど調べたMySQLの'username') |
Master/Confirm Password | (先ほど調べたMySQLの'password'を2回入力) |
Initial database name | (先ほど調べたMySQLの'database') |
- [create database]をクリックする
- 作成したインスタンスが[Avallable]に変わった(数分かかる)ことを確認して、インスタンスを選択して[Modify]をクリックする
- Network & Securityセクションで下図の通り[Security group]の検索窓に[my]と入力し、[My-default-sg]を選択する
- 画面最下部の[Continue]をクリックする
- [My-default-sg]が追加されていることを確認し[Modfy DB Instance]をクリックする
- インスタンス名をクリックする
- あとで使うのでEndpointを控えておく
###[1-4]EC2内のMySQLをRDSに移行する
今回は移行元(EC2)からWP-CLIでdumpを書き出し、移行先(RDS)にはMySQL Clientでdumpを書き込みます。
- WordPressインスタンスにSSH接続する
- WP-CLIでMySQLのdumpを書き出す
$ cd /var/www/vhosts/i-xxxxxxxx
$ wp db export
-
i_xxxxxxxx.sql
が作成されていることを確認する
$ ll
- MySQLの設定中の**
'host'
**の値をRDSのエンドポイントに書き換える(:3306は不要)
$ sudo cp local-config.php local-config.php.org
$ sudo vim local-config.php
'database' => 'i_xxxxxxxx',
'username' => 'wp_db46xxxxxxxxx',
'password' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
//'host' => 'localhost',
'host' => 'wp-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com',
-
この時点でブログページにアクセスすると、RDSにデータを移行していないため、インストール画面が表示されてしまう(害はないので、アクセスして確かめよう)。表示される画面は下図と異なる場合がある
※ 設定が間違っていると下図のようなエラーが表示される
-
MySQL ClientでdumpをRDSに書き込む(エンドポイントの:3306は不要)
$ mysql -h {RDS_endpoint} -P 3306 -u {username} -p {databasename} < {dump_data}
Enter password: {password}
<実行例>
$ mysql -h wp-db.xxxxx.ap-northeast-1.rds.amazonaws.com -P 3306 -u wp_db46xxxxxxxxx -p i_xxxxxxxx < i_xxxxxxxx.sql
- ブログページにアクセスして元と同じように表示されることを確かめる
##[2]uploadsディレクトリのメディアファイルの保存先をS3に変更する
###【注意】2020年5月現在、絡新婦プラグインは公開が終了しています
したがって、手軽に冗長構成下でメディアファイルを同期することはできなくなりました。本ハンズオンにおいては、画像や動画を含まない投稿に限定することで鉄板構成を学んでいただくことができます。
記事の投稿時にアップロードしたメディアファイル(画像等)は、WordPressサーバのuploadsディレクトリに保存され、MySQLにはそのURLが書き込まれます。したがってWordPressサーバをスケールアウト構成とする場合、全てのサーバのuploadsディレクトリが同期されていないと、接続したサーバによってメディアファイルのリンク切れを起こしてしまうことになります。
通常はrsyncやlsyncd等を使って各サーバのuploadsディレクトリ間で双方向の同期をかけます。
今回はより簡易な方法として「絡新婦(じょろうぐも)プラグイン」を利用します。「絡新婦プラグイン」を使うと、uploadsディレクトリ内のファイルを自動的にS3に転送し、ソース内のURLも自動的にS3のエンドポイントに書き換えてくれます。Webページのメディアファイルは常にS3を参照しますので、サーバ間の同期を気にする必要がなくなります。
※ StaticPress S3プラグインとの同時利用はできません
###[2-1]S3バケットを作成し、IAMキーを取得する
**独自ドメインを使ってAmazon S3で静的Webサイトをホストする**を参考にして、画像を保存するS3バケットの作成、Web公開、IAMキーの取得を行って下さい。
- 上記手順ではバケット名とFQDNを一致させていますが、絡新婦に使うバケットにドメイン(FQDN)を割り当てる必要はないので、任意の分かりやすい名前をつけてOKです
- StaticPress S3用のバケットと共用可能です
###[2-2]「絡新婦(じょろうぐも)プラグイン」を有効にして設定する
- WordPressダッシュボードを開く
- [プラグイン] -> [Nephila clavata(絡新婦)] -> [有効化]
※ StaticPress S3プラグインが有効になっている場合は「停止」する
- [設定]をクリックする
- S3バケットのIAMキーを入力し、AWSリージョンを選択する
- Stogage Classは[STANDARD]を選択する
- [変更を保存]をクリックする
- S3バケットを選択し[変更を保存]をクリックすると、S3 URLが自動的に入力される
- ブログページにアクセスして画像の参照先(画像を右クリックして新しいタブで開けば分かる)がS3エンドポイントに変わっていることを確認する。S3エンドポイントに変わらない場合は、新規で画像を含む記事を投稿してから確かめてみる
##[3]EC2をELBにぶら下げる
###[3-1]EC2をELBにぶら下げる
- AWS ConsoleでEC2を開く
- 左ペインの[Load Balancers]をクリックする
- [Create Load Balancer]をクリックする
- [Classic Load Balancer]を選択し[Create]をクリックする
- Load Balancer Nameに適当な名前を入力し[Next: Asign Security Groups]をクリックする
- WordPressインスタンスにあたっているのと同じもの(厳密にはSSHは不要)を選択し[Next: Asign Security Settings]をクリックする
- [Next: Configure Health Check]をクリックする
- Ping Pathを[/wp-content/index.php]に変更し[Next: Add EC2 Instances]をクリックする
- WordPressインスタンスを選択し[Next: Add Tags]をクリックする
- [Review and Create]をクリックする(タグの設定は任意)
- [Create]をクリックする
- [Close]をクリックする
- 作成したELBを選択する
- [Edit stickiness]をクリックする
- [Enable Load Balancer Generated Cookie Stickiness]を選択しExpiration Period:にセッション維持の制限時間を秒単位で入力する(3600秒もあれば充分)
- [Save]をクリックする
- [Instances]タブをクリックする
- しばらく待ってStatusが[OutOfService]から[InService]に変わっていることを確認する
###[3-2]DNSをELBに向ける
**elb.{独自ドメイン}**のようなサブドメインを作成し、ELBを向くようにします。独自ドメインをもっていない場合は本項を飛ばしてください。
####独自ドメインをRoute 53でホストしている場合
AレコードAliasを登録する
http://qiita.com/Ichiro_Tsuji/items/8471fe0b3d4d17cde146#aレコードaliasの登録
####独自ドメインをRoute 53 以外のDNSでホストしている場合
DNSにCNAMEレコードを作成し、ELBのDNS name(下図黄緑の囲み)を登録する
###[3-3]WordPressアドレスを変更する
- 先ほどDNSに登録した**http://elb.{独自ドメイン}**(独自ドメインをもっていない場合は、ELBのDNS name)にアクセスして、トップページが表示されることを確認する(このままでは記事等のリンク先がELB経由とならない)
- [設定]をクリックする
- WordPress アドレス (URL)とサイトアドレス (URL)を、先ほどDNSに登録したELBのURL(独自ドメインをもっていない場合は、http://{ELBのDNS name})に変更する
**※ ここの設定を誤るとWordPress管理画面にアクセスできなくなるので慎重に!!**設定を誤って管理画面にアクセスできなくなった場合は次項参照 - [変更を保存]をクリックする
- 変更後の「WordPress アドレス (URL)」でブログページと管理画面にアクセスできることを確かめる
####もし、管理画面にアクセスできなくなったら・・・
本来であればDBのレコードを直接修正して復旧する必要がありますが、暫定的にwp-config.phpを修正することで管理画面にアクセスできるようになります。
- WordPressサーバにSSHでアクセスし、下記コマンドを実行する
※http://elb.iot.kyoto
は、ELBのURL
$ cd /var/www/vhosts/i-xxxxxxxx
$ sudo cp wp-config.php wp-config.php.org
$ sudo vim wp-config.php
/*53行目あたり、//define('WP_DEBUG_DISPLAY', false);の後に追記する*/
define('WP_HOME','http://elb.iot.kyoto');
define('WP_SITEURL','http://elb.iot.kyoto');
###【注意】2020年5月現在、[3-4][3-6]の手順によるAMIMOTO AMIインスタンスのクローニングができなくなっています。クローニング自体はWebサーバの冗長化において一般的に行われることですので、当該の記事は修正しません。下記にAMIMOTO AMIインスタンスを冗長化したい場合の手順を記します。
- 通常の手順でもう1台AMIMOTO AMI(Apache)を立ち上げる。その際、元のインスタンスと違うAvailabillity Zoneを選択する(Availabillity Zoneの設定は[3-4]参照)
- 新規で立ち上げた方のインスタンスにSSHで接続し、DBの接続情報を変更する([1-4]参照)
- 下記の全ての接続情報が2台のインスタンスで一致している必要があるので注意
'database' => 'i_xxxxxxxx',
'username' => 'wp_db46xxxxxxxxx',
'password' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
'host' => 'wp-db.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com',
- [3-5]→[3-7]の順に進める
###[3-4]EC2のクローンを作成する ※AMIMOTO AMIでは実行できなくなりました
- AWS ConsoleでEC2を開く
- 左ペインの[Instances]をクリックする
- WordPressインスタンスの上で右クリックし、[Image] -> [Create Image]の順に選択する
- このとき併せてAvailabillity Zoneを確認しておく
- 任意のImage nameを入力する
- No Rebootにチェックを入れ[Create Image]をクリックする
- 左ペインの[AMIs]をクリックする
- Statusがavailableに変わったら、作成されたイメージの上で右クリックして[Launch]を選択する
- 下記以外は全てクローン元と同じ設定でインスタンスを作成する
・Availabillity Zoneを先ほど確認した値と違う方を選ぶ
・[Name]Tagに見分けられる名前をつける
###[3-5]クローンインスタンスをELBにぶら下げる
- 左ペインの[Load Balancers]をクリックする
- Load Balancerを選択する
- [Instances]タブを開く
- [Edit Instances]をクリックする
- 先ほど作成したインスタンスを選択する
- [Save]をクリックする
- しばらく待ってからリロードして、追加したインスタンスのStatusが[InService]に変わっていることを確認する
###[3-6]クローンインスタンスの新しいコンテンツディレクトリにコンテンツをコピーする ※AMIMOTO AMIでは実行できなくなりました
クローン元と先とではEC2のインスタンスIDが変わるので、それにともなってコンテンツディレクトリ名が変わります(AMIMOTO独特の現象)。そこで、旧ディレクトリから新ディレクトリにコンテンツをコピーします。
$ cd /var/www/vhosts
$ ll
-
ディレクトリが新旧2つあるのが分かる。コンテンツは旧ディレクトリにしか入っていない
※ まれにディレクトリが1つしかない場合がある(原因不明)。この場合、コンテンツコピー作業は不要
-
コンテンツをコピーする
$ sudo cp -r {旧ディレクトリ}/* {新ディレクトリ}
<実行例>
$ sudo cp -r i-faxxxxxx/* i-fexxxxxx/
- WebブラウザでクローンインスタンスのPublic DNSにアクセスしてブログページが表示されることを確認する
###[3-7]片肺状態にしてみる
片方のインスタンスを停止するなどして、わざと片肺状態にしてもブログページや管理画面へのアクセスに問題がないことを確かめる。とくに、メディアファイルはブラウザにキャッシュされるので、他のブラウザで開いてリンク切れしていないか確かめる
###[3-8]メンテナンス時の注意
テーマの修正やプラグインの追加/アップデート、WordPress本体のアップデートなど、ソースコードの変更を伴うメンテナンスを行う場合は、インスタンス間でソースコードの不一致が起こらないよう下記手順でクローン作成を行うことをおすすめします。
- 片方のインスタンスをELBから切り離し、停止する
- 残ったインスタンスでメンテナンスを行う
- メンテナンス済みインスタンスのクローンを作成し、ELBにぶら下げる
##[4]RDSをリストアしてみる(時間が余った人向け)
RDSは5分前までの任意の時刻を指定して簡単にリストアすることができます。おおまかな手順を記しますのでリストアにチャレンジしてみましょう。
###RDSのリストアとは
現在稼働しているRDSインスタンスのバックアップおよびトランザクションログから5分前までの任意の時刻を指定してリストアします
- リストアの際に新しいインスタンスが作成されます
- 新しく作成されたインスタンスは、リストア元のインスタンスとは違うインスタンス名にする必要があります
###大まかな手順
- リストアが正しく行われたか確認するために新しい記事を投稿し、投稿時刻を控える
- AWS ConsoleでRDSを開く
- RDSのインスタンス名を変更する(例:wp-db -> wp-db-old)。変更した時点でブログページにはアクセスできなくなる
【RDSインスタンスの名前を変更する手順】
・名前を変更するRDSインスタンスを選択し、[Instance Actions] -> [Modify]
・[DB Instance Identifier] テキストボックスに新しい名前を入力する
・[Apply Immediately] チェックボックスをオンにし、[Continue] をクリックする
・[Modify DB Instance] をクリックして変更を完了する
- RDSインスタンスを選択し、[Instance Actions] -> [Restore to Point in Time]
- 記事を投稿した時刻より前の時刻を指定し、[DB Instance Identifier]で変更前のインスタンス名(例:wp-db)を指定する
- リストアしたインスタンスがavailableになったら、ブログページにアクセスして記事投稿前の状態になっていることを確認する
- リストア元のインスタンスを削除する
#あとかたづけ
今回使用したAWSのサービスのうち、Route 53以外は通常の使い方であれば1年間の無料利用枠に収まります。
無料利用枠は下記で確認して下さい。
http://aws.amazon.com/jp/free/
AMIMOTO AMIは起動後14日を過ぎると自動的にソフトウェア料金の課金が始まります。
触りたおして気が済んだら、下記の手順であとかたづけをしましょう。
##EC2インスタンスの削除方法
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/terminating-instances.html
##RDSの削除手順
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html
##S3の削除方法
http://docs.aws.amazon.com/ja_jp/gettingstarted/latest/swh/getting-started-cleanup-s3.html
##Route 53の削除方法
http://docs.aws.amazon.com/ja_jp/gettingstarted/latest/swh/getting-started-cleanup-route53.html