WordPress 5.2.3 に自動更新されたところ、どうも弊環境の mod_security に引っかかる項目が増えたようでWordPressのコンパネにログインができなくなりました。
/var/log/httpd/modsec_audit.log の内容を確認の上で除外ルールを3つほど追加し正常にコンパネが利用できる状態に。
この辺り環境によっても設定している除外ルールは様々かと思いますが、もし5.2.3更新以後に引っかかる場合は確認してみてください。
WordPress 5.2.3 に自動更新されたところ、どうも弊環境の mod_security に引っかかる項目が増えたようでWordPressのコンパネにログインができなくなりました。
/var/log/httpd/modsec_audit.log の内容を確認の上で除外ルールを3つほど追加し正常にコンパネが利用できる状態に。
この辺り環境によっても設定している除外ルールは様々かと思いますが、もし5.2.3更新以後に引っかかる場合は確認してみてください。
WordPressをはじめとした管理者が自由に投稿できるタイプのCMS冗長化は、DBを Amazon RDS などに向けてもテーマの編集やアップロードした画像、各種ファイルの扱いなどが面倒でした。
Amazon S3 に画像をアップロードするようにするWordPressプラグインなども有りますし、複数サーバー間のrsync、lsyncdでファイルの内容を同期するなどの方法も有りますが、先日東京リージョンでもリリースされた Amazon EFS を利用すると簡単に「複数サーバーで共用のドキュメントルート」を実現する事が出来ます。
Amazon EFS (Elastic File System)はマネージドなNFSサービスで複数のEC2インスタンスからマウント・アクセスする事が可能です。
以下手順
AWSマネジメントコンソールにログイン。
新しいVPCを作ります。
作成したVPCに新しいサブネットを2つ作ります。ここではAZ冗長化の為に1a AZと1c AZにサブネットを作成します。
インターネットゲートウェイを作成します。
作成したインターネットゲートウェイをVPCにアタッチします。
作成したVPCのデフォルトルートテーブルにルーティングを追加。
0.0.0.0/0 を先ほど作成したインターネットゲートウェイに向けます。
Webアクセス用のセキュリティグループを追加。VPCの選択ミスに注意。
SSH/HTTP/HTTPSをまとめて許可。SSHは本来はセキュリティグループを分けてより適切に制御した方が好ましいです。
Webサーバ用のEC2インスタンスを起動していく。Amazon Linux 2 インスタンスを選択。
インスタンスタイプの選択。
VPCの選択を忘れない事。サブネットはとりあえず1aの方を選択する。自動割り当てパブリックIPは有効にする。
ストレージの設定。
セキュリティグループは「既存のセキュリティグループ」からWeb用に作成した物を適用。
キーペアが無ければ新しく作成して手元にダウンロードする。
マシンの起動を待つ。
起動したらダウンロードしたキーペアを鍵ファイルにSSH接続。
PHP関連とApacheを導入。
yum install php php-common php-opcache php-gd php-mysqlnd php-mbstring php-fpm httpd
データベース冗長化の為にAmazon RDS for MySQL のインスタンスを作成する。RDSの画面からMySQLを起動していく。
MySQL 5.7.21を選択。
マルチAZ設定を有効化。これでDB側が複数AZに冗長化されます。
DB名やユーザー、パスワードなどを適当に設定。メモしておく事。
作成したVPCを選択。DBサブネットグループは新規作成。
DBパラメータグループ、オプショングループはデフォルトのまま。本来は別で作成しておいた方がいいです。後から設定を変更する際にデフォルトのままだと面倒です。
EC2インスタンスにmysql (mysql-serverではない)をインストール。パッケージとしてはmariadbが降ってきます。
RDSのエンドポイント名をメモ。
RDSに適用されているセキュリティグループにWeb用セキュリティグループからのTCP: 3306許可を追加。
mysqlコマンドからRDSに接続が出来る事を確認。
ドキュメントルート冗長化の為のEFSを起動していきます。
作成したVPCとサブネットを選択。セキュリティグループはとりあえずデフォルトのまま。
パフォーマンスモードはとりあえずそのまま。
EFSが利用可能になるのを待ちます。
EFS用のセキュリティグループを作成。
EFS用セキュリティグループにWeb用セキュリティグループからの全許可を追加して保存。
EFSインスタンスの画面からマウント方法を確認する。必要なEFSマウントヘルパーを導入する。
sudo yum install -y amazon-efs-utils
現在のVPCの設定ではDNS名でアクセスできないという警告が出ているので対応する。
VPCの設定で「DNSホスト名の編集」を「はい」に変更。
EFSにDNS名でアクセスできるようになります。
先ほどのEFS接続方法がより具体的な内容に変化している。
EFSのセキュリティグループの設定を先ほど作成したEFS用のセキュリティグループに変更。これでWebサーバからのNFSアクセスが通るようになります。
手順通りにコマンドを実行しEFSがマウントできたことを確認。今回は手動で叩いていますが、EC2のユーザーデータに仕込んでおくと起動時にマウントしてくれるようになります。
Apacheを起動。
EC2のDNS名で接続できることを確認。
EFSマウント配下にドキュメントルート用のディレクトリを作成、Apacheのドキュメントルート設定もそこを参照するように変更。今回は /efs/wp に実態を配置、 /var/www/html/wp をそこへのシンボリックリンクにして、/var/www/html/wp をドキュメントルートにしています。
Apacheを再起動して反映。閲覧テスト用のファイルをドキュメントルートに配置。
/etc/php.ini の設定で date.timezone を Asia/Tokyo に設定しておく。PHP設定変更後もApache再起動を実施。
testと書いたindex.html、<?php phpinfo(); が実行される info.php が閲覧できることを確認。
WordPressをセットアップしていきます。tar.gzでのアーカイブをwgetでダウンロード。
アーカイブをドキュメントルート配下に展開。この際にEFSは少しディスクI/Oが遅い事が分かります。ゆくゆくはCloudFrontなどでCDNキャッシュする事も検討した方がいいかもしれません。ファイル展開後はファイルの権限をApacheのものに変更。先ほど作成したindex.htmlとinfo.phpは削除しておきます。
WebブラウザでアクセスしWordPressのセットアップを進める。
DBの向き先はRDSのエンドポイント。その他WordPressのID・パスワードは適当に設定しメモしておく。
セットアップ完了。
現在起動しているEC2インスタンスのAMI(マシンイメージ)を取得。外部からのアクセスが有る状況でもないので「再起動しない」オプションは有効でOK。
作成したAMIから2つ目のEC2インスタンスを起動していく。サブネットはAZ冗長化の為に1cの方を選択。
マシン起動後にSSHログイン、先に1aで起動している方と同様にEFSマウント。先ほども書いたようにユーザーデータにしておくと最初からマウントされた状態になるかと思います。
1aで起動している方のDNS名、同1cのDNS名でどちらもWordPressサイトが閲覧できることを確認。
テーマを切り替えてみます。
もう片方にも反映されました。
画像アップロードを含む記事を作成してみます。
どちらのDNS名でも画像が見られることを確認。これで冗長化を実現できている事が分かります。同期用の設定などを組まなくていいのは楽ですね。
最後にロードバランサ―を立てます。Application Load Balancerを使います。
既存のサブネットを登録。
Web用のセキュリティグループを設定。本来このセキュリティグループにSSH許可は不要なのでALB用に別でセキュリティグループを作成した方がいいです。
ターゲットグループには起動済みのEC2インスタンス2つを追加。
作成したロードバランサーのDNS名をメモ。
ALBのDNS名でWordPressサイトが閲覧できることを確認。
以上でWebサーバー、DBサーバーが冗長化されただけでなく、コンテンツの同期も実現した環境が完成しました。ここまで所要時間は大体1時間強~2時間ほどでした。後は以下を検討していけばいいと思います。
セッション維持:
今回セッション維持は考えていません。WordPressに記事を投稿する際は起動している適当なインスタンスに直接アクセスするなど適当な方法を使います。
オートスケーリング:
AMI作成+ユーザーデータによるEFSマウント設定でオートスケーリングさせます。ファイルの同期はEFSをマウントするだけで完了します。
セキュリティグループ周り:
もうちょっと適切な内容で整理した方がいいです。
Apahce、PHPの設定、MySQLの設定:
今回は何も触っていないのでもちろん要チューニングです
CloudFront導入:
ファイルアクセスのレスポンスが気になるようであれば導入。実際どの程度の負荷まで耐えられるかは未知数。
AWS WAF導入:
既にALBが有るのでそこにAWS WAFを追加する事が出来ます。
あとはEFSを利用したドキュメントルートがどの程度のI/Oまで耐えられるかですね。ほぼ読み込みなら問題ない気がしていますが、これを実運用するならもちろん負荷テストは必要になるかと思います。場合によってはNFSからEC2ローカルに同期するような構成も検討が必要でしょう。以上、EFSでWordPressを冗長化してみた記事でした。
■ 2018年10月27日追記
Amazon Elastic File System (EFS) のプロビジョンドスループット機能が2018年 8月より利用できるようになっています。これを使えば I/O パフォーマンスは改善されるかも?
新機能 – Amazon Elastic File System (EFS) のプロビジョンドスループット | Amazon Web Services ブログ
無料版のAzure WebAppsはそれなりに良い物だったのですが、いかんせんスペック不足過ぎており、上位のプランにアップしようと思うといきなり数千円からという価格になってくるため、AWSのAmazon EC2よりもお安く使えるAmazon Lightsailに移設してみました。
EC2(AWSにおけるIaaSなクラウドサーバ)とLightsail(AWSにおけるVPS)の違いは以下のようになっております。
今回はt2.nanoベースと思われる月額5ドルのプランにしてみました。nanoインスタンスはCPUクレジットに不安が残るものの、今のところ明らかにAzure WebApps 無料プランよりは快適に動いています。
以下、移設の中で引っかかった所をまとめておきます。
LightsailにはAmazon Route53とは別のDNS管理機能が有り、一般的なVPSサーバを建てるための設定が全てLighsail側で完結するようになっているのですが、ここでRoute53でドメインを取得しているとひと手間必要になります。
Route53で新規取得したドメインは自動でNSレコードやSOAレコードがRoute53側に設定されますが、LightsailのDNS管理機能を使うにはここでネームサーバの指定をLighsailのDNS機能のネームサーバーへ変更してやる必要が有ります。
考えてみれば当たり前なのですが気づくのに結構時間がかかりました。ネームサーバの指定は例えばGoogle Plubic DNSのキャッシュ フラッシュ機能でもフラッシュ出来ないので、結構な時間変更の反映を待つ形になります。仕方が無いのでRoute53側でも一次的なAレコードを追加しました。
今思うとドメイン関連は、Route53だけで完結させても良かった気がします。
昔SQLでパパっと変更すればOKだったような気がしますが、実際にはテキストではない形でデータを持っている部分も有りダメという情報を見かけました。
サイト URL の変更 – WordPress Codex 日本語版
https://wpdocs.osdn.jp/%E3%82%B5%E3%82%A4%E3%83%88_URL_%E3%81%AE%E5%A4%89%E6%9B%B4
上記を参考にwp-login.phpに一次的に
update_option('siteurl','http://example.com/'); update_option('home','http://example.com');
を記載する形で対応しました。
WordPressはサイト移設時に行う301リダイレクトについてもプラグインがいくつか有り、移行元サイトの方で「Simple 301 Redirects」「Redirection」等を試してみたのですが、なぜか動かない。もしかしてHTTPヘッダの送出ではなく.htaccessファイルを作るなど、Apacheであること前提のプラグインだったりするんでしょうか?(未確認)
仕方が無いので(Azure WebAppsはIISなので)web.configを編集して対応しました。
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <!-- もともとWordPressを動かすために書いてあったURLリライトルール --> <rule name="Redirect All" stopProcessing="true"> <match url="(.*)"/> <action type="Redirect" url="http://www.sodo-shed.com/{R:1}" redirectType="Permanent"></action> </rule> <!-- 以下略
これで問題なく新サイトへのパス指定を維持したリダイレクトが動いています。最初からこれでよかったですね。
最初からメモリが少ない(一番下の月額5ドルのプランは512MB)事が分かっているので、
innodb_buffer_pool_size=64M
にするなど相当にしょっぱい設定にしていましたが、それでもMySQLが起動しません。スワップ領域を追加する事で起動するようになりました。
Amazon EC2, mysql aborting start because InnoDB: mmap (x bytes) failed; errno 12
https://stackoverflow.com/questions/10284532/amazon-ec2-mysql-aborting-start-because-innodb-mmap-x-bytes-failed-errno-12
に記載の方法で追加(以下引用)。
Run dd if=/dev/zero of=/swapfile bs=1M count=1024 Run mkswap /swapfile Run swapon /swapfile Add this line /swapfile swap swap defaults 0 0 to /etc/fstab
私は1024MBではなく2048MBでスワップを作成しました。一度の接続数が10に満たないサイトですが、以下のようなメモリ使用状況になります。vm.swappinessは20に設定しています。
$ free -m total used free shared buffers cached Mem: 89 473 16 33 41 85 -/+ buffers/cache: 345 143 Swap: 2047 336 1711
月額10ドルのプランではメモリが1GB有るので、お試しでも512MBはちょっと……という方はそちらを選ぶといいと思います。
前述のようにt2系インスタンス(と同じような制御の物)を使っている可能性が高いのですが
Amazon Lightsailのベンチマーク – 稲葉サーバーデザイン
https://inaba-serverdesign.jp/blog/20161208/aws_lightsail_benchmark.html
t2系では重要なCPUクレジットバランス(CPUクレジット残高)を確認する方法が、すくなくともマネジメントコンソール上では見当たりません。CloudWatch側のメトリクスにも有りません。
t2系インスタンスはクレジットが枯渇しそうでないか、だけを見ればCPUについて今のスペックが適切かどうかが分かりますが、それが無いのでサーバー監視の設定は何かしら別で用意した方がよさそうです。
他にも何かあったような気がしますが、CPUクレジット以外については当たり前と言えば当たり前に必要になる対応なので、逆にそれ以外は特殊なことは無く、EC2でAmazon Linuxを立ち上げるような気持ちではるかに格安なサーバーを建てる事が可能でした。価格重視だと国内VPSにも種類は多いですが、AWSである事、VPC間接続でEC2 VPCとの接続が可能である事、その他AWSで提供されるサービスとの親和性、Amazon Linuxが使えることなどにメリットを感じるならなかなか良いんじゃないでしょうか。