お陰様で litera.app/blog のアクセス数が月間 100 万 PV に迫る勢いまで成長し、今まで適当に設定した(嘘です)冗長化と負荷分散設定ではもはや死に体になってきていたので、ちゃんとコンテンツ配信できる仕組みを整えてみました。この記事では以下の内容でやった内容や起こった事象を書き記して、同じことを考えている方の参考になれば、と思います。
目次
- WordPress のプラグイン「Export Media Library」を使って画像をエクスポートし、S3 に移行(誤り)
- WordPress のプラグイン「search regex」を使って記事中の URL を S3 の新 URL に置換
- EC2 インスタンスから画像を一気に S3 にコピー
- Route53 でドメインの割り振り先を S3 のバケット URL に設定(誤り)
- CloudFront で S3 バケットの SSL 証明書を取得
- Route53 でドメインの割り振り先を CloudFront の URL に設定
- WordPress のプラグイン「search regex」を使って記事中の URL を新 URL に置換
目次見ただけで長い記事になりそうだ、、ChatGPT 君の力を借りよう。
wordpressのプラグイン「Export Media Library」を使って画像をエクスポートし、S3に移行(誤り)
まず、私は画像を移行するために「Export Media Library」という WordPress のプラグインをインストールしました。このプラグインは、WordPress のメディアライブラリ内の画像を一括でエクスポートする機能を提供してくれます。
最初に「Export Media Library」プラグインをインストールしました。これは特に問題なし。
次に、「Export Media Library」を使用して画像をエクスポートし、ローカル PC にダウンロードしました。これも特に問題なし(と思っていた)
しかし、このプラグインは WordPress が自動生成するサムネイル画像をエクスポートすることができないことを S3 にアップロードされた画像の数と見比べて判明。結果として、一部の画像のみが S3 に移行された。あと自動生成した画像数が多く、これ全部一回ローカルに転送したらネットワーク使用量(=費用)やばくない?ということで、画像の出力と S3 へのアップは別の方法を模索するため、一回断念。
このため、ブログ記事内では、一部の画像が S3 から配信され、他の画像は従来の EC2 インスタンスから配信されるという状況になってしまいました。こ、これは望ましくないぞ、、でももう時間が、、ということでせっかく休日に作業したのに中途半端な状態で終わることに。
教訓:WordPressの画像を移行するのに「Export Media Library」はおすすめしません。後述しますが、画像の移行先が S3 なら EC2 インスタンスから Amazon CLI を使って直接アップできるし、サブネット内からの転送なので料金もかかりません。ので、そちらを使ったほうがいいです。
wordpressのプラグイン「search regex」を使って記事中のURLをS3の新URLに置換
さて、実は結果だけもう先に書いちゃってますが、一部の画像とはいえ S3 にアップしたので、少しでもブログの負荷を下げるために、S3 を参照できる画像は S3 側のパスに変えておくのに「search regex」というプラグインで検索を置換を行いました。
しかしこれがまた曲者で。
記事数に対して検索結果が全然少ない。1/3 くらい。これ、あとから(作業開始後1時間~1時間半後くらいに)発覚したんですが、自動生成されたサムネイル画像のパスが保存されているテーブルが検索対象になっていない?ぽく、結局本文内の記事のみ S3 の URL にアップデートすることになりました。
それでも何度か置換を行えば必要な分(本文内の画像URL)は全部置き換わったので、結果としては楽に置換できたと思います。でも全件対象にならないのかは謎です。内部で limit 処理でも入れてるのかな?という感じ。興味がある人は調べて私におせーてください。ご連絡はこちらから。
EC2インスタンスから画像を一気にS3にコピー
ブログ画像の URL を一部変更し、S3 から読みだしたことでブログサーバの負荷はほんの少しだけ軽減されたように思います。とはいえ、夕方くらいには CPU クレジットが 150 近くまで減り、ハラハラしながらモニタリングしていました。
もちろんこの間、ただ減っていく CPU クレジットを手をこまねいて眺めていたわけではありませんよ。EC2 にある画像を S3 に直接アップできないものか、と調査を進め、以下のようにすることで直接アップが可能だという知見を得ました。
1.ブログサーバの含まれる VPC に、S3 へのエンドポイントを追加
2.ブログサーバの IAM に S3 へのアクセス権を付与
3.Amazon CLI でバケットを指定してファイルをコピー
上記1~3もちょっと調べればやり方の記事は出てくるので、ここではいろいろと発生した問題について記載します。
1:特に問題なし(参照した記事から実際の設定画面の UI が変わっていたけど、まぁなんとかなるレベル。
2:先にコマンドだけ試しちゃったので S3 へのアクセス権限がねーぜ、と言われたので EC2 内のコマンド実行ユーザ単位のアクセス権にするか、EC2 インスタンスの IAM ユーザに S3 のアクセスポリシーを割り当てるか考えました。後者のほうが楽だったので AWS の管理コンソールから S3 へのポリシーを割り当てた。
3:最初は cp コマンドでやろうと思ってましたが、いろいろ調べて sync コマンドでフォルダをまるごと指定して実施。--exculde "" --include ".png" などで転送ファイルオプションを指定して、不要な index.php が S3 に行かないように制御して全ファイルの転送は終了
ファイルの転送処理自体の作業はなんてことなかったんですが、途中実は年度を間違えてコピーしていたことに気づき、10 ヶ月分の転送処理をやり直したのは秘密です。とはいえ、それも 10 分くらいの手戻りでしたが。
Route53でドメインの割り振り先をS3のバケットURLに設定(誤り)
よっしこれで S3 から全画像を配信できる準備が整ったぞ!と意気揚々とし次は S3 にドメインを割り当てる番だ、とうっきうきで Route53 にドメインの設定を行って、早速アクセス。
無味無臭なあのブラウザのエラー画面で「SSL証明書が怪しいんだぜ~?」という警告を頂戴する。
そういや、S3 ってどうやって独自ドメインの SSL 設定するんだっけ?と調べたところ、どうやらCloudFront を経由しないと SSL 化できないとのネット記事。
CloudFrontでS3バケットのSSL証明書を取得
ということで、以下のように作業。
1.CloudFront でオリジンを S3 のバケットにしてキャッシュ化する。
2.AWS Certificate Manager で SSL 証明書のリクエストを作成。ドメインは Route53 上にあるので、この画面だけで Route53 への Vefiry 用 CNAME が登録できる。この点は AWS 使ってその便利さを再度実感した。
3.ドメイン所有者検証( Verify )には数分程度かかるが、それも無事に終了。
Route53でドメインの割り振り先をCloudFrontのURLに設定
ここで改めてドメインの割り振り先を Route53 に設定。CNAME の値は上で作った CloudFront のURLにする( S3 ではないことに注意)
この時点で S3 から CloudFront にキャッシュされた画像が指定のドメインで SSL アクセスできるようになった。
wordpressのプラグイン「search regex」を使って記事中のURLを新URLに置換
そして改めて今度はブログ内の記事を S3 ではなく SSL を使えるようになったドメインで設定し、サムネイルも本文内の画像も、無事に割り当てた URL からの読み込みを確認できました。
まとめ
途中、実はロードバランサーで無理やり割り振ることも考えたのですが、構成的に難しかったのと、これを機会にちゃんと配信インフラ整備しようと思って結構時間使いました。ここで設定しておけば今後メンテナンスコストも、実際のサーバ費用も安く抑えられるかもしれないと思ったのもあります。
本当は設定時の画像とか載せてみやすくしようとも思ったのですが、UIは結構すぐ変わって割りと混乱するので、この記事ではやらなきゃいけないことの網羅と、注意点だけに絞って記載したつもりです。
世の中に広くあまねく wordpress ユーザに届けば幸い。
そんな AWS を使い倒してサービスを構築している当社で働きたい!という方、ぜひご応募お待ちしております。
追伸:結局ChatGPTは最初のセクションだけ書いてもらい、あとは全部自力で書きました。