WordPress を AWS Lambda で運用する
以前 WordPress を AWS Lambda で 運用する 記事を投稿 (英語) しましたが、 EFS対応前 に執筆しました。EFS を使える様になって、WordPress を AWS Lambda 内の実行環境が完全に変わったので新しい記事を書きました。
今回は、SAM より Terraform を選びました。理由はいくつかありますが、主には私が管理するインフラはほぼ Terraform で管理されているのため、既存環境と融合性が優れてる。
Terraform モジュールとして公開 しています。ソースコードは GitHub で公開 しています。
実際どうなの?
まあまあいいよ。このリンク先で稼働しています。 めちゃくちゃ速いわけでもないけど、遅すぎというわけでもない。CloudFrontを利用して静的アセットをキャッシュし、 opcache をチューニングしたらだいぶ速くなった。
通常なら Lambda が同時並行で起動されるときは個々のインスタンスが独立されて実行されれますが、 EFS を使えば異なる Lambda のインスタンスを跨いでファイルシステムを同期させることができる。このため、通常通り WordPress の更新、テーマやプラグインインストール、アップロード等利用できる。
準備するもの
今回のチュートリアルでは、 Lambda のソースコードに入ってるのは PHP を実行する環境のみ。 WordPress のファイル等は、 EFS のボリュームにインストールするので、別途 EC2 のインスタンスを用意する必要があります。
下記に、具体的に何を用意しないといけないのをリストしました。
- 有効なAWSアカウント
- インターネットにアクセスできるプライベートサブネット。 EFS を使うために VPC 内に Lambda を起動する制約がありますが、そうすると NATゲートウェイ や NATインスタンス ( 比較) を使わないとインターネットにアクセスできない。
- Terraform 0.12 以上
- MySQL データベース
- WordPress のファイルを初期インストールするための EC2 インスタンス
Terraform が作成するリソース一覧は こちらにあります。
ステップ
今回は独立した Terraform モジュールを使いますが、他の Terraform の環境に埋め込む場合は適宜修正してください。
このチュートリアルをそのまま使う場合、 us-west-2
リージョンを使ってください。PHP は標準で提供されていないため、カスタムの Lambda レイヤーを使って実行します。私が公開したレイヤーが現在、 us-west-2 しか公開していない。他のリージョンでも公開することを努めていますが、その間は 私がフォークした php-lambda-layer を直接作成することができます。
1. EC2インスタンスを起動する
今回、 t3a.nano
を選びました。 amazon-efs-utils のパッケージを予めインストールしておくのはおすすめです。
コンソールにいるついでに、データベースにアクセスできるセキュリティグループのIDと Lambda を起動するプライベートサブネットのIDをメモしておいてください。
2. Terraform 環境を作成する
$ git clone https://github.com/KotobaMedia/terraform-aws-wordpress-on-lambda-efs
$ cd ./terraform-aws-wordpress-on-lambda-efs
ディレクトリに local.auto.tfvars
というファイルを作って、下記の情報を入れます。
# ステップ1でメモしたセキュリティグループのIDを配列に入れます
security_group_ids = ["sg-XXX"]
# ステップ1でメモしたサブネットのIDを配列に入れます
subnet_ids = ["subnet-XXX", "subnet-XXX", "subnet-XXX"]
もし ~~.cloudfront.net
のデフォルトドメインより、カスタムドメインを使う場合は、 acm_certificate_name
と domain_name
変数も指定します。
Apply すると、terraform がリソースを作ってくれます。
$ terraform apply
AWS 認証情報を求められる場合、中止 ( Ctrl-C
) した上、環境変数で認証情報を設定してください。私の場合、複数のAWS環境を管理しているので、 AWS_PROFILE
という環境変数をよく使います。
Terraform が実際にインフラのリソースを作成する前に、実際稼働しているインフラのリソースの差分を出します。今回は新しく作成しているはずなので、全て「追加」というように出ると思います。確認した上で、 yes
を答えてください。
CloudFront distribution が入ってるため、apply に多少時間かかる(僕の場合は、全部で5分ぐらいかかりました)。完了したら、アウトプット変数がいくつか表示されます。この変数をまただす場合は、 terraform output
コマンドを使ってください。
そのターミナルをそのまま開いてください、後で使います。
3. EC2 に EFS のファイルシステムをマウントする
EC2 が EFS にアクセスするためにセキュリティグループをアサインする必要があります。ステップ2の Terraform が EFS にアクセスできるためのセキュリティグループを作ってくれたので、それを使いました。 efs_security_group_id
のアウトプット変数の値を EC2 インスタンスに貼り付けてください。
次、EC2 にログインして、 EFS をマウントしましょう。下記のコマンドから、 fs-XXXXX
を efs_file_system_id
のアウトプット変数の値で置き換えてください。
$ sudo -s
# mkdir /mnt/efs
# mount -t efs fs-XXXXX:/ /mnt/efs
もし問題などあれば、 ユーザーガイドによくある問題をリスト しているので、確認してください。
4. WordPress をインストールしましょう
ファイルシステムがマウントされて、やっと WordPress のファイルをインストールできるようになりました。 Terraform がランダムで新しいディレクトリを作った( /mnt/efs/roots/wp-lambda-$ランダム
)ので、そこに cd
しましょう。
最新の WordPress をダウンロードして、そこに解凍してください。
ここから、通常通りの WordPress のインストールを進められることができると思います。カスタムドメインを利用していない場合は cloudfront_distribution_domain_name
でアクセスできます。カスタムドメインを利用している場合は、CloudFront のdistribution のドメインに CNAME を向けて、指定したドメインでアクセスできると思います。
ここから何ができるか
このままだとパーフォーマンスが最高とは言えないのですが、下記の最適化も加えられると考えられます。
- アップロードファイルを EFS より S3 にアップロードする。私は Humanmade の S3 Uploads プラグイン をよく使います。
src/php.ini
に入ってる opcache の設定を調節する。- 静的アセット( JS / CSS 等)を軽量な nginx サーバーで返す。
handler.php
を調節してCache-Control
を追加する。これによって、 CloudFront のキャッシュがもっと使えるようになります。
制約
AWS のサービスの技術的な制約によって下記のようなリミットがあります。
- AWS Lambda の 呼び出しペイロードの容量上限が 6 MB のようです。これによって、 6MB 以上のファイルを Lambda WordPress にアップロードできません。
- API Gateway の最長のタイムアウトが 29 秒。29秒以上のリクエストが中断されます。ほぼ大丈夫ですが、たまに更新やプラグインのインストール等で発生しました。
この運用の形によって、他の制約もあります。
- FTP やログイン可能な SSH アクセスがありません。EC2 インスタンスを使ってファイルを管理しないといけない。
- 無限に同時並行で実行できるプラットフォーム Lambda から接続数が有限な MySQL に接続します。もし接続で問題になるところがあれば Aurora Serverless を試してみる価値があると思います。
最後まで読んでくれてありがとうございます!
質問、難しかったところ、改善してほしいところ、コメント等は下記のコメントフォームや Twitter で連絡してください。