Lightsail上のWordPressサイトがSSHごと無応答になった件
概要
WordPressサイトにアクセスできなくなり、同時にSSH接続もできない状態になった。
当初は、直前に適用した Luxeritas fork版やWordPress側の問題も疑ったが、調査の結果、テーマやWordPressのPHPエラーではなく、Lightsailインスタンスのリソース不足、特に Apache/PHP プロセスのメモリ消費と bot/crawler アクセスが主因と考えられる状態だった。
環境
対象は AWS Lightsail 上の WordPress 環境。
- Lightsail: 512MB RAM / 2 vCPU / 20GB SSD
- OS: Debian系
- Web server: Apache 2.4
- DB: MariaDB 10.11
- WordPress: 6.x 系
- PHP: 8.2 系
- Theme: Luxeritas fork版
- 有効プラグイン: Jetpack, Site Kit, WP-Optimize, Broken Link Checker など
発生した現象
以下のような状態になった。
- WordPressサイトにアクセスできない
- SSHでも接続できない
- OS自体がハングアップしているように見える
- Lightsailコンソールから再起動すると復旧する
- 同様の現象が数日前にも発生していた
HTTPだけでなくSSHもつながらないため、WordPressテーマやプラグイン単体のPHPエラーではなく、OSまたはインスタンス全体のリソース問題を疑った。
再起動後の確認
Lightsailコンソールからインスタンスを再起動し、SSH接続できるようになった後に確認した。
uptime, free -h, df -h, last -x などを確認したところ、ディスク容量には余裕があった。
一方、メモリは以下のようにかなり厳しい状態だった。
Mem: 447Mi
free: 5.7Mi
available: 156Mi
Swap: 2.0Gi
swapは設定済みだったが、512MB RAMのインスタンスとしては余裕がかなり少ない。
カーネルログからは、OOM killer や kernel panic の明確な痕跡は確認できなかった。
sudo journalctl -k -b -1 --no-pager | grep -Ei "oom|out of memory|killed process|blocked|hung|panic|segfault"
この時点では、決定的なOOMは出ていないものの、リソース不足の可能性は残った。
Apache / MariaDB の状況
Apache と MariaDB のログを確認すると、再起動時には正常に停止していた。
apache2.service: Deactivated successfully
mariadb.service: Normal shutdown
つまり、サービスが異常終了したというより、インスタンス再起動に伴って通常停止した形に見える。
MariaDB自体も再起動後は正常に起動しており、ディスク不足もなかった。
アクセスログの確認
Apacheのアクセスログを集計したところ、かなり偏ったアクセスが見つかった。
4735 47.128.115.59
807 103.59.160.151
692 144.172.112.170
...
URL別では、特に以下が目立った。
4866 /robots.txt
784 /wp-login.php
18 /.env
8 /config.yaml
8 /config.json
7 /secret.json
...
/.env, /config.json, /secret.* などへのアクセスは明らかにスキャン系アクセスであり、bot/crawler/攻撃アクセスが多いことが分かった。
特に /robots.txt へのアクセスが非常に多く、これを WordPress/PHP に処理させている場合、不要な負荷になる。
Apacheプロセスのメモリ消費
ps aux --sort=-%mem で確認すると、Apacheの子プロセスが1本あたり 80MB 前後のRSSを使っていた。
www-data apache2 87MB
www-data apache2 87MB
www-data apache2 83MB
www-data apache2 82MB
...
mysql mariadbd 113MB
512MB RAM の環境では、Apache worker が数本立つだけでメモリを大きく消費する。
MariaDBだけで約100MB、Apache workerが複数本で数百MBとなるため、botアクセスが増えるとすぐにメモリが逼迫する構成だった。
この時点で、VMハングの主因は以下と判断した。
512MB RAM
+ Apache/PHP workerのメモリ消費
+ bot/crawlerアクセス
+ WordPressプラグインの定期処理
実施した対策1: Apache worker数の制限
Apacheの prefork 設定を見直し、workerが増えすぎないようにした。
/etc/apache2/mods-available/mpm_prefork.conf を調整し、以下のようにした。
<IfModule mpm_prefork_module>
StartServers 2
MinSpareServers 1
MaxSpareServers 3
MaxRequestWorkers 4
MaxConnectionsPerChild 500
</IfModule>
設定確認後、Apacheを再起動した。
sudo apachectl configtest
sudo systemctl restart apache2
再起動後のメモリ状態は大きく改善した。
変更前は空きメモリがほぼ無い状態だったが、変更後は以下のようになった。
Mem: 447Mi
used: 186Mi
free: 160Mi
available: 261Mi
Swap: 2.0Gi
Apache workerも、再起動直後は約10MB程度のものが2本程度になり、かなり健全になった。
実施した対策2: robots.txt の静的化
/robots.txt へのアクセスが非常に多かったため、WordPressに処理させず、Apacheが静的ファイルとして返すようにした。
sudo tee /var/www/html/robots.txt >/dev/null <<'EOF'
User-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
Sitemap: https://blog2020.iwadjp.com/sitemap.xml
EOF
sudo chown www-data:www-data /var/www/html/robots.txt
sudo chmod 644 /var/www/html/robots.txt
確認すると、robots.txt は 200 OK で静的に返るようになった。
curl -I https://blog2020.iwadjp.com/robots.txt
実施した対策3: debug.log の確認
対策後、WordPressの主要エンドポイントを確認した。
curl -I https://blog2020.iwadjp.com/
curl -I https://blog2020.iwadjp.com/wp-json/
curl -I "https://blog2020.iwadjp.com/?amp=1"
curl -I https://blog2020.iwadjp.com/robots.txt
結果はすべて 200 OK。
その後、debug.log を確認したが、新しいエラーは出ていなかった。
sudo tail -n 100 /var/www/html/wp-content/debug.log
このため、Luxeritas fork版やWordPressテーマ側の問題ではなく、サーバリソース側の問題と判断した。
プラグイン面での対策候補
特に注意すべきプラグインは以下。
- Broken Link Checker
- WP-Optimize
- Jetpack
- Site Kit
- Blog2Social
この中でも、Broken Link Checker はリンクスキャンによって負荷をかけやすいため、WordPress 7.0更新前の安定化期間中はいったん無効化する方針にした。
WP-Optimize はプラグイン自体を止めるのではなく、まずは以下の自動処理を止める方針。
- ページキャッシュ
- 自動DB最適化
- 画像圧縮の自動処理
- 予約クリーンアップ
Jetpack は影響範囲が広いため、すぐに停止するのではなく、不要機能をOFFにする方向で様子を見る。
今回の結論
今回のVMハングは、Luxeritas fork版の適用が直接原因ではなさそう。
主因は以下と考えられる。
512MB RAM の小型Lightsail
+ Apache workerのメモリ消費
+ bot/crawlerアクセス
+ WordPressプラグインの定期処理
Apache worker数の制限と robots.txt の静的化により、メモリ状態は大きく改善した。
今後の方針
当面は以下の方針で運用する。
- Broken Link Checker を一時停止する
- WP-Optimize の自動処理を抑える
- Jetpack は不要機能のみOFFにする
- 1〜2日様子を見る
- 再発しなければ WordPress 7.0-ja 更新へ進む
- 再発する場合は Lightsail を 1GB以上へ変更する
512MB環境でも動かすことは可能だが、WordPress + Apache + MariaDB + 複数プラグイン構成では余裕が小さい。
今回の件で、WordPress更新より先に、サーバリソースとApache設定を見直す重要性を再確認した。