今回、新しくブログを作成したわけですが、そのときにいろいろ挑戦してみました。
仕事でAWSとGCPを9:1くらいで使っているので、プライベートではGCPを使っています。なので、今回もGCPを使いました。
以下のような感じで、GCP上にWordPressを乗せるというもの。
現状のこのブログはこのような構成になっています。
特に今回こだわったのが以下の点。
- Compute Engine上でWordPress
- Cloud Storageの手前にはCloud CDNを挟む
- Cloud Load Balancing(負荷分散)を使ってURIパスに対してメディアファイルかそれ以外かを振り分ける
- Cloud Load Balancingを使ってHTTPS化
- 静的ファイルはCloud Storage
Compute Engine上でWordPress
まずはこれをやらなきゃいけないところ。GCP上でWordPressを導入するのは実は意外と簡単だった。
Cloud Launcherを使うことで、WordPressの仮想マシンを簡単にデプロイできました。
今まで、Compute EngineのVMを立てて、そこに手動でWordPressをインストールして・・・っていうのはやったことは何度かあったのですが、今回のようにCloud Launcherを使うと本当にサクッととてもキレイに作ることができて感動しました!
Cloud Load Balancing(負荷分散)を使ってURIパスに対してメディアファイルかそれ以外かを振り分ける
静的ファイルはWordPressでいうところのメディアですね。ファイルサイズが大きくなりそうでそれだけでVMのディスクを圧迫するのは勿体無いし、それをたくさんダウンロードしようとしてVMに負荷をかけるのは良くないと思って、静的ファイルについてはCloud Storageに乗せることにしました。
今回の下の方でも説明しますが、ロードバランサのホストとパスのルールの設定を以下のように設定することで、静的ファイルはCloud Storage(GCS)に、それ以外のファイルはCompute EngineのVMにアクセスするように設定しました。
Cloud Load Balancingを使ってHTTPS化
ロードバランサを使った最大の理由はこれ!SSL認証を簡単に導入するためです。
今回はSSL証明書は無料で取得できるLet's Encryptを利用しました
参考サイト:https://qiita.com/tomoyoshi-de/items/2a357cfa6f1f6287c0df
途中で認証ファイルを格納する必要があるのですが、上の記事だとCloudStorage上に乗せていますが、CloudStorage上に.well-known/acme-challengeというディレクトリを切ることができないようなので(acme-challengeを作成しようとしたらエラーになった)、/var/www/html/以下に/.wll-known/acme-challengeのディレクトリを作成しました
cd /var/www/html mkdir -p .wll-known/acme-challenge vim V_oT7yK970QJSjKnhpOt5MXY80FTm3kqw6SEovuz8gw // ←ここのファイル名は作成時に指定されるものを入力する
あとは、参考サイトに書いてあるとおりにいけば認証がうまくいきます。
あとはロードバランサの設定でフロントエンドの設定でプロトコルをHTTPSに設定して、バックエンドのプロトコルをHTTPにすればおっけーです。
フロントエンドのIPアドレスをエフェメラルではなく静的IPにしました(AWSで言うところのElastic IPですねきっと)
静的ファイルはCloud Storage
使用したWordPressのプラグインは「WP-Stateless」というもの。簡単にGCSと連携してくれます。
ただ、この初期設定を操作していくと、GCPのプロジェクトを新しく作られちゃうので、設定が終わったらサービスアカウントのJSON(設定上だとService Account JSONと書かれている項目)をGCPのコンソール上で自分の使いたいプロジェクト上で作り直して設定しなおしました。そうしないとロードバランサからGCSへのアクセスがうまくできなかったので。。
GCSの設定は簡単で、バックエンドにバケットを設定できるので、そこでサクッと設定できました。
また、静的ファイルのURLをデフォルトだとGoogleのURL(storage.googleapis.com)になってしまうので、そこも設定を行います。
- Bucket Folderをmediaにして、わざとバケット直下にmediaというディレクトリをはさみます。
- Domainをblog.pnkts.netに設定します。
- blog.pnkts.net/media/~でGCSにアクセスするように先程のホストとパスのルールを設定します。
- プラグインのソースをちょっと修正します。
4番目のプラグインのソースをいじるのは、画像をアップロードして使おうと思っても、storage.googleapis.comのドメインでメディアを記事に挿入しようとしてくるので、頑張ってソースを読んで修正しました。修正したところは以下のようなところです。
$ pwd /var/www/html/wp-content/plugins/wp-stateless $ vim lib/classes/class-bootstrap.php
public function get_gs_host($sm = array()) { $sm = $sm?$sm: $this->get( 'sm'); $image_host = 'https://storage.googleapis.com/'; $is_ssl = strpos($sm['custom_domain'], 'https://'); $custom_domain = str_replace('https://', '', $sm['custom_domain']); if ( $sm['bucket'] && $custom_domain == $sm['bucket']) { $image_host = $is_ssl === 0 ? 'https://' : 'http://'; // bucketname will be host } return $image_host . $sm['bucket']; }
この関数のreturn値を無理やり書き換えます。
public function get_gs_host($sm = array()) { $sm = $sm?$sm: $this->get( 'sm'); $image_host = 'https://storage.googleapis.com/'; $is_ssl = strpos($sm['custom_domain'], 'https://'); $custom_domain = str_replace('https://', '', $sm['custom_domain']); if ( $sm['bucket'] && $custom_domain == $sm['bucket']) { $image_host = $is_ssl === 0 ? 'https://' : 'http://'; // bucketname will be host } // GCSにアップロードしたものを独自ドメインで取得するため return "https://blog.pnkts.net"; return $image_host . $sm['bucket']; }
見てわかるように、ものすごい無理やりです。でもこれでうまくいきました。
この結果、例えばこの記事の一番最初の画像は以下のようなURLパスになります。シンプルでカッコイイでしょ!!
https://blog.pnkts.net/media/2018/04/5f7d0ee4-blog-pnkts.png
※はてなブログに移行したため、現在はこのURLで確認することができなくなっております。
Cloud Storageの手前にはCloud CDNを挟む
GCSに直接アクセスしちゃってもいいんですが、高速化(するはず)と料金が安くなる(はず)のため、Cloud CDNを利用して、メディアファイルをキャッシュさせるようにしてみました。
これも簡単、コンソール上でポチポチっとするだけで作成することができます。
WordPressが動いている側もアクセスする度にPHPが実行しちゃっているので、そちらもCDNを挟んだほうがいいのかもしれないですが、挟んでも正常に動くかどうかがちょっと心配だったので、一旦メディアファイルだけをキャッシュさせることにしました。
きっとこれでページの読み込みがより高速になったはずです。
最後に
各項目毎にそれぞれ別の記事にしたほうがよかったかもしれないくらいのボリュームになってしまいましたね。
とりあえず6時間位かけて作ってみたのですが、なんとかうまくブログを開設することができました。
また、本当はDBをCloud SQLを使いたかったのですが、まだそこまでできてないのです。もうちょっと時間があるときにチャレンジしようかなと思います。
参考サイト
Let's Encrypt でSSL無料化 in gcp:https://qiita.com/tomoyoshi-de/items/2a357cfa6f1f6287c0df