ENECHANGE の川西( a.k.a. cuzic )です。
最近、いびきの軽減を目的として、のどちんこを切除する手術を受けました。 職場で昼寝していて、いびきが職場に鳴り響いていたのがなくなり、職場環境改善にもつながりました。
Wordpress のメディア(画像、動画)ファイルとは
Wordpress は、主に下記の3つで構成されています。
- Wordpress の本体のコード( ENECHANGE では Git repo 上に管理されている)
- 記事データ(ENECHANGE では AWS の RDS の MySQL にある)
- メディアファイル(wp-uploads フォルダ以下にあるファイル群。本稿の主題)
ENECHANGE ではこのメディアファイルの管理する方式を変更しました。
Wordpress のメディアファイルの管理方式の問題点
Wordpress はメディア(画像、動画)をファイルとして保管しています。ファイルとして保管しているため、複数台構成とするとき、そのまま冗長化してしまうと、次のような問題があります。
- アクティブ・スタンバイで運用する場合、アクティブ側にだけ画像ファイルがある状態となる。障害で切り替わったのち、画像が表示できない不具合が生じる
- 両系アクティブの場合、サーバ1台だけにメディアファイルが存在する状態となるため、表示したときどのサーバに接続したかによって、画像が表示されたりされなかったりする。
このような問題点を解決する方法として、いろんなやり方がありますが、 ENECHANGE では s3fs を採用していました。
それまでの ENECHANGE の構成
ENECHANGE で Wordpress のメディアファイルを保存するのに使っていた s3fs は、その名から想像できるとおり、 AWS の S3 をファイルシステムとしてマウントする技術です。 s3fs を使って AWS の S3 にメディアファイルを配置することによって、記事の編集作業をするときにアクセスしていたサーバと記事を配信するときのサーバが異なっていても、同じメディアファイルを配信し、正常に表示できるようにしていました。
しかしながらこの方式には次のような問題点がありました。
- 初期に構築した人がすでに enechange.jp のプロジェクトから離れてしまったため、設定等が分かる人はいない
- s3fs は不具合が多く報告されており、継続して利用するのに不安がある
- そもそも s3 の設計思想と、ファイルシステムとしてマウントする場合に求められる要件は大きく異なり、筋が良いと思えなかった。
そこで、代替案があれば、別の技術に乗り換えよう思っていました。ちょうど Wordpress のインフラ環境リニューアルのプロジェクトがあったので、 s3fs を別の技術に乗り替える作業に着手しました。
Amazon EFS とは
そこで白羽の矢が立ったのが、 Amazon EFS です。 EFS ( Elastic File System ) を簡単に説明すると、AWS のマネージドサービスの NFS ( Network File System ) です。
Amazon EFS を使えば、複数台のサーバでファイル共有がカンタンにできるようになるので、 Wordpress の冗長化目的に最適です。実際に Amazon の技術資料 で、Wordpress の冗長化には EFS を採用しています。
enechange.jp の初期構築のタイミングではまだ Amazon EFS が存在しなかったので、当時は仕方ありません。ですが、せっかくのインフラのリニューアルのタイミングで s3fs を使い続ける理由はありません。EFS に切り替えることになりました。
Amazon EFS への移行
Amazon EFS の利用はとてもカンタンで、少しの設定ですぐに利用できました。
ENECHANGE では EFS マウントヘルパーを利用して、マウントしました。
手順については、Amazon のドキュメント で詳しくまとまっています。
ENECHANGE では下記のような設定を記述しました。なお、ENECHANGE ではこのタイミングで Amazon Linux 2 の Elastic Beanstalk 環境に移行しており、Amazon Linux 2 の EB 環境向けの設定ファイル例となっています。
.ebextensions/amazon-efs-utils.config
.ebextensions 以下で、amazon-efs-utils という yum package をインストールしています。 amazon-efs-utils を使うことで Amazon EFS の設定をとても簡単にできます。 通常のNFS で接続する場合と比較して、amazon-efs-utils を使うと、EFS に最適な設定が自動的に有効化されるので、高いパフォーマンスで接続できます。
.ebextensions/amazon-efs-utils.config
packages: yum: amazon-efs-utils: []
.platform/hooks/prebuild/10_efs.sh
プラットフォームフック というのは Amazon Linux 2 で新たに導入された Elastic Beanstalk のカスタマイズ方法です。
プラットフォームフックを利用することで、.platform
以下の特定のディレクトリに記述したシェルスクリプトを、環境構築時やデプロイ時に実行できます。
.platform/prebuild
ディレクトリのシェルスクリプトで EFS のマウントを実行しています。prebuild ディレクトリ内のスクリプトはアプリケーションを解凍して展開した直後、アプリケーションのセットアップを開始する前に実行されます。
#!/bin/bash if [ ! -d /mnt/uploads ]; then mkdir /mnt/uploads chown webapp:webapp /mnt/uploads fi # Amazon Linux 2 以降の EB 環境では環境変数が自動的にセットされなくなったので # 明示的に取得する必要がある WORDPRESS_UPLOADS_EFS_ID=$(/opt/elasticbeanstalk/bin/get-config environment -k WORDPRESS_UPLOADS_EFS_ID) mount | fgrep -q uploads || mount -t efs $WORDPRESS_UPLOADS_EFS_ID:/ /mnt/uploads
シェルスクリプトに慣れた方であれば見れば何をしているのかは簡単に理解できるでしょう。
WORDPRESS_UPLOADS_EFS_ID という EB の環境プロパティの設定内容を、 WORDPRESS_UPLOADS_EFS_ID という環境変数に設定しています。 本番と staging でマウントすべき EFS の ID が異なりますので、その差を EB の環境プロパティ設定を使って吸収しています。
mount | fgrep -q uploads
で、すでに mount 済かどうかをチェックしていて、まだ mount
していない場合にだけ、マウント処理を実行しています。
.platform/hooks/predeploy/50_symlink_uploads.sh
.platform/predeploy
ディレクトリのシェルスクリプトで uploads ディレクトリのシンボリックリンクの作成作業を実行しています。predeploy ディレクトリ内のスクリプトはアプリケーションのセットアップが終了したあと、デプロイを開始する前に実行されます。
#!/bin/bash cd wp-content ln -s /mnt/uploads uploads
このスクリプトの内容は簡単なので解説不要ですね。 wp-content/uploads にアクセスすると、/mnt/uploads 内のファイルにアクセスできるようにシンボリックリンクを作成しています。
おわりに
今回は Wordpress の Elastic Beanstalk 化に合わせて、 Amazon EFS を導入した件について説明しました。
設定例についても、掲載しているので、同じように Amazon EFS を導入しようとしている方のお役に立てると嬉しいです。