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 の静的化により、メモリ状態は大きく改善した。

今後の方針

当面は以下の方針で運用する。

  1. Broken Link Checker を一時停止する
  2. WP-Optimize の自動処理を抑える
  3. Jetpack は不要機能のみOFFにする
  4. 1〜2日様子を見る
  5. 再発しなければ WordPress 7.0-ja 更新へ進む
  6. 再発する場合は Lightsail を 1GB以上へ変更する

512MB環境でも動かすことは可能だが、WordPress + Apache + MariaDB + 複数プラグイン構成では余裕が小さい。

今回の件で、WordPress更新より先に、サーバリソースとApache設定を見直す重要性を再確認した。

WordPress

Posted by iwadjp