見出し
はじめに
ご存知のとおりこのブログはWordPressで立ち上げています。
WordPressはどうしてもバックエンドの処理やデータベースの更新があるため、せっかくCloudFrontを挟んでいてもキャッシュはほとんど動作しません。
こうなるとオリジンサーバーが落ちてしまった時に、Sorryページの表示はできてもWordPressはダウンしてしまうので少しもったいないですね。
複数サーバーでの運用などで冗長性を高めることは簡単ですが、このブログは企業レベルではなく個人ブログなので、なるべくお金をかけずに冗長化をしたいところです。
そこでWordPressを静的ページにしてS3に格納し、
CloudFront + S3によって実現するサーバーレスなWordPress環境をセカンダリサーバーとして運用することで、メインのLightSailサーバーがダウンしてしまっても情報を提供できるように改良してみました。
構成図
構成図としては上記のとおりです。
このブログのドメインである『noname.work』はCloudFrontを指しているのですが、CloudFrontに指定しているオリジンサーバーは『origin.noname.work』というドメインになっています。
この『origin.noname.work』というドメインには2種類のサーバーが向き先として指定されており、基本的にはLightSail上で動作しているWordPressへアクセスが流れるようになっていますが、LightSailサーバーがダウンしてしまうなどヘルスチェックに失敗した場合にはCloudFront + S3上で動作する静的なWordPressページへアクセスが流れるようにフェイルオーバーする仕組みです。
静的なWordPressの準備
よくブログやコーポレートサイトなどに使用されるWordPressは、バックエンドでPHPが動作したりデータベース上にデータが更新されていく動的なサイトです。しかしCloudFront + S3のみでWordPressを表現させるには静的なサイトに変換する必要があります。
そこで、『StaticPress』というWordPressのプラグインを使用します。
これは現在のWordPressサイトを静的なhtmlファイルに出力し直してくれるプラグインです。
htmlとして出力された静的なファイルはそのままサーバー内の任意のパスに保存されます。
静的なhtmlファイルをS3に自動的にアップロードしてくれる拡張プラグインとして『StaticPress-S3』というものも存在しますが、CloudFrontを前面においたWordPressではホスト周りの設定が複雑になってしまうため、今回は利用しません。
そもそもこのプラグインは長年保守されておらず、(延長されたが)S3の署名バージョン2が廃止となった場合にはモロに影響を受けてしまいます。
そのため、生成されたhtmlファイルをサーバーからS3へ送るのは雑にcronで実行すればいいかなという考えです。
そうそう。
このプラグインを使う前に、パーマリンクの設定でURLの最後がファイル名になるように変えておく必要があるので注意しましょう。
(例)
https://hogehoge.com/2021/04/12345.html
みたいな
S3へのアップロード
AWS CLIでアップロードコマンドを実行できるようにしましょう。
基本的な部分なので記載しませんが、AWSコンソールから該当のS3バケットへPUT/GETできるIAMロールを作成してアクセスキーを登録しておきましょう。
私の環境では以下のコマンドでS3バケットへアップロードしました。。
$ aws s3 sync /opt/bitnami/apps/wordpress/htdocs/static/ s3://{該当バケット}
S3側を確認するときちんとファイル群がアップロードできていることを確認できました。
このS3へのsyncはいちいちサーバー内にsshしてコマンドを叩くのも面倒なので、cronで1ヶ月に1度行うようにしました。
あくまでも静的なセカンダリーサーバーは緊急時のみ使用されるため、リアルタイムに同期している必要はないためです。
とはいえ通信量はそこまで多くはならないので、更新頻度の多いブログであれば1日1回程度のsyncでも良いかもしれませんね。
S3をCloudFront経由で公開する
S3は単体で静的ホスティングすることができますが、今回のような静的WordPressを公開するためにはほとんど全てのファイルを公開させなければなりません。そうすると、WordPressのテーマファイルなど様々なデータを取得されてしまう可能性があります。
安全性を考えるのであれば静的なWordPressへのアクセスはCloudFrontを経由させて、S3バケットへのアクセスはCloudFront以外は拒否する設定にする方が良さそうですね。
今回は構成図の通り『origin.noname.work』というドメインのセカンダリに指定する予定なので、CNAME設定を合わせておきます。
Route53でフェイルオーバー設定
まずはCloudFront + S3の静的WordPressが正常に動作することを確認します。
CloudFrontのドメインを直接指定してアクセスしてみたところ、正常にWordPressのブログが表示されていますね。
Route53の設定で『origin.noname.work』というドメインのフェイルオーバーを設定しておきます。
フェイルオーバーを有効にするとドメインの向き先をプライマリとセカンダリでそれぞれ設定することができます。
なお、プライマリにはヘルスチェックの設定が必須ですがセカンダリにはヘルスチェックの設定はなくても問題ありません。
今回は構成図通りにプライマリはLightSailの動的なページを指定して、LightSailのサーバーが落ちてしまった場合にはS3上の静的なページが表示されるようにしました。
動作確認
動作確認のためLightSail上で動作しているApacheを停止させてみました。
およそ5分程度すると、origin.noname.workの向き先がCloudFrontに切り替わったことが確認できました。
しばらくはCloudFrontのSorryページが表示されましたが、さらに5分程度経過すると本ブログの記事がアクセス可能になったことを確認できました。
すぐさま切り替わらない理由はサーバーダウンからフェイルオーバーまでの時間・フェイルオーバーからDNSの切り替わるまでのキャッシュ時間・CloudFrontのエラーページのキャッシュ時間などが影響していると思われます。
それでも全体で10分程度で記事への閲覧が復活していたので、多少のダウンタイムが許される個人ブログであれば上々といったところでしょう。
なお、LightSailのApacheを起動させたところ3分程度で『origin.noname.work』ドメインの向き先がプライマリへ切り替わりました。
CloudFrontのオリジンを別のCloudFrontにする場合の注意事項
今回の構成ではCloudFrontのオリジンサーバーがCloudFrontになるケースが発生します。
この場合ではCloudFrontのヘッダー情報からHostを送らないように注意する必要があります。
CloudFrontの設定でオリジンサーバーへHost情報を送ってしまうと「noname.work」というドメインで「origin.noname.work」でアクセスされるはずだったCloudFrontへアクセスしようとしてしまいます。
CloudFrontはCNAMEsに設定したドメインか、CloudFront自身のドメイン以外ではアクセスを受け付けませんので、当然エラーとなってしまうわけです。
Hostヘッダーをオリジンサーバーへ送らなければ、「origin.noname.work」というドメイン名でアクセスされますので正常に動作することが期待できます。
私のWordPressではUser-agent以外はオリジンサーバーで必要しないので、上記のように設定し直しました。
終わりに
WordPressを静的なhtmlへ変換してサーバーレス環境によるセカンダリサーバーを立てることで冗長化を行いました。
企業レベルでは10分程度のサービスダウンは許されないケースも多いと思いますが、個人でできる範囲での冗長化としてはコストパフォーマンスを考えても十分選択肢になると思います。
CloudFront + S3の構成なので、データアクセス量が少ないことを考えても1ヶ月あたり$1.0くらいしかかからないでしょう。
問題はサーバーダウンするほどこのブログへのアクセス量が増えたことがないので、今回の冗長化が活用できる機会が少ないことですかね・・・。
せっかく冗長化しているので、もっとアウトプットを増やしてブログへのPVも増やしていきたいですね(笑)
コメントを残す