背景
AWS EC2 (Amazon Linux 2023) 上で Apache + PHP-FPM + Laravel を運用している環境で、突如アプリが 503 エラーを多発。サーバログを確認すると OOM Killer が発動し、php-fpm プロセスが強制終了されていました。
OOM発生の確認
まずは journalctl で OOM Killer の発動を確認。
journalctl
sudo journalctl -k -S -2h -r | grep -i -E 'out of memory|oom-kill|killed process' -n -A2 -B2
出力例:
Sep 16 19:00:37 web01 kernel: Out of memory: Killed process 2395225 (php-fpm) total-vm:6829692kB, anon-rss:6224880kB
Sep 16 19:00:37 web01 kernel: oom-kill:constraint=CONSTRAINT_NONE ... task=php-fpm,pid=2395225
→ PHP-FPMの子プロセスが約6GB使用して落ちていることがわかります。
直前の処理を調べる
php-fpm の slow log から該当 PID を検索。
sudo egrep "2395225" /var/log/php-fpm/www-slow.log
抜粋:
script_filename = /var/www/example.com/public/index.php
[0x00007f9874a157b0] readImage() /vendor/spatie/pdf-to-image/src/Pdf.php:166
[0x00007f9874a15690] saveImage() /app/Library/Img.php:135
→ 原因は spatie/pdf-to-image を使った PDF → 画像変換処理。
アクセスログの相関確認
同時刻の Apache アクセスログを確認。
sudo awk -v ts="16/Sep/2025:19:00" '$4 ~ ts {print $7, $9}' /var/log/httpd/example.com-access_log | sort | uniq -c | sort -nr | head -n 30
結果例:
37 /api/monitoring/access_log 200
18 / 302
14 / 503
...
→ PDF変換リクエストが集中し、503エラーも発生していたことが確認できました。
設定を見直したポイント
php-fpm
/etc/php-fpm.d/www.conf
pm = dynamic
pm.max_children = 40
pm.start_servers = 12
pm.min_spare_servers = 8
pm.max_spare_servers = 24
pm.max_requests = 2000
php_admin_value[memory_limit] = 256M
通常のWebリクエスト負荷には対応可能な設定でしたが、大きなPDFを扱う場合は一時的に数百MB〜数GBのメモリを消費するため不十分でした。
Apache (mpm_prefork)
<IfModule mpm_prefork_module>
StartServers 10
ServerLimit 260
MaxRequestWorkers 260
MaxConnectionsPerChild 2000
</IfModule>
Web側の同時処理数も増えており、結果的に「重い処理 × 同時アクセス」でサーバ全体のメモリを食い潰したと考えられます。
今回の原因まとめ
- 通常のリクエストに耐える調整はしていたが、PDF変換処理が想定外に重くメモリを大量消費した
- 複数リクエストが同時実行され、サーバメモリを枯渇 → OOM Killer 発動
- 503エラーが断続的に発生し、サービス影響あり
対策案
- 重い処理を分離
- バッチ処理やキュー (Queue Worker) に回す
- Webリクエストと分離することで影響を局所化
- リクエスト制限
- nginx/Apache の制限や Laravel のジョブ制御で同時変換数を制御
- メモリ監視とアラート
- Datadog や CloudWatch で php-fpm のメモリ利用状況を監視
- max_children reached をトリガーに警告通知
- インスタンスタイプ見直し
- 大容量PDFを扱う前提なら、メモリ多めのインスタンス (例: m5.xlarge, r5.large) も検討
まとめ
- OOM発生時は journalctl → php-fpm slowlog → access_log の順で突き止める
- 通常リクエスト用の設定強化だけでは、特殊処理(PDF変換など)の大規模メモリ消費に対応できない
- 本番運用では「重い処理は分離」「メモリ監視を強化」することが再発防止の鍵